1、Netty这个词,对于熟悉并发的童鞋一点都不陌生,它是一个异步事件驱动型的网络通信框架;
2、使用Netty不需要我们关注过多NIO的API操作,简简单单的使用即可,非常方便,开发门槛较低;
3、而且Netty也经历了各大著名框架的“摧残”,足以证明其性能高,稳定性高;
4、那么本章节就来和大家分享分析一下Netty的服务端启动流程,分析Netty的源码版本为:netty-netty-4.1.22.Final;

二、简单认识Netty

2.1 何为Netty?

1、是一个基于NIO的客户端、服务器端的网络通信框架;

2、是一个以提供异步的、事件驱动型的网络应用工具;

3、可以供我们快速开发高性能的、高可靠性的网络服务器与客户端;

2.2 为什么使用Netty?

1、开箱即用,简单操作,开发门槛低,API简单,只需关注业务实现即可,不用关心如何编写NIO;

2、自带多种协议栈且预置多种编解码功能,且定制化能力强;

3、综合性能高,已历经各大著名框架(RPC框架、消息中间件)等广泛验证,健壮性非常强大;

4、相对于JDK的NIO来说,netty在底层做了很多优化,将reactor线程的并发处理提到了极致;

5、社区相对较活跃,遇到问题可以随时提问沟通并修复;

2.3 大致阐述启动流程

1、创建两个线程管理组,一个是bossGroup,一个是workerGroup,每个Group下都有一个线程组children[i]来执行任务;

2、bossGroup专门用来揽客的,就是接收客户端的请求链接,而workerGroup专门用来干事的,bossGroup揽客完了就交给workerGroup去干活了;

3、通过bind轻松的一句代码绑定注册,其实里面一点都不简单,一堆堆的操作;

4、创建NioServerSocketChannel,并且将此注册到bossGroup的子线程中的多路复用器上;

5、最后一步就是将NioServerSocketChannel绑定到指定ip、port即可,由此完成服务端的整个启动过程;

2.4 Netty服务端启动Demo

/**
 * Netty服务端启动代码。
 *
 * @author hmilyylimh
 *
 * @version 0.0.1
 *
 * @date 2018/3/25
 *
 */
public class NettyServer {

    public static final int TCP_PORT = 20000;

    private final int port;

    public NettyServer(int port) {
        this.port = port;
    }

    public void start() throws Exception {
        EventLoopGroup bossGroup = null;
        EventLoopGroup workerGroup = null;
        try {
            // Server 端引导类
            ServerBootstrap serverBootstrap = new ServerBootstrap();

            // Boss 线程管理组
            bossGroup = new NioEventLoopGroup(1);

            // Worker 线程管理组
            workerGroup = new NioEventLoopGroup();

            // 将 Boss、Worker 设置到 ServerBootstrap 服务端引导类中
            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    // 指定通道类型为NioServerSocketChannel,一种异步模式,OIO阻塞模式为OioServerSocketChannel
                    .localAddress("localhost", port)//设置InetSocketAddress让服务器监听某个端口已等待客户端连接。
                    .childHandler(new ChannelInitializer<Channel>() {//设置childHandler执行所有的连接请求
                        @Override
                        protected void initChannel(Channel ch) throws Exception {
                            ch.pipeline().addLast(new PacketHeadDecoder());
                            ch.pipeline().addLast(new PacketBodyDecoder());

                            ch.pipeline().addLast(new PacketHeadEncoder());
                            ch.pipeline().addLast(new PacketBodyEncoder());

                            ch.pipeline().addLast(new PacketHandler());
                        }
                    });
            // 最后绑定服务器等待直到绑定完成,调用sync()方法会阻塞直到服务器完成绑定,然后服务器等待通道关闭,因为使用sync(),所以关闭操作也会被阻塞。
            ChannelFuture channelFuture = serverBootstrap.bind().sync();
            System.out.println("Server started,port:" + channelFuture.channel().localAddress());
            channelFuture.channel().closeFuture().sync();
        } finally {
            // Shut down all event loops to terminate all threads.
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        new NettyServer(TCP_PORT).start();
    }
}

三、常用的类结构

原理剖析-Netty之服务端启动工作原理分析(上)

四、源码分析Netty服务端启动

4.1、创建bossGroup对象

1、源码:
	// NettyServer.java, Boss 线程管理组, 上面NettyServer.java中的示例代码
	bossGroup = new NioEventLoopGroup(1);

	// NioEventLoopGroup.java
    /**
     * Create a new instance using the specified number of threads, {@link ThreadFactory} and the
     * {@link SelectorProvider} which is returned by {@link SelectorProvider#provider()}.
     */
    public NioEventLoopGroup(int nThreads) {
        this(nThreads, (Executor) null);
    }	
	
	// NioEventLoopGroup.java
    public NioEventLoopGroup(int nThreads, Executor executor) {
        this(nThreads, executor, SelectorProvider.provider());
    }	
	
	// NioEventLoopGroup.java
    public NioEventLoopGroup(
            int nThreads, Executor executor, final SelectorProvider selectorProvider) {
        this(nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE);
    }	
	
	// NioEventLoopGroup.java
    public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider,
                             final SelectStrategyFactory selectStrategyFactory) {
        super(nThreads, executor, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject());
    }	
	
	// MultithreadEventLoopGroup.java
    /**
     * @see MultithreadEventExecutorGroup#MultithreadEventExecutorGroup(int, Executor, Object...)
     */
    protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
        // DEFAULT_EVENT_LOOP_THREADS 默认为CPU核数的2倍
        super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
    }	
	
	// MultithreadEventExecutorGroup.java
    /**
     * Create a new instance.
     *
     * @param nThreads          the number of threads that will be used by this instance.
     * @param executor          the Executor to use, or {@code null} if the default should be used.
     * @param args              arguments which will passed to each {@link #newChild(Executor, Object...)} call
     */
    protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {
        this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, args);
    }	
	
	// MultithreadEventExecutorGroup.java
    /**
     * Create a new instance.
     *
     * @param nThreads          the number of threads that will be used by this instance.
     * @param executor          the Executor to use, or {@code null} if the default should be used.
     * @param chooserFactory    the {@link EventExecutorChooserFactory} to use.
     * @param args              arguments which will passed to each {@link #newChild(Executor, Object...)} call
     */
    protected 

相关文章: