一、深入剖析EventLoop和EventLoopGroup线程模型
-
- 高性能RPC框架的3个要素:IO模型、数据协议、线程模型
- EventLoop好比一个线程,1个EventLoop可以服务多个Channel,1个Channel只有一个EventLoop。可以创建多个 EventLoop 来优化资源利用,也就是EventLoopGroup
- EventLoopGroup 负责分配 EventLoop 到新创建的 Channel,里面包含多个EventLoop
- EventLoopGroup -> 多个 EventLoop ,EventLoop -> 维护一个 Selector
- 学习资料:http://ifeve.com/selectors/
二、Netty启动引导类Bootstrap模块
group :设置线程组模型,Reactor线程模型对比EventLoopGroup
单线程
/** * 启动流程 */ public void run() throws InterruptedException { //配置服务端线程组 两个线程组 EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new EchoServerHandler()); } }); System.out.println("Echo 服务器启动ing"); //绑定端口,同步等待成功 ChannelFuture channelFuture = serverBootstrap.bind(port).sync(); //等待服务端监听端口关闭 channelFuture.channel().closeFuture().sync(); } finally { //优雅退出,释放线程池 workGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } }
关键代码
EventLoopGroup bossGroup = new NioEventLoopGroup(1); serverBootstrap.group(bossGroup)
多线程
/** * 启动流程 */ public void run() throws InterruptedException { //配置服务端线程组 两个线程组 EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup,workGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new EchoServerHandler()); } }); System.out.println("Echo 服务器启动ing"); //绑定端口,同步等待成功 ChannelFuture channelFuture = serverBootstrap.bind(port).sync(); //等待服务端监听端口关闭 channelFuture.channel().closeFuture().sync(); } finally { //优雅退出,释放线程池 workGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } }
关键代码
EventLoopGroup bossGroup = new NioEventLoopGroup(1); serverBootstrap.group(bossGroup,workGroup)
主从线程
/** * 启动流程 */ public void run() throws InterruptedException { //配置服务端线程组 两个线程组 EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup,workGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new EchoServerHandler()); } }); System.out.println("Echo 服务器启动ing"); //绑定端口,同步等待成功 ChannelFuture channelFuture = serverBootstrap.bind(port).sync(); //等待服务端监听端口关闭 channelFuture.channel().closeFuture().sync(); } finally { //优雅退出,释放线程池 workGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } }
关键代码
EventLoopGroup bossGroup = new NioEventLoopGroup(); serverBootstrap.group(bossGroup, workGroup)
参考
点我前往channel:设置channel通道类型NioServerSocketChannel、OioServerSocketChannel
option
- option: 作用于每个新建立的channel,设置TCP连接中的一些参数,如下
- ChannelOption.SO_BACKLOG: 存放已完成三次握手的请求的等待队列的最大长度;
- Linux服务器TCP连接底层知识:
- syn queue:半连接队列,洪水攻击,tcp_max_syn_backlog
- accept queue:全连接队列, net.core.somaxconn
- 系统默认的somaxconn参数要足够大 ,如果backlog比somaxconn大,则会优先用后者 点我前往
- ChannelOption.TCP_NODELAY: 为了解决Nagle的算法问题,默认是false, 要求高实时性,有数据时马上发送,就将该选项设置为true关闭Nagle算法;如果要减少发送次数,就设置为false,会累积一定大小后再发送
- 知识拓展:
- childOption: 作用于被accept之后的连接
- childHandler: 用于对每个通道里面的数据处理
客户端启动引导类Bootstrap
- remoteAddress: 服务端地址
- handler:和服务端通信的处理器
三、Netty核心组件Channel模块
- 什么是Channel: 客户端和服务端建立的一个连接通道
- 什么是ChannelHandler: 负责Channel的逻辑处理
- 什么是ChannelPipeline: 负责管理ChannelHandler的有序容器
- 他们是什么关系:
- 一个Channel包含一个ChannelPipeline,所有ChannelHandler都会顺序加入到ChannelPipeline中 创建Channel时会自动创建一个ChannelPipeline,每个Channel都有一个管理它的pipeline,这关联是永久性的
- Channel当状态出现变化,就会触发对应的事件
- 状态:
- channelRegistered: channel注册到一个EventLoop
- channelActive: 变为活跃状态(连接到了远程主机),可以接受和发送数据
- channelInactive: channel处于非活跃状态,没有连接到远程主机
- channelUnregistered: channel已经创建,但是未注册到一个EventLoop里面,也就是没有和Selector绑定
- 状态:
四、ChannelHandler和ChannelPipeline模块
- 方法:
- handlerAdded : 当 ChannelHandler 添加到 ChannelPipeline 调用
- handlerRemoved : 当 ChannelHandler 从 ChannelPipeline 移除时调用
- exceptionCaught : 执行抛出异常时调用
- ChannelHandler下主要是两个子接口
- ChannelInboundHandler:(入站)
- 处理输入数据和Channel状态类型改变
- 适配器 ChannelInboundHandlerAdapter(适配器设计模式)
- 常用的:SimpleChannelInboundHandler
- ChannelOutboundHandler:(出站)
- 处理输出数据,适配器 ChannelOutboundHandlerAdapter
- ChannelInboundHandler:(入站)
- ChannelPipeline: 好比厂里的流水线一样,可以在上面添加多个ChannelHanler,也可看成是一串 ChannelHandler 实例,拦截穿过 Channel 的输入输出 event, ChannelPipeline 实现了拦截器的一种高级形式,使得用户可以对事件的处理以及ChannelHanler之间交互获得完全的控制权
本文作者为DBC,转载请注明。