Netty

Netty和Tomcat最大的区别就在于通信协议,Tomcat是基于Http协议的,他的实质是一个基于http协议的web容器,但是Netty不一样,他能通过编程自定义各种协议,因为netty能够通过codec自己来编码/解码字节流,完成类似redis访问的功能,这就是netty和tomcat最大的不同。

Netty 的整体流程

流程可以分为服务启动、建立连接、读取数据、业务处理、发送数据、关闭连接以及关闭服务。

服务启动

  1. EchoServer#new NioEventLoopGroup(1)->NioEventLoop#provider.openSelector() : 创建 selector
  2. EchoServer#b.bind(PORT).sync->AbstractBootStrap#doBind()->initAndRegister()-> channelFactory.newChannel() / init(channel) : 创建 serverSocketChannel 以及初始化
  3. EchoServer#b.bind(PORT).sync->AbstractBootStrap#doBind()->initAndRegister()-> config().group().register(channel) :从 boss group 中选择一个 NioEventLoop 开始注册 serverSocketChannel
  4. EchoServer#b.bind(PORT).sync->AbstractBootStrap#doBind()->initAndRegister()->config().group().register(channel)->AbstractChannel#register0(promise)->AbstractNioChannel#javaChannel().register(eventLoop().unwrappedSelector(), 0, this) : 将 server socket channel 注册到选择的 NioEventLoop 的 selector
  5. EchoServer#b.bind(PORT).sync()->AbstractBootStrap#doBind()->doBind0()->AbstractChannel#doBind(localAddress)->NioServerSocketChannel#javaChannel().bind(localAddress, config.getBacklog()) : 绑定地址端口开始启动
  6. EchoServer#b.bind(PORT).sync()->AbstractBootStrap#doBind()->doBind0()->AbstractChannel#pipeline.fireChannelActive()->AbstractNioChannel#selectionKey.interestOps(interestOps|readInterestOp): 注册 OP_READ 事件

建立连接

服务启动后便是建立连接的过程了,相应过程及源码类如下:

  1. NioEventLoop#run()->processSelectedKey() NioEventLoop 中的 selector 轮询创建连接事件(OP_ACCEPT)
  2. NioEventLoop#run()->processSelectedKey()->AbstractNioMessageChannel#read->NioServerSocketChannel#doReadMessages()->SocketUtil#accept(serverSocketChannel) 创建 socket channel
  3. NioEventLoop#run()->processSelectedKey()->AbstractNioMessageChannel#fireChannelRead->ServerBootstrap#ServerBootstrapAcceptor#channelRead-> childGroup.register(child) 从worker group 中选择一个 NioEventLoop 开始注册 socket channel
  4. NioEventLoop#run()->processSelectedKey()->AbstractNioMessageChannel#fireChannelRead->ServerBootstrap#ServerBootstrapAcceptor#channelRead-> childGroup.register(child)->AbstractChannel#register0(promise)-> AbstractNioChannel#javaChannel().register(eventLoop().unwrappedSelector(), 0, this) 将 socket channel 注册到选择的 NioEventLoop 的 selector
  5. NioEventLoop#run()->processSelectedKey()->AbstractNioMessageChannel#fireChannelRead->ServerBootstrap#ServerBootstrapAcceptor#channelRead-> childGroup.register(child)->AbstractChannel#pipeline.fireChannelActive()-> AbstractNioChannel#selectionKey.interestOps(interestOps | readInterestOp) 注册 OP_ACCEPT 事件

读写与业务处理

  1. NioEventLoop#run()->processSelectedKey() NioEventLoop 中的 selector 轮询创建读取事件(OP_READ)
  2. NioEventLoop#run()->processSelectedKey()->AbstractNioByteChannel#read()nioSocketChannel 开始读取数据
  3. NioEventLoop#run()->processSelectedKey()->AbstractNioByteChannel#read()->pipeline.fireChannelRead(byteBuf)把读取到的数据传播出去供业务处理
  4. AbstractNioByteChannel#pipeline.fireChannelRead->EchoServerHandler#channelRead在这个例子中即 EchoServerHandler 的执行
  5. EchoServerHandler#write->ChannelOutboundBuffer#addMessage 调用 write 方法
  6. EchoServerHandler#flush->ChannelOutboundBuffer#addFlush 调用 flush 准备数据
  7. EchoServerHandler#flush->NioSocketChannel#doWrite 调用 flush 发送数据

关闭连接

  1. NioEventLoop#run()->processSelectedKey() NioEventLoop 中的 selector 轮询创建读取事件(OP_READ),这里关闭连接仍然是读取事件
  2. NioEventLoop#run()->processSelectedKey()->AbstractNioByteChannel#read()->closeOnRead(pipeline)当字节<0 时开始执行关闭 nioSocketChannel
  3. NioEventLoop#run()->processSelectedKey()->AbstractNioByteChannel#read()->closeOnRead(pipeline)->AbstractChannel#close->AbstractNioChannel#doClose() 关闭 socketChannel
  4. NioEventLoop#run()->processSelectedKey()->AbstractNioByteChannel#read()->closeOnRead(pipeline)->AbstractChannel#close->outboundBuffer.failFlushed/close 清理消息:不接受新信息,fail 掉所有 queue 中消息
  5. NioEventLoop#run()->processSelectedKey()->AbstractNioByteChannel#read()->closeOnRead(pipeline)->AbstractChannel#close->fireChannelInactiveAndDeregister->AbstractNioChannel#doDeregister eventLoop().cancel(selectionKey()) 关闭多路复用器的 key

原文地址:https://www.cnblogs.com/KL2016/p/14861947.html