前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Netty服务端是如何一点一点被带动起来的(概略)

Netty服务端是如何一点一点被带动起来的(概略)

作者头像
书唐瑞
发布2022-06-02 14:13:05
2030
发布2022-06-02 14:13:05
举报
文章被收录于专栏:Netty历险记
代码语言:javascript
复制
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

public class Server {
    public static void main(String[] args) throws Exception {

        // 这个线程用于接收客户端的连接
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        // 这4个线程用于处理IO读写
        EventLoopGroup workerGroup = new NioEventLoopGroup(8);
        // 这8个线程用于业务处理
        EventLoopGroup businessGroup = new NioEventLoopGroup(8);

        ServerBootstrap serverBootstrap = new ServerBootstrap();
        try {
            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel ch) {
                            ChannelPipeline channelPipeline = ch.pipeline();
                            channelPipeline.addLast(new StringEncoder());
                            channelPipeline.addLast(new StringDecoder());
                            channelPipeline.addLast(businessGroup, new ServerInHandler());
                        }
                    });

            // bind绑定
            ChannelFuture channelFuture = serverBootstrap.bind("127.0.0.1", 8080).sync();
            channelFuture.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

以上代码虽不能作为真正的服务端生产代码, 麻雀虽小五脏俱全, 它足以可以说明本篇所要阐述的过程.

Netty服务端启动的导火索就从这个bind方法开始了.

首先要说明一点的是,NioServerSocketChannel它会经历创建-初始化-注册-绑定这4大过程.

NioEventLoop它会经历创建-启动-执行这3大过程.

这4+3=7个过程完成之后, 服务端也就启动起来了.

在执行bind方法之前, NioEventLoop已经完成了创建. (已经执行过的使用绿色表示). 它是通过

代码语言:javascript
复制
EventLoopGroup bossGroup = new NioEventLoopGroup(1);

被创建的.

NioEventLoop要想启动起来, 是由NioServerSocketChannel在注册的时候被启动起来的.

在执行bind方法的过程中, 首先会来到第一个重要的地方, 那就是创建NioServerSocketChannel.

源码位置: io.netty.bootstrap.AbstractBootstrap#initAndRegister

在创建的过程, 主要创建了以下几个属性

id,unsafe,pipeline,config等.

接下来就是初始化操作,这里面有个比较重要的操作

到目前为止,内存里有以下几个主要类

继续看重要的NioServerSocketChannel的注册功能

这个时候, NioEventLoop里就有了一个与之绑定的唯一线程, 同时队列里面有个注册任务. Thread就会取出注册任务并执行.

这个注册任务会走到如下地方

目前阶段会形成如下结构

注册完成之后,接下来就是绑定操作.

总之一句话, 注册操作要在绑定操作之前, 绑定操作必须在后面.

绑定完成之后,会'激活'NioServerSocketChannel的ACCEPT事件,就可以接收客户端的请求了.

最后的结构图,请再熟悉下

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Netty历险记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档