java 事件驱动 netty_Netty4 SEDA 事件驱动原理分析

Netty4 SEDA事件驱动原理分析

的事件处理线程(AioEventLoop)建立过程分析

(Bootstrap启动ServerSocketChannel处理线程的过程分析)

1:AbstractBootstrap.initAndRegister(): 向BossGroup(AioEventLoopGroup)

注册初始化后的AioServerSocketChannel,

6b3f061dad48c319d1239bf548e7a89d.png

2,调用MultithreadEventExecutorGroup.next()方法,在BossGroup中取出一个可用的EventLoop

e924f9dc5b3231eec6ba69747f6f61e0.png

3, 返回到MultithreadEventLoopGroup.register(Channel channel, ChannelPromise promise)方法,

将AioServerSocketChannel注册到(2)从BossGroup中取出的那个EventLoop.

1b0da6fea9a87fa4978676afebea59d6.png

4,进入到AioEventLoop.register(Channel channel, ChannelPromise future)方法

AioEventLoop实现了JDK的ScheduledExecutorService,持有一条线程,具备任务执行能力,

将AioServerSocketChannel测试到AioEventLoop后,由AioEventLoop执行ServerSocketChannel的accept新的socket的操作

0fd7d62b46233bc90b6c834523e33def.png

5,进入到AbstractChannel.AbstractUnsafe.register(EventLoop eventLoop, ChannelPromise promise)方法,

b524042e2e781d87591f604a65458c30.png

6)进入到SingleThreadEventExecutor.execute(Runnable task)方法,执行startThread()后,AioServerSocketChannel的事件处理线程(AioEventLoop)启动,将由它来接管AioServerSocketChanel的事件处理(如Accept新的Socket),然后ServerBootstrap线程就进入等待状态,等待ServerSocketChannel绑定端口,然后等待ServerSocketChannel关闭.

3be20410b814f01f47c07e4ce0662995.png

7)先看下面

286ad28073b961690199eac5c1a760bd.png

90e52d2dd720c4e9e280c1372b3f871b.png

8)AioServerSocketChannel的事件处理线程AioEventLoop从一个BlockingDeque里取出新任务,取出的第一个任务是给AioServerSocketChannel注册JDK的AsynchronousServerSocketChannel(这才是真正和底层操作系统通信的ServerSocketChannel)

63742c6f09948867dc2709cb7b78001f.png

注册了:

9ad4c41bfb5f9b73582b44d147ed5055.png

9)Channel成功注册后,调用其pipeline.fireChannelRegistered()方法Fire这个channel注册的事件

552a4534ef8fdb9a60da227c5ff30567.png

10)ChannelPipeline的fireChannelRegistered方法先初始化 其处理器链的第一个元素HeadHandler,然后再执行HeadHandler的fireChannelRegistered()方法

8da5e6c111e1fa2624a214f1f6beb29e.png

DefaultChannelHandlerContext.fireChannelRegistered(),Netty4 的DefaultChannelHandlerContext对ChannelInboundInvoker接口的的事件处理方法fireXxxx(),具有链式传递效应,顺序将同一方向上的所有事件

8538c132017266139b42c6d4faae903f.png

d27bcf5dc18d3a2c15c33f87c76246c5.png

4caaa38b7987fc8237addfbc11da46d9.png

11)然后, AioServerSocketChanel的pipeline的处理器链上的ChannelInitializer响应channelRegistered事件: 给pipeline安装上Acceptor,使得AioServerSocketChanel得以具备处理socket Accept事件的能力.

a63c57d37fad8608323b2348d71e716d.png

12) AioServerSocketChanel将accept委托给JDK的异步ServerSocketChannel来执行异步accept,并指定了事件处理器,当ACCEPT事件发生的时候, AcceptHandler就会被调用

39caea8ec551e8d90f0d5ce9e9376ba3.png

然后AioServerSocketChanel的AioEventLoop就进入等待状态,等待taskQueue有任务到来

当相应事件发生时,JDK的CompletionHandler.complted(..)方法会被一条后台Daemon的线程调用 :

1e8412918ba393cc26b3d5404dc22a4d.png

b35674a1d2e765f47c73b9d40f9e5ffb.png

ec09dbe7f1fa24ff41891c8d4e7d9899.png

将接收到的SocketChannel包装成AioSocketChannel作为一个Message写进AioServerSocketChannel的ChannelPipeline的inboundMessageBuffer,然后Fire 相关事件inboundBufferUpdated事件

14)AioServerSocketChannel的ChannelPipeline Fire inboundBufferUpdated事件

c5ecbe18b0b5f89764acc4722717d409.png

15)沿inbound方向找到了SererBootstrapAcceptor的ChannelHandlerContext

edf9e284ec3ea49ce8150168ef1412d0.png

16)inboundBufferUpdate事件传递到ServerBootstrapAcceptor

ac41f05cdc4290ca2036a775bebd1270.png

17) DefaultChannelHandlerContext.invokeInboundBufferUpdated(),调用Acceptor的inboundBufferUpdated方法

8103be9fb6bf564ed1a99235ddf0f36c.png

18)Acceptor取得AioSocketChannel,并向其添加ChannelInitializer

501d520b22b23b88c70200d384673d73.png

19)向ChildGroup注册AioSocketChannel

47c30f44d0ad8b2a5156abc94f5d10f4.png

20)将AioSocketChannel注册到AioEventLoopGroup分配的AioEventLoop上

