這博文的系列主要是為了更好的了解一個完整的nio框架的編程細(xì)節(jié)以及演進(jìn)過程,我選了同父(Trustin Lee)的兩個框架netty與mina做對比。版本涉 及了netty3.x、netty4.x、mina1.x、mina2.x、mina3.x。這里并沒有寫netty5.x的細(xì)節(jié),看了 netty5的修改文檔 ,似乎有一些比較有意思的改動,準(zhǔn)備單獨寫一篇netty4.x與netty5.x的不同。 netty從twitter發(fā)布的這篇《 Netty 4 at Twitter: Reduced GC Overhead 》文章讓國內(nèi)Java界為之一振,也小火了一把,同時netty的社區(qū)發(fā)展也不錯,版本迭代非???,半年不關(guān)注大、小版本就發(fā)了好幾輪了。但是mina就有點淡了,github上面它最后大多數(shù)代碼最后的修改日期均在2013年,不過我從個人情感上還是挺喜歡mina3的代碼,沒有太多的用不上的功能(支持各種協(xié)議啥的),跑自帶的benchmark性能也比netty4好一些。但是如果是生產(chǎn)用的話,就偏向netty多一些了,畢竟社區(qū)活躍,版本迭代也快。 1. mina、netty的線程模型mina與netty都是Trustin Lee的作品,所以在很多方面都十分相似,他們線程模型也是基本一致,采用了Reactors in threads模型,即Main Reactor + Sub Reactors的模式。由main reactor處理連接相關(guān)的任務(wù):accept、connect等,當(dāng)連接處理完畢并建立一個socket連接(稱之為session)后,給每個 session分配一個sub reactor,之后該session的所有IO、業(yè)務(wù)邏輯處理均交給了該sub reactor。每個reactor均是一個線程,sub reactor中只靠內(nèi)核調(diào)度,沒有任何通信且互不打擾。 在前面的博文:[ Netty 4.x學(xué)習(xí)筆記 – 線程模型 ],對netty的線程模型有一定的介紹?,F(xiàn)在來講講我對線程模型演進(jìn)的一些理解:
以上圖片及總結(jié)參考:《Linux多線程服務(wù)端編程》 2. mina、netty的任務(wù)調(diào)度粒度mina、netty在線程模型上并沒有太大的差異性,主要的差異還是在任務(wù)調(diào)度的粒度的不同。任務(wù)從邏輯上我給它分為成三種類型:連接相關(guān)的任務(wù) (bind、connect等)、寫任務(wù)(write、flush)、調(diào)度任務(wù)(延遲、定時等),讀任務(wù)則由selector加循環(huán)時間控制了。 mina、netty任務(wù)調(diào)度的趨勢是逐漸變小,從session級別的調(diào)度 -> 類型級別任務(wù)的調(diào)度 -> 任務(wù)的調(diào)度。 代碼
分析mina1、2的任務(wù)調(diào)度粒度為session。mina會將有IO任務(wù)的的session寫入隊列中,當(dāng)循環(huán)執(zhí)行任務(wù)時,則會輪詢所有的session,并依次把session中的所有任務(wù)取出來運行。這樣粗粒度的調(diào)度是不公平調(diào)度,會導(dǎo)致某些請求的延遲很高。 mina3的模型改動比較大,代碼相對就比較難看了,我僅是隨便掃了一下,它僅提煉出了writeQueue。 而netty3的調(diào)度粒度則是按照IO操作,分成了registerTaskQueue、writeTaskQueue、eventQueue三個 隊列,當(dāng)有IO任務(wù)時,依次processRegisterTaskQueue、processEventQueue、 processWriteTaskQueue、processSelectedKeys(selector.selectedKeys)。 netty4可能覺得netty3的粒度還是比較粗,將隊列細(xì)分成了taskQueue和delayedTaskQueue,所有的任務(wù)均放在 taskQueue中,delayedTaskQueue則是定時調(diào)度任務(wù),且netty4可以靈活配置task與selectedKey處理的時間比 例。 BTW: netty3.6.0之后,所有的隊列均合并成了一個taskQueue 有意思的是,netty4會優(yōu)先處理selectedKeys,然后再處理任務(wù),netty3則相反。mina1、2則是先處理新建的session,再處理selectedKeys,再處理任務(wù)。 難道selectedKeys處理順序有講究么? |
|