30.Netty源码服务端启动主要流程

2023年 8月 16日 88.7k 0

服务端启动主要流程

•创建 selector

•创建 server socket channel

•初始化 server socket channel

•给 server socket channel 从 boss group 中选择一个 NioEventLoop

•将 server socket channel 注册到选择的 NioEventLoop 的 selector

•绑定地址启动

•注册接受连接事件(OP_ACCEPT)到 selector上

从Echo服务器示例入手

在《引导器作用:客户端和服务端启动都要做些什么?》的课程中,我们介绍了如何使用引导器搭建服务端的基本框架。在这里我们实现了一个最简单的 Echo 服务器,用于调试 Netty 服务端启动的源码。

public class EchoServer {
    public void startEchoServer(int port) throws Exception {
        //默认会创建 cpu核心数*2 个 NioEventLoop
        //创建NioEventLoop 会调用openSelector 创建一个Selector
        //将创建的Selector赋值给NioEventLoop的selector属性
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer() {
                        @Override
                        public void initChannel(SocketChannel ch) {
                            ch.pipeline().addLast
                                            (new FixedLengthFrameDecoder(10));
                            ch.pipeline().addLast(new ResponseSampleEncoder());
                            ch.pipeline().addLast(new RequestSampleHandler());
                        }
                    });
            //同步阻塞
            ChannelFuture f = b.bind(port).sync();
            f.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
    public static void main(String[] args) throws Exception {
        new EchoServer().startEchoServer(8088);
    }
}
​
public class ResponseSampleEncoder extends MessageToByteEncoder {
    @Override
    protected void encode(ChannelHandlerContext ctx, ResponseSample msg, ByteBuf out) {
​
        if (msg != null) {
            out.writeBytes(msg.getCode().getBytes());
            out.writeBytes(msg.getData().getBytes());
            out.writeLong(msg.getTimestamp());
        }
    }
}
​
public class RequestSampleHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        String data = ((ByteBuf) msg).toString(CharsetUtil.UTF_8);
        ResponseSample response = new ResponseSample("OK", data,    
                                                     System.currentTimeMillis());
        ctx.channel().writeAndFlush(response);
    }
}
​
我们以引导器 ServerBootstrap 为切入点,开始深入分析 Netty 服务端的启动流程。在服务端启动之前,需要配置 ServerBootstrap 的相关参数,这一步大致可以分为以下几个步骤:

配置 EventLoopGroup 线程组;

配置 Channel 的类型;

设置初始化Handler;

设置网络监听的端口;

设置处理Handler;

配置 Channel 参数。

配置 ServerBootstrap 参数的过程非常简单,把参数值保存在 ServerBootstrap 定义的成员变量里就可以了。我们可以看下 ServerBootstrap 的成员变量定义,基本与 ServerBootstrap 暴露出来的配置方法是一一对应的。如下所示,我以注释的形式说明每个成员变量对应的调用方法。

volatile EventLoopGroup group; // group()
volatile EventLoopGroup childGroup; // group()
volatile ChannelFactory, Object> childOptions = new ConcurrentHashMap, Object>[] currentChildOptions =
childOptions.entrySet().toArray(newOptionArray(0));
final Entry, Object>[] currentChildOptions =
childOptions.entrySet().toArray(newOptionArray(0));
final Entry

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论