Netty 框架學習 —— EventLoop 和線程模型


EventLoop 接口

Netty 是基於 Java NIO 的,所以 Channel 也有其生命週期,處理一個鏈接在其生命週期內發生的事件是全部網絡框架的基本功能。一般來講,咱們使用一個線程來處理一個鏈接,該鏈接的生命週期的某一事件就緒,則會調用對應的事件處理邏輯java

在 Netty 中,一個 EventLoop 負責處理一個 Channel 的生命週期事件。在代碼設計上,EventLoop 間接實現了 JUC 中的 ExecutorService 和 ScheduleExecutorService 兩個接口,所以其具備了線程池的特性。一個 EventLoop 將由一個永遠不會改變的 Thread 驅動,EventLoop 由一個 Selector 和 TaskQueue 組成,Selector 會選擇 Channel 生命週期中某一事件,並由 EventLoop 所在的線程選擇對應的 ChannelHandler 進行處理。除此以外,用戶還能夠手動提交任務給 EventLoop,以當即執行或調度執行網絡


任務調度

有時候,你但願在 Channel 中調度一個任務以當即執行、稍後執行或者週期性執行。然而,這些任務有可能會形成長時間的阻塞,若是寫在 ChannelHandler 裏面,則有可能會阻塞整個執行鏈。所以,咱們能夠把這些任務提交給 EventLoop,EventLoop 會把這些任務放入 TaskQueue 中,等待建立線程去執行,這個過程是異步非阻塞的,不會影響到主執行鏈框架

Channel ch = ...;
ScheduleFuture<?> future = ch.eventLoop().schedule(
    // 建立一個 Runnable 以供調度稍後執行
	new Runnable() {
        @Override
        public void run() {
            // 要執行的代碼
            System.out.println("60 second later");
        }
    }, 60, TimeUnit.SECONDS);

由此咱們知道,EventLoop 所在線程負責一個 Channel 的整個生命週期內的全部事件。有時候,咱們還會在別的線程去獲取一個 Channel,並向該 Channel 對應的 EventLoop 提交任務。這種非對應 Channel 所提交過來的任務,EventLoop 會把它放入任務隊列中,等待下次執行異步


EventLoop 的線程分配

服務於 Channel 的 EventLoop 包含在 EventLoopGroup 中,根據不一樣的傳輸實現,EventLoop 的建立和分配方式也不一樣ide

1. 異步傳輸

異步傳輸實現只使用了少許的 EventLoop,一個 EventLoop 可能會被多個 Channel 所共享,經過儘量少的線程來支撐大量的 Channel,而不是每一個 Channel 分配一個 Threadoop

須要注意的是,一個 EventLoop 被用於支撐多個 Channel,那麼對於全部相關聯的 Channel 來講,ThreadLocal 是同樣的,這使得它對於實現狀態追蹤等功能來講是個糟糕的選擇線程

2. 阻塞傳輸

每個 Channel 都將分配給一個 EventLoop,每一個 Channel 的 IO 事件都將只會被一個 Thread 處理設計

相關文章
相關標籤/搜索