日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Reactor三种线程模型与Netty线程模型

發(fā)布時間:2024/7/5 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Reactor三种线程模型与Netty线程模型 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、Reactor三種線程模型

1.1、單線程模型

? ? ? ?單個線程以非阻塞IO或事件IO處理所有IO事件,包括連接、讀、寫、異常、關(guān)閉等等。單線程Reactor模型基于同步事件分離器來分發(fā)事件,這個同步事件分離器,可以看做是一個單線程的while循環(huán)。下圖描述了單線程模型的處理過程,看起來與網(wǎng)上大部分資料的圖片不同,但本質(zhì)是相同的。

? ? ? ?注意上面的Selector之所以會有OP_ACEEPT事件,是因為在單線程模型中,Selector輪詢的是監(jiān)聽套接字與已連接客戶端套接字的所有IO事件

? ? ? ?單線程處理所有IO事件的弊端很明顯。沒能利用計算機CPU多核的特性,一個線程某個時刻只能處理單個IO事件,此時如果有其他描述符有IO事件就緒(如來了一個新的連接),這些IO事件將暫時得不到處理。

? ? ? ?C++框架libevent中,基于event_base_loop做消息輪詢,使用event_base_dispatch來分發(fā)IO消息,本質(zhì)上是對上述模型的封裝。如果不使用evthread_use_pthreads,則其默認就是單線程模型處理請求。

1.2、多線程模型

? ? ? ?一個線程/進程接收連接、一組線程/進程處理IO讀寫事件。也就是將accept的線程與處理讀、寫等IO事件的線程分離,并且使用m多個線程以非阻塞IO或者事件IO來處理n個套接字的IO事件,這里的n一般遠大于m,線程數(shù)m一般取CPU邏輯核心數(shù)的1-3倍,而套接字數(shù)n則取決于請求數(shù)和進程可以打開的最大描述符個數(shù)。下圖是多線程模型

? ? ? ?可以看到,這里把客戶端的已連接套接字,轉(zhuǎn)交給某個IO線程之后,由此線程輪詢處理其之后的所有IO事件,這實際參考了netty4的線程模型設(shè)計。實際reactor的多線程模型,并不需要將已連接套接字綁定在某個線程上,也可以統(tǒng)一放在連接池中,由多個IOWork線程從池中取連接進行輪詢并處理,但這樣會復雜很多,而且容易出問題,比如說不同線程從同一個channel收到了write事件,這就類似驚群問題了;并且多線程并發(fā)操作同一個channel,后續(xù)很可能需要你將IO事件進行同步,與其如此,不如直接將channel綁定到一個線程,讓channel上觸發(fā)與處理IO事件邏輯上同步。netty3中channel(已連接套接字)入站事件由固定線程處理,出站事件由觸發(fā)的線程處理,netty4中修改了設(shè)計,將channel綁定到固定的eventloop(線程)。

? ? ? ?另外一點,每個已連接套接字的IO事件由固定線程處理,不代表事件也一定由此線程觸發(fā),恰恰相反,實際業(yè)務中,讀(入站)事件來自于客戶端寫數(shù)據(jù)觸發(fā),而寫(出站)事件往往由別的線程觸發(fā),例如在發(fā)起一個異步mysql操作完成之后,在異步回調(diào)線程中寫結(jié)果數(shù)據(jù)來觸發(fā)套接字的出站。

1.3、從多線程模型

? ? ? ?一組線程/進程接收連接、一組線程/進程處理IO讀寫事件。它與多線程模型的主要區(qū)別在于其使用一組線程或進程在一個共享的監(jiān)聽套接字上accept連接。這么做的原因是為了應付單個線程/進程不足以快速處理內(nèi)核中監(jiān)聽套接字的已連接套接字隊列(并發(fā)量極大)的情況。如下:?

? ? 主從多線程模型,有可能引起驚群效應。不過這個問題已經(jīng)漸漸被規(guī)避,內(nèi)核可以保證連接只被唯一一個accept調(diào)用所獲取,其余對此連接的accept調(diào)用將失敗。

二、Netty支持的線程模型

? ? ? ?Netty支持單線程、多線程模型、主從多線程模型。但經(jīng)本人多次測試、調(diào)試發(fā)現(xiàn),ServerBootstrap默認不會使用主從多線程模型。雖然server支持設(shè)置EventLoopGroup(多個EventLoop)。但實際對于一個本地地址(IP+端口)進行accept,netty只會綁定到一個EventLoop上,故只會創(chuàng)建一個線程處理。

? ? ? ?按本人的理解,Boss EventLoopGroup(Master EventLoopGroup,參數(shù)nThreads不為1)的作用主要用在對共享的監(jiān)聽套接字或者多個本地地址監(jiān)聽,對多個本地地址進行監(jiān)聽一般表示一個JVM中有多個server,即有多個ServerBootStrap,這時,Boss EventLoopGroup可以通過共享給這多個ServerBootStrap起到作用(創(chuàng)建多個boss/master Thread)。

? ? ? ?以下面的代碼為例MASTER_THREAD_CNT為4,但netty實際只會使用第一個EventLoop,只會給第一個EventLoop創(chuàng)建線程。

?

調(diào)試跟蹤源碼,可以明白netty的邏輯。
在ServerBootstrap繼承的initAndRegister方法中,調(diào)用MultithreadEventLoopGroup#register方法,此方法調(diào)用this.next獲取當前索引的下一個(索引位0,即是第一個)EventLoop。

然后register方法進一步調(diào)用register方法,在register中執(zhí)行eventLoop.execute,這里才會真正為監(jiān)聽套接字創(chuàng)建第一個輪詢線程。

?

? ? ? ?問題就在于在ServerBootstrap上調(diào)用bind方法,初始化監(jiān)聽socket并綁定EventLoop時,是調(diào)用的next方法。因此netty只會初始化第一個MasterEventLoop,如果想將MasterEventLoopGroup中的每個EventLoop都初始化,很顯然,需要重復綁定多個監(jiān)聽套接字或者多次綁定一個可共享的套接字。

總結(jié)

以上是生活随笔為你收集整理的Reactor三种线程模型与Netty线程模型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。