我准备战斗到最后,不是因为我勇敢,是我想见证一切。 --双雪涛《猎人》
我准备战斗到最后,不是因为我勇敢,是我想见证一切。 --双雪涛《猎人》
1、netty的两大线程组
ServerBootstrap的初始化
核心操作Bind方法源码解析
大致梳理一下netty的线程模型
❝❞
一个技术,为什么要用它,解决了那些问题? 如果不用会怎么样,有没有其它的解决方法? 对比其它的解决方案,为什么最终选择了这种,都有何利弊? 你觉得项目中还有那些地方可以用到,如果用了会带来那些问题? 这些问题你又如何去解决的呢?
「本文基于Netty 4.1.45.Final-SNAPSHOT」
先来一张Doug lea
的Reactor架构图

在研究源码之前,先脸熟一下netty底层的reactor架构图

1、netty的两大线程组
在架构图中,可以看到netty是基于reactor模式的一套高性能主从架构。用来支持单机可达到百万连接。现在我们来重点看一下,在Reactor模型中,最主要的角色Reactor
。
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
// 创建两个线程组
###EventLoopGroup的初始化
整体的线程组的源码初始化逻辑如下图

整个源码都可以看出netty在设计上的精髓之处,并且底层都是凌驾于java NIO的封装。
ServerBootstrap的初始化
在初始化两个线程组之后,netty的模板代码都是会将两个线程组给赋值到ServerBootstrap
对象中。具体来看看整个赋值逻辑
ServerBootstrap bootstrap = new ServerBootstrap();
// 使用链式编程来配置参数
bootstrap.group(bossGroup, workerGroup) //设置两个线程组
// 使用NioServerSocketChannel作为服务器的通道实现
.channel(NioServerSocketChannel.class)
初始化服务器连接队列大小,服务端处理客户端连接请求是顺序处理的,所以同一时间只能处理一个客户端连接。
多个客户端同时来的时候,服务端将不能处理的客户端连接请求放在队列中等待处理
.option(ChannelOption.SO_BACKLOG, 1024)
.childHandler(new ChannelInitializer<SocketChannel>() {//创建通道初始化对象,设置初始化参数,在 SocketChannel 建立起来之前执行
@Override
protected void initChannel(SocketChannel ch) throws Exception {
//对workerGroup的SocketChannel设置处理器
ch.pipeline().addLast(new NettyServerHandler());
}
});

核心操作Bind方法源码解析
// 绑定一个端口并且同步, 生成了一个ChannelFuture异步对象,通过isDone()等方法可以判断异步事件的执行情况
// 启动服务器(并绑定端口),bind是异步操作,sync方法是等待异步操作执行完毕
ChannelFuture cf = bootstrap.bind(9000).sync();

❝整个netty 中服务端bind 出发,到客户端连接事件的触发,整体流程图如上(画了两天!!!我吐了)
❞
从整个源码中可以梳理出,netty的设计精髓,通过pipeline管道的方式,完美的呈现了事件驱动,又充分利用了线程池异步执行,实现了将NIO从同步非阻塞转换为异步非阻塞的通讯模型。
大致梳理一下netty的线程模型

❝这里可以看出,netty在底层透彻的贯穿了reactor模式,使用主从架构的reactor来实现单机百万连接!牛
❞
❝本文仅供笔者本人学习,有错误的地方还望指出,一起进步!望海涵!
「转载请注明出处!」
欢迎关注我的公共号,无广告,不打扰。不定时更新Java后端知识,我们一起超神。
——努力努力再努力xLg
加油!
❞
文章转载自努力努力再努力xLg,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。





