動態

詳情 返回 返回

Netty學習三 - 動態 詳情

本文主要梳理下Netty裏的EventLoop。

EventLoop並非Netty所獨有,它是一種事件等待和處理的程序模型,可以解決多線程資源消耗高的問題,EventLoop在node.js中也有使用。下圖是EventLoop通用的運行模式。每當事件發生時,應用程序都會將產生的事件放入事件隊列中,然後EventLoop會輪詢從隊列中取出事件執行或者將事件分發給相應的事件監聽者執行。事件執行的方式通常分為立即執行、延後執行、定期執行幾種。
image.png

下面將Netty裏的EventLoop進行展開。

Netty裏的EventLoop可以理解為Reactor線程模型的事件處理引擎,每EventLoop線程都維護一個Selector選擇器和任務隊列taskQueue,它主要負責處理IO事件、普通任務和定時任務。下面從事件處理和任務處理兩個部分介紹Netty EventLoop的實現原理。

事件處理機制
Netty中推薦使用NioEventLoop作為實現類,NioEventLoop的事件處理機制採用的是無鎖串行化的設計思路。

  1. BossEventLoopGroup和WorkerEventLoopGroup包含一個或多個NioEventLoop,BossEventLoopGroup負責監聽客户端的Accept事件,當事件觸發時,將事件註冊到WorkerEventLoopGroup中的一個NioEventLoop上。每新建一個Channel,只選擇一個NioEventLoop與其綁定。所以説Channel生命週期的所有事件處理都是線程獨立的,不同的NioEventLoop線程之間不會發生任何交集。
  2. NioEventLoop完成數據讀取後,會調用綁定的ChannelPipleline進行事件傳播,ChannelPipleline也是線程安全的,數據會被傳遞到ChannelPipleline的第一個ChannelHandler中。數據處理完成後,將加工完成的數據再傳遞給下一個ChannelHandler,整個過程是串行化執行的,不不會發生線程上下文切換的問題。

NioEventLoop無鎖串行化設計不僅使系統吞吐量達到最大化,而且讓用户不需要花太多精力關心線程安全問題。但我們也需要意識到這種設計的缺陷:不能執行時間過長的IO操作,一旦某個IO事件發生阻塞,那麼後續的所有IO事件都無法執行,最後造成事件積壓,我們在使用時一定要注意這點。

任務處理機制
NioEventLoop不僅負責處理IO事件,還要兼顧執行任務隊列中的任務。任務隊列遵循FIFO規則,可以保證任務執行的公平性。NioEventLoop處理的任務類型基本可以分為三類:

  1. 普通任務
    通過NioEventLoop的execute方法向任務隊列taskQueue中添加任務。例如Netty在寫數據時會封裝WriteAndFlushTask提交給taskQueue,taskQueue的實現類是多生產者單消費者隊列MpsChunkedArrayQueue,在多線程併發添加任務時,可以保證線程安全。
  2. 定時任務
    通過調用NioEventLoop的schedule方法向定時任務隊列shecduleTaskQueue中添加任務,用於週期性執行該任務,例如心跳消息發送等。定時任務隊列shecduleTaskQueue採用優先隊列PriorityQueue實現。
  3. 尾部隊列
    tailTasks相比於普通任務隊列優先級較低,在每次執行完taskQueue中任務後會去獲取尾部隊列中任務執行。尾部任務並不常用,主要用於做一些收尾工作,比如統計事件循環的執行時間、監控信息上報等。
user avatar mannayang 頭像 king_wenzhinan 頭像 seazhan 頭像 u_11365552 頭像 chuanghongdengdeqingwa_eoxet2 頭像 jkdataapi 頭像 yizhidanshendetielian 頭像 huangxunhui 頭像 tuhooo 頭像 devlive 頭像 gvison 頭像 dengjijie 頭像
點贊 41 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.