• Netty源码学习(一)Netty线程模型


    给你一台4路E7-4820V2(32核心64线程),512G内存的服务器,你该如何编程才能支持百万长连接?

    最直接的想法是采用BIO的模式,为每个连接新建一个线程,在一一对应的线程中直接处理连接上的数据请求。

    但在Java中,新建线程的开销非常昂贵(默认情况下每个线程会占据1M多的内存,百万连接就是1T内存,这显然是不可接受的)

    优化点的想法是使用Java NIO,用一个线程来处理所有客户端的请求。

    但是根据我之前的测试,单个线程最多同时处理5w/s的echo message,此时单个core已经跑满,如果再接着加大负载会导致请求堆积。

    进一步的优化是将线程分离,使用一个线程作为acceptor,一堆线程作为worker

    acceptor监听服务端口的accept事件,如果有accept事件被触发,说明有客户端连接进来,acceptor获取连接(Channel)并将其分派给某个worker,worker监听这个Channel的read事件,一旦Channel可读,worker就会做出相应的处理。

    也就是说将连接均分到各个worker,减轻压力,也可以让多个core被利用起来,使单机处理百万长连接成为可能。

    这就是所谓Reactor模型了,也是Netty所采用的线程模型。(还有更进一步的主从多线程模型,用于处理认证较为耗时的情况,这里不做介绍)

    借用一下Doug Lea老爷子的示例图:

    用这个思想分析一下Netty的示例代码:

        public void go(int port) {
            EventLoopGroup bossGroup = new NioEventLoopGroup(1);//acceptor线程
            EventLoopGroup workerGroup = new NioEventLoopGroup();//worker线程组
            try {
                ServerBootstrap b = new ServerBootstrap();
                b.group(bossGroup, workerGroup)
                        .channel(NioServerSocketChannel.class)
                        .childHandler(new ChannelInitializer<SocketChannel>() {
                            @Override
                            public void initChannel(SocketChannel ch) throws Exception {
                                ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                                    @Override
                                    public void channelRead(ChannelHandlerContext ctx,
                                            Object msg) { //ehco to client
                                        ctx.write(msg);
                                        ctx.flush();
                                    }
                                });
                            }
                        })
                        .option(ChannelOption.SO_BACKLOG, 128)
                        .childOption(ChannelOption.SO_KEEPALIVE, true);
                
                ChannelFuture f = b.bind(port).sync();
                f.channel().closeFuture().sync();
            } catch (Exception e) {
            } finally {
                workerGroup.shutdownGracefully();
                bossGroup.shutdownGracefully();
            }
        }

    可以猜出所谓的bossGroup就是Reactor模型中的acceptor,负责处理客户端产生的TCP连接请求,workerGroup则是worker,真正负责IO读写操作。具体实现我们后续再做分析。

  • 相关阅读:
    如何把SQLServer数据库从高版本降级到低版本
    关于如何利用Pocket CHM Pro制作帮助文档
    关于ASP.net TextBox控件的失去焦点后触发其它事件
    由window.history.back()引发的问题
    设置按钮不可用避免重复提交
    【转】一个高端.NET技术人才的2014年度总结
    Zabbix 各种报错信息和遇到的问题处理(持续总结更新~~~~~)
    ASP.NET调用Web Service
    ASP.NET导出bdf文件
    CS文件密码加密类
  • 原文地址:https://www.cnblogs.com/stevenczp/p/7577004.html
Copyright © 2020-2023  润新知