007ca78451346e70e13493b2b2340493.png

21)BOSS线程(AioServerSocketChannel所属的线程)启动AioSocketChannel所属的AioEventLoop线程,BOSS线程的Accept工作也至此结束,然后就去回去处理其taskQueue中的任务,或进入wait状态,等待下一个Accept事件的发生.

57b86c14db14a61ffa09a0252483ff84.png

    Worker线程线程的初始化

22)Worker线程(AioSocketChannel所属的AioEventLoop)独立运行后,取出其taskQueue中的第一个任务: 通过AioSocketChannel的ChannelPipeline触发pipeline的ChannelHandlerContext处理器链的channelRegistered注册事件

c146eec18e0463826837ec9efe905f7b.png

23)初始化ByteHeadHandler(ChannelOutboundHandler的子类),给它分配outByteBuf和outMsgBuf

f697adc660f3d5fd1a796f9c313deeca.png

24)触发处理器链的下一节点的channelRegistered事件

2f7e5101e640aacdcec3f13255aad214.png

25)沿ChannelHandlerContext处理器链找到了自己定义 的用户AioSocketChannel初始化的HttpSnoopServerInitializer

4ec06c42038a86799c84e4a505fa0461.png

26)ChannelInitializer是利用channelRegistered事件来初始化pipeline,向其安装相关channelHandler

26d687fa9ebfbf2f78f2e5825b9a022f.png

27)从pipeline的处理器链删除初始化器,并触发下一处理器的channelRegistered事件

8fabd4069723d9a76338c42daa751d61.png

28) channelRegistered事件通过一个一个ChannelHandlerContext的fireChannelRegistered方法沿ByteHeadHandler传递到TailHandler,然后事件就停止传播

afa116f84ed15d43897da06d325cc705.png

29)ChannelPipeline完成channelRegistered的事件触发后,就触发channelActive事件,

然后channelActive事件就随着ChannelHandlerContext和链式调用而在处理器链中传递,原理上上面差不多,故不详细说.

da10f7f56e52b94e72563d3bf6ce6b3e.png

30)AioSocketChannel读取数据

738cf79b07dcfc8a89e9945eb27a9129.png

由pipeline来读取数据

08f585e771f8dd82f79328a8060963d7.png

到TailHandler读取数据

5e65fced9604321499750c1ca39412b3.png

31)向outbound方向上寻找最近的ChannelOperationHandler,委托它进行数据读取

570b3d5c1bada13f83084945a3f2a24e.png

首先委托给HttpResponseEncoder读取

73c6d64ee62b8990b46c2027469f3e19.png

HttpRequestDecoder委托给下一个ChannelOperationHandler读取

54483865ff2d0d2ecb158f7761581c93.png

最终委托给ByteHeadHandler读取

247dd2d5133e8d532f0e6b8daba1ef4e.png

32)最终由AioSocketChannel通过JDK的AsynchronousSocketChannel从底层读取

47590a46af1410fd4442918ea6628cba.png

33)AioSocketChannel将读取数据操作委托给JDK的AsynchronousSocketChannel来完成,AioSocketChannel的当前线程不会被阻塞,立马返回处理taskQueue中下一任务或没任务时进入wait等待BlockingQueue的状态.

AsynchronousSocketChannel的read操作完成后会被一条后台Daemon线程调用

c212cc1520fbf4c971c835200d77fe94.png

34)ReadHandler的执行从Daemon线程转移回AioSocketChannle所属的AioEventLoop线程来执行

9f19db946413a1fa34bf713c19b7bfb4.png

35)由AioEventLoop执行ReadHandler

a6e4993d38aa4907a2bc4d5c0df2b575.png

36)数据已准备好,pipeline触发inboundBufferUpdated方法,然后pipeline中处理器链的inbound方向上的ChannelStateHandler的inboundBufferUpdated方法会被顺度调用

1e1400c5277d1ec0069cca6d651744ca.png

37)head 触发处理器链上inbound方向上的stateHandler的inboudBufferUpdated方法的顺序调用

34dee28c4beddd35d46248f2a5050452.png

38) 处理器链上inbound方向上的stateHandler的inboudBufferUpdated方法的顺序调用

39)输入数据: DefaultChannelHandlerContext.flush(ChannelPromise promise)

b216a1b53180ef52f05b57f7fd30ccf0.png

40)由HttpServerCodec中的HttpResponseEncoder将HttpMessage 转换为ByteBuf

DefaultChannelHandlerContext.invokeFlush0(ChannelPromise promise)

48fafed1c83a275917054e960c6ac572.png

41)由Pipeline的ByteHeadHandler将ByteBuf  flush出去

a0d323b9bfd1a8da05670a986167e1f0.png

42)AioSocketChannel将Flush操作委托给JDK AsyncounsSocketChannel异步进行,最终结果等写操作完成后由后台Deamon线程通知并执行WriteHandler.

而AioEventLoop线程是马上返回的,不会被write操作阻塞,然后继续执行taskQueue中的任务或进入wait状态等待BlockingQueue.

a1dac2457ce8277f0bf9a2b8713c18d5.png

43)Write操作完成后,WriteHandler被后台Daemon线程调用

5b13746e2039b5fb6456e0f69df1b7f5.png

44)再次WriteHandler转交由关联的AioSocketChannel所属的AioEventLoop执行

02d49ef98415e481a3a90445be6ce108.png

45) AioEventLoop执行完WriteHandler后,整个接收和响应过程就完成了.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值