1、netty客户端与服务端的通信流程image.png

  1. new ServerBootstrap()
  2. .group(new NioEventLoopGroup())
  3. .channel(NioServerSocketChannel.class)
  4. // 添加一个channel初始化handle,handle就是一道一道的工序,来处理传输到服务端的数据,他们都是按循序执行的,并且是交给nioevent中的线程来执行
  5. .childHandler(new ChannelInitializer<NioSocketChannel>() {
  6. @Override
  7. protected void initChannel(NioSocketChannel ch) throws Exception {
  8. // pipeline是channel的一个属性,他可以绑定很多的handle.
  9. ch.pipeline().addLast(new StringDecoder());
  10. ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){
  11. @Override
  12. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  13. log.info(msg.toString());
  14. }
  15. });
  16. // 这两个handle都是由nio线程来执行的,如果有些handle比较耗费时间,那么此时我们可以创建defaulEventLoopGroup来执行handle的任务,只需要在匿名类中指定一个默认事件循环组,不然会影响io线程处理读写事件的性能,并且handle执行链不是由相同的线程执行的话,还需要额外添加一行代码。
  17. }
  18. })
  19. .bind(8085)
  20. .sync();

image.png

serversocketchannel可以有两个时间循环组,一个BossEventLoop一个WorkEventLoop。
其实BossEventLoop只关注Accept事件,Work只关心读和写的事件。
他们都会轮询,模型是reactor的主从多线程模式,但是netty在此基础改进了,也可以有多个线程来处理accept事件,然后会建立起socket连接,当发生读写事件时,此时就交给Work组的线程去完成。

handle如果调用链不属于同一个线程,那么则会通过判断下一个handle所属的eventloop和当前线程是否是同一个线程,来决定是当前线程执行还是用下一个handle来提交一个任务,让别的线程执行。
这样做的目的是?

image.png

image.png
带有Future、Promise的类型都是异步方法配套使用,异步方法的调用者并不关心其运行结果,就以客户端的建立链接的connect()方法为例,这是一个异步方法,是由main线程发起调用的,但是建议socket连接本身就需要花费不少时间,所以当主线程调用到channel的方法时,此时的channel还有没有与服务端建立链接,所以无论怎么调用服务端都不会收到数据,调用sync()会阻塞住当前线程,直到nio线程的connect连接建立。

image.png
netty为什么要用异步的方式去处理建立连接,优雅的释放资源,关闭链接呢?

2、