【讀后感】Netty 系列之 Netty 高性能之道 - 相比 Mina 怎樣 ?
太陽火神的漂亮人生 (http://blog.csdn.net/opengl_es)
本文遵循“署名-非商業用途-保持一致”創作公用協議
【讀后感】
不知道這是什么節奏,或許人家早就春意盎然了。僅僅是我方才感覺到而已!
研究 Mina 的過程中,偶然發現了 Netty,有人說 Mina 好久不更新了,而 Netty 一直很活躍。
這僅僅能說。
Netty 在快速的完好其中,
至於 Mina。是沒有后勁兒了呢,還是已經很完好了,不須要再繼續更新,這個到是不得而知,
至少眼下看。還不錯,
相比 Netty 的大數據、大並發、高效率。。。還有什么。請移步下文,自品其詳吧!
Netty系列之Netty高性能之道
1. 背景
1.1. 驚人的性能數據
近期一個圈內朋友通過私信告訴我,通過使用Netty4 + Thrift壓縮二進制編解碼技術。他們實現了10W TPS(1K的復雜POJO對象)的跨節點遠程服務調用。相比於傳統基於Java序列化+BIO(同步堵塞IO)的通信框架,性能提升了8倍多。
其實。我對這個數據並不感到吃驚,依據我5年多的NIO編程經驗,通過選擇合適的NIO框架,加上高性能的壓縮二進制編解碼技術。精心的設計Reactor線程模型,達到上述性能指標是全然有可能的。
以下我們就一起來看下Netty是怎樣支持10W TPS的跨節點遠程服務調用的。在正式開始解說之前,我們先簡介下Netty。
1.2. Netty基礎入門
Netty是一個高性能、異步事件驅動的NIO框架,它提供了對TCP、UDP和文件傳輸的支持,作為一個異步NIO框架,Netty的全部IO操作都是異步非堵塞的,通過Future-Listener機制,用戶能夠方便的主動獲取或者通過通知機制獲得IO操作結果。
作為當前最流行的NIO框架,Netty在互聯網領域、大數據分布式計算領域、游戲行業、通信行業等獲得了廣泛的應用,一些業界著名的開源組件也基於Netty的NIO框架構建。
2. Netty高性能之道
2.1. RPC調用的性能模型分析
2.1.1. 傳統RPC調用性能差的三宗罪
網絡傳輸方式問題:傳統的RPC框架或者基於RMI等方式的遠程服務(過程)調用採用了同步堵塞IO,當client的並發壓力或者網絡時延增大之后,同步堵塞IO會因為頻繁的wait導致IO線程常常性的堵塞,因為線程無法高效的工作,IO處理能力自然下降。
以下,我們通過BIO通信模型圖看下BIO通信的弊端:
圖2-1 BIO通信模型圖
採用BIO通信模型的服務端。通常由一個獨立的Acceptor線程負責監聽client的連接,接收到client連接之后為client連接創建一個新的線程處理請求消息,處理完畢之后,返回應答消息給client,線程銷毀,這就是典型的一請求一應答模型。
該架構最大的問題就是不具備彈性伸縮能力。當並發訪問量添加后,服務端的線程個數和並發訪問數成線性正比,因為線程是JAVA虛擬機很寶貴的系統資源,當線程數膨脹之后,系統的性能急劇下降,隨着並發量的繼續添加,可能會發生句柄溢出、線程堆棧溢出等問題。並導致server終於宕機。
序列化方式問題:Java序列化存在例如以下幾個典型問題:
1) Java序列化機制是Java內部的一種對象編解碼技術。無法跨語言使用;比如對於異構系統之間的對接,Java序列化后的碼流須要能夠通過其他語言反序列化成原始對象(副本),眼下很難支持。
2) 相比於其他開源的序列化框架。Java序列化后的碼流太大,不管是網絡傳輸還是持久化到磁盤,都會導致額外的資源占用。
3) 序列化性能差(CPU資源占用高)。
線程模型問題:因為採用同步堵塞IO,這會導致每一個TCP連接都占用1個線程,因為線程資源是JVM虛擬機很寶貴的資源。當IO讀寫堵塞導致線程無法及時釋放時。會導致系統性能急劇下降,嚴重的甚至會導致虛擬機無法創建新的線程。
2.1.2. 高性能的三個主題
1) 傳輸:用什么樣的通道將數據發送給對方。BIO、NIO或者AIO,IO模型在很大程度上決定了框架的性能。
2) 協議:採用什么樣的通信協議,HTTP或者內部私有協議。協議的選擇不同。性能模型也不同。
相比於公有協議,內部私有協議的性能通常能夠被設計的更優。
3) 線程:數據報怎樣讀取?讀取之后的編解碼在哪個線程進行,編解碼后的消息怎樣派發,Reactor線程模型的不同。對性能的影響也很大。
圖2-2 RPC調用性能三要素
2.2. Netty高性能之道
2.2.1. 異步非堵塞通信
在IO編程過程中。當須要同一時候處理多個client接入請求時。能夠利用多線程或者IO多路復用技術進行處理。
IO多路復用技術通過把多個IO的堵塞復用到同一個select的堵塞上,從而使得系統在單線程的情況下能夠同一時候處理多個client請求。與傳統的多線程/多進程模型比。I/O多路復用的最大優勢是系統開銷小。系統不須要創建新的額外進程或者線程,也不須要維護這些進程和線程的執行,減少了系統的維護工作量,節省了系統資源。
JDK1.4提供了對非堵塞IO(NIO)的支持,JDK1.5_update10版本號使用epoll替代了傳統的select/poll,極大的提升了NIO通信的性能。
JDK NIO通信模型例如以下所看到的:
圖2-3 NIO的多路復用模型圖
與Socket類和ServerSocket類相相應。NIO也提供了SocketChannel和ServerSocketChannel兩種不同的套接字通道實現。這兩種新增的通道都支持堵塞和非堵塞兩種模式。堵塞模式使用很easy。可是性能和可靠性都不好。非堵塞模式正好相反。
開發者一般能夠依據自己的須要來選擇合適的模式,一般來說。低負載、低並發的應用程序能夠選擇同步堵塞IO以減少編程復雜度。可是對於高負載、高並發的網絡應用,須要使用NIO的非堵塞模式進行開發。
Netty架構依照Reactor模式設計和實現。它的服務端通信序列圖例如以下:
圖2-3 NIO服務端通信序列圖
client通信序列圖例如以下:
圖2-4 NIOclient通信序列圖
Netty的IO線程NioEventLoop因為聚合了多路復用器Selector。能夠同一時候並發處理成百上千個clientChannel,因為讀寫操作都是非堵塞的,這就能夠充分提升IO線程的執行效率。避免因為頻繁IO堵塞導致的線程掛起。
另外,因為Netty採用了異步通信模式,一個IO線程能夠並發處理N個client連接和讀寫操作。這從根本上攻克了傳統同步堵塞IO一連接一線程模型。架構的性能、彈性伸縮能力和可靠性都得到了極大的提升。
2.2.2. 零拷貝
許多用戶都聽說過Netty具有“零拷貝”功能,可是具體體如今哪里又說不清楚,本小節就具體對Netty的“零拷貝”功能進行解說。
Netty的“零拷貝”主要體如今例如以下三個方面:
1) Netty的接收和發送ByteBuffer採用DIRECT BUFFERS,使用堆外直接內存進行Socket讀寫,不須要進行字節緩沖區的二次拷貝。
假設使用傳統的堆內存(HEAP BUFFERS)進行Socket讀寫。JVM會將堆內存Buffer拷貝一份到直接內存中。然后才寫入Socket中。相比於堆外直接內存。消息在發送過程中多了一次緩沖區的內存拷貝。
2) Netty提供了組合Buffer對象,能夠聚合多個ByteBuffer對象。用戶能夠像操作一個Buffer那樣方便的對組合Buffer進行操作,避免了傳統通過內存拷貝的方式將幾個小Buffer合並成一個大的Buffer。
3) Netty的文件傳輸採用了transferTo方法。它能夠直接將文件緩沖區的數據發送到目標Channel,避免了傳統通過循環write方式導致的內存拷貝問題。
以下,我們對上述三種“零拷貝”進行說明,先看Netty 接收Buffer的創建:
圖2-5 異步消息讀取“零拷貝”
每循環讀取一次消息,就通過ByteBufAllocator的ioBuffer方法獲取ByteBuf對象,以下繼續看它的接口定義:
圖2-6 ByteBufAllocator 通過ioBuffer分配堆外內存
當進行Socket IO讀寫的時候。為了避免從堆內存拷貝一份副本到直接內存,Netty的ByteBuf分配器直接創建非堆內存避免緩沖區的二次拷貝,通過“零拷貝”來提升讀寫性能。
以下我們繼續看另外一種“零拷貝”的實現CompositeByteBuf,它對外將多個ByteBuf封裝成一個ByteBuf,對外提供統一封裝后的ByteBuf接口。它的類定義例如以下:
圖2-7 CompositeByteBuf類繼承關系
通過繼承關系我們能夠看出CompositeByteBuf實際就是個ByteBuf的包裝器。它將多個ByteBuf組合成一個集合,然后對外提供統一的ByteBuf接口,相關定義例如以下:
圖2-8 CompositeByteBuf類定義
加入ByteBuf,不須要做內存拷貝,相關代碼例如以下:
圖2-9 新增ByteBuf的“零拷貝”
最后,我們看下文件傳輸的“零拷貝”:
圖2-10 文件傳輸“零拷貝”
Netty文件傳輸DefaultFileRegion通過transferTo方法將文件發送到目標Channel中,以下重點看FileChannel的transferTo方法,它的API DOC說明例如以下:
圖2-11 文件傳輸 “零拷貝”
對於許多操作系統它直接將文件緩沖區的內容發送到目標Channel中,而不須要通過拷貝的方式。這是一種更加高效的傳輸方式,它實現了文件傳輸的“零拷貝”。
2.2.3. 內存池
隨着JVM虛擬機和JIT即時編譯技術的發展,對象的分配和回收是個很輕量級的工作。
可是對於緩沖區Buffer,情況卻稍有不同。特別是對於堆外直接內存的分配和回收。是一件耗時的操作。為了盡量重用緩沖區,Netty提供了基於內存池的緩沖區重用機制。以下我們一起看下Netty ByteBuf的實現:
圖2-12 內存池ByteBuf
Netty提供了多種內存管理策略。通過在啟動輔助類中配置相關參數,能夠實現差異化的定制。
以下通過性能測試,我們看下基於內存池循環利用的ByteBuf和普通ByteBuf的性能差異。
用例一,使用內存池分配器創建直接內存緩沖區:
圖2-13 基於內存池的非堆內存緩沖區測試用例
用例二,使用非堆內存分配器創建的直接內存緩沖區:
圖2-14 基於非內存池創建的非堆內存緩沖區測試用例
各執行300萬次,性能對照結果例如以下所看到的:
圖2-15 內存池和非內存池緩沖區寫入性能對照
性能測試表明。採用內存池的ByteBuf相比於朝生夕滅的ByteBuf,性能高23倍左右(性能數據與使用場景強相關)。
以下我們一起簡單分析下Netty內存池的內存分配:
圖2-16 AbstractByteBufAllocator的緩沖區分配
繼續看newDirectBuffer方法,我們發現它是一個抽象方法,由AbstractByteBufAllocator的子類負責具體實現。代碼例如以下:
圖2-17 newDirectBuffer的不同實現
代碼跳轉到PooledByteBufAllocator的newDirectBuffer方法,從Cache中獲取內存區域PoolArena,調用它的allocate方法進行內存分配:
圖2-18 PooledByteBufAllocator的內存分配
PoolArena的allocate方法例如以下:
圖2-18 PoolArena的緩沖區分配
我們重點分析newByteBuf的實現。它相同是個抽象方法,由子類DirectArena和HeapArena來實現不同類型的緩沖區分配,因為測試用例使用的是堆外內存。
圖2-19 PoolArena的newByteBuf抽象方法
因此重點分析DirectArena的實現:假設沒有開啟使用sun的unsafe,則
圖2-20 DirectArena的newByteBuf方法實現
執行PooledDirectByteBuf的newInstance方法。代碼例如以下:
圖2-21 PooledDirectByteBuf的newInstance方法實現
通過RECYCLER的get方法循環使用ByteBuf對象,假設是非內存池實現,則直接創建一個新的ByteBuf對象。從緩沖池中獲取ByteBuf之后,調用AbstractReferenceCountedByteBuf的setRefCnt方法設置引用計數器,用於對象的引用計數和內存回收(相似JVM垃圾回收機制)。
2.2.4. 高效的Reactor線程模型
常常使用的Reactor線程模型有三種,分別例如以下:
1) Reactor單線程模型。
2) Reactor多線程模型。
3) 主從Reactor多線程模型
Reactor單線程模型,指的是全部的IO操作都在同一個NIO線程上面完畢,NIO線程的職責例如以下:
1) 作為NIO服務端。接收client的TCP連接;
2) 作為NIOclient,向服務端發起TCP連接;
3) 讀取通信對端的請求或者應答消息。
4) 向通信對端發送消息請求或者應答消息。
Reactor單線程模型示意圖例如以下所看到的:
圖2-22 Reactor單線程模型
因為Reactor模式使用的是異步非堵塞IO,全部的IO操作都不會導致堵塞,理論上一個線程能夠獨立處理全部IO相關的操作。從架構層面看,一個NIO線程確實能夠完畢其承擔的職責。比如,通過Acceptor接收client的TCP連接請求消息。鏈路建立成功之后,通過Dispatch將相應的ByteBuffer派發到指定的Handler上進行消息解碼。用戶Handler能夠通過NIO線程將消息發送給client。
對於一些小容量應用場景,能夠使用單線程模型。
可是對於高負載、大並發的應用卻不合適。主要原因例如以下:
1) 一個NIO線程同一時候處理成百上千的鏈路,性能上無法支撐,即便NIO線程的CPU負荷達到100%,也無法滿足海量消息的編碼、解碼、讀取和發送;
2) 當NIO線程負載過重之后,處理速度將變慢,這會導致大量client連接超時,超時之后往往會進行重發。這更加重了NIO線程的負載。終於會導致大量消息積壓和處理超時,NIO線程會成為系統的性能瓶頸;
3) 可靠性問題:一旦NIO線程意外跑飛,或者進入死循環。會導致整個系統通信模塊不可用,不能接收和處理外部消息,造成節點故障。
為了解決這些問題,演進出了Reactor多線程模型。以下我們一起學習下Reactor多線程模型。
Rector多線程模型與單線程模型最大的差別就是有一組NIO線程處理IO操作,它的原理圖例如以下:
圖2-23 Reactor多線程模型
Reactor多線程模型的特點:
1) 有專門一個NIO線程-Acceptor線程用於監聽服務端,接收client的TCP連接請求。
2) 網絡IO操作-讀、寫等由一個NIO線程池負責,線程池能夠採用標准的JDK線程池實現。它包括一個任務隊列和N個可用的線程,由這些NIO線程負責消息的讀取、解碼、編碼和發送;
3) 1個NIO線程能夠同一時候處理N條鏈路。可是1個鏈路僅僅相應1個NIO線程,防止發生並發操作問題。
在絕大多數場景下,Reactor多線程模型都能夠滿足性能需求。可是,在極特殊應用場景中,一個NIO線程負責監聽和處理全部的client連接可能會存在性能問題。比如百萬client並發連接。或者服務端須要對client的握手消息進行安全認證,認證本身很損耗性能。在這類場景下,單獨一個Acceptor線程可能會存在性能不足問題,為了解決性能問題,產生了第三種Reactor線程模型-主從Reactor多線程模型。
主從Reactor線程模型的特點是:服務端用於接收client連接的不再是個1個單獨的NIO線程。而是一個獨立的NIO線程池。
Acceptor接收到clientTCP連接請求處理完畢后(可能包括接入認證等)。將新創建的SocketChannel注冊到IO線程池(sub reactor線程池)的某個IO線程上,由它負責SocketChannel的讀寫和編解碼工作。
Acceptor線程池僅僅僅僅用於client的登陸、握手和安全認證。一旦鏈路建立成功,就將鏈路注冊到后端subReactor線程池的IO線程上,由IO線程負責興許的IO操作。
它的線程模型例如以下圖所看到的:
圖2-24 Reactor主從多線程模型
利用主從NIO線程模型,能夠解決1個服務端監聽線程無法有效處理全部client連接的性能不足問題。因此。在Netty的官方demo中,推薦使用該線程模型。
其實,Netty的線程模型並非固定不變,通過在啟動輔助類中創建不同的EventLoopGroup實例並通過適當的參數配置,就能夠支持上述三種Reactor線程模型。
正是因為Netty 對Reactor線程模型的支持提供了靈活的定制能力,所以能夠滿足不同業務場景的性能訴求。
2.2.5. 無鎖化的串行設計理念
在大多數場景下,並行多線程處理能夠提升系統的並發性能。可是。假設對於共享資源的並發訪問處理不當。會帶來嚴重的鎖競爭,這終於會導致性能的下降。為了盡可能的避免鎖競爭帶來的性能損耗,能夠通過串行化設計,即消息的處理盡可能在同一個線程內完畢。期間不進行線程切換,這樣就避免了多線程競爭和同步鎖。
為了盡可能提升性能,Netty採用了串行無鎖化設計,在IO線程內部進行串行操作。避免多線程競爭導致的性能下降。表面上看,串行化設計似乎CPU利用率不高。並發程度不夠。可是。通過調整NIO線程池的線程參數,能夠同一時候啟動多個串行化的線程並行執行。這樣的局部無鎖化的串行線程設計相比一個隊列-多個工作線程模型性能更優。
Netty的串行化設計工作原理圖例如以下:
圖2-25 Netty串行化工作原理圖
Netty的NioEventLoop讀取到消息之后,直接調用ChannelPipeline的fireChannelRead(Object msg),僅僅要用戶不主動切換線程,一直會由NioEventLoop調用到用戶的Handler,期間不進行線程切換。這樣的串行化處理方式避免了多線程操作導致的鎖的競爭。從性能角度看是最優的。
2.2.6. 高效的並發編程
Netty的高效並發編程主要體如今例如以下幾點:
1) volatile的大量、正確使用;
2) CAS和原子類的廣泛使用;
3) 線程安全容器的使用;
4) 通過讀寫鎖提升並發性能。
假設大家想了解Netty高效並發編程的細節。能夠閱讀之前我在微博分享的《多線程並發編程在 Netty 中的應用分析》。在這篇文章中對Netty的多線程技巧和應用進行了具體的介紹和分析。
2.2.7. 高性能的序列化框架
影響序列化性能的關鍵因素總結例如以下:
1) 序列化后的碼流大小(網絡帶寬的占用)。
2) 序列化&反序列化的性能(CPU資源占用);
3) 是否支持跨語言(異構系統的對接和開發語言切換)。
Netty默認提供了對Google Protobuf的支持,通過擴展Netty的編解碼接口。用戶能夠實現其他的高性能序列化框架,比如Thrift的壓縮二進制編解碼框架。
以下我們一起看下不同序列化&反序列化框架序列化后的字節數組對照:
圖2-26 各序列化框架序列化碼流大小對照
從上圖能夠看出,Protobuf序列化后的碼流僅僅有Java序列化的1/4左右。正是因為Java原生序列化性能表現太差,才催生出了各種高性能的開源序列化技術和框架(性能差僅僅是其中的一個原因,還有跨語言、IDL定義等其他因素)。
2.2.8. 靈活的TCP參數配置能力
合理設置TCP參數在某些場景下對於性能的提升能夠起到顯著的效果,比如SO_RCVBUF和SO_SNDBUF。假設設置不當。對性能的影響是很大的。以下我們總結下對性能影響比較大的幾個配置項:
1) SO_RCVBUF和SO_SNDBUF:通常建議值為128K或者256K;
2) SO_TCPNODELAY:NAGLE算法通過將緩沖區內的小封包自己主動相連,組成較大的封包,阻止大量小封包的發送堵塞網絡,從而提高網絡應用效率。
可是對於時延敏感的應用場景須要關閉該優化算法;
3) 軟中斷:假設Linux內核版本號支持RPS(2.6.35以上版本號),開啟RPS后能夠實現軟中斷,提升網絡吞吐量。RPS依據數據包的源地址,目的地址以及目的和源端口,計算出一個hash值。然后依據這個hash值來選擇軟中斷執行的cpu。從上層來看。也就是說將每一個連接和cpu綁定,並通過這個hash值,來均衡軟中斷在多個cpu上。提升網絡並行處理性能。
Netty在啟動輔助類中能夠靈活的配置TCP參數。滿足不同的用戶場景。相關配置接口定義例如以下:
圖2-27 Netty的TCP參數配置定義
2.3. 總結
通過對Netty的架構和性能模型進行分析。我們發現Netty架構的高性能是被精心設計和實現的,得益於高質量的架構和代碼,Netty支持10W TPS的跨節點服務調用並非件十分困難的事情。
3. 作者簡介
李林鋒。2007年畢業於東北大學,2008年進入華為公司從事高性能通信軟件的設計和開發工作,有6年NIO設計和開發經驗,精通Netty、Mina等NIO框架。Netty中國社區創始人。《Netty權威指南》作者。
聯系方式:新浪微博 Nettying 微信:Nettying
給InfoQ中文站投稿或者參與內容翻譯工作,請郵件至editors@cn.infoq.com。也歡迎大家通過新浪微博(@InfoQ)或者騰訊微博(@InfoQ)關注我們。並與我們的編輯和其他讀者朋友交流。
採用內存池的ByteBuf相比於朝生夕滅的ByteBuf,性能高23倍左右2014年5月30日 10:43 by Zhang Yuan
所以分配和回收效率要遠低於在Java Heap上的對象
Re: 採用內存池的ByteBuf相比於朝生夕滅的ByteBuf。性能高23倍左右2014年5月31日 03:34 by 林鋒 李
所以ByteBuffer的最優使用方法是:
1)網絡IO讀寫,直接與Socket打交道的使用直接內存;
2)其他的用途的ByteBuffer。建議直接使用ByteBuffer。
雖然基於堆內存分配的ByteBuffer性能已經很高。可是大塊緩沖區的開辟和回收依舊很損耗性能,
假設為每條消息都創建一個ByteBuffer。用完就馬上回收,這不是一個好的策略,所以Netty開發和提供了ByteBuffer 內存池。
Re: 支持,須要深入了解netty2014年6月3日 02:14 by 林鋒 李
升級中假設遇到什么疑難問題,也能夠發郵件給我討論下,我打算將來有空寫一篇具體點的升級指南。
Ding2014年6月5日 01:27 by qingyi xu
Re: node.js2014年6月5日 04:11 by zhang frank
Good2014年6月5日 07:28 by 穆 曉林
為什么要設置這么大的緩沖區呢,保持1000tcp鏈接能否夠覺得(256k+128K)*1000的內存
Re: node.js2014年6月5日 09:57 by 林鋒 李
只是過分追求性能也是把雙刃劍,比如Netty直接利用了一些JDK提供商相關的特性。如sun的Unsafe。
Re: Good2014年6月5日 10:09 by 林鋒 李
關於內存的問題,有兩種解決的方法:
1) 依據實際的組網計算內存。JDK的內存上限未必一定要設置成4G或者8G;
2) 內存緩沖區能夠使用內存池,消費完放回池子,不是每條鏈路都一直占用這么多內存。
實際上你說的問題不存在,原因例如以下:
1. 假設是長連接,1000個TCP,意味着1000個節點的集群組網。國內除了阿里等互聯網巨頭。誰有這么大的集群組網?
2. 假設是短連接。處理完畢鏈路就會關閉,資源釋放,buffer是不會被某條鏈路長期持有的;
3. 集群情況下,消息是分發到多個節點上的。
4. 內存池的應用。
實際上,你改小,依照這個公式,那我 10W個鏈路,100W個鏈路。內存還是不夠,你改小也沒用。
不夠就加內存唄。假設server內存不足。那就說明支持不了這么多鏈路。
Re: Good2014年6月5日 10:09 by 林鋒 李
關於內存的問題,有兩種解決的方法:
1) 依據實際的組網計算內存。JDK的內存上限未必一定要設置成4G或者8G;
2) 內存緩沖區能夠使用內存池,消費完放回池子。不是每條鏈路都一直占用這么多內存。
實際上你說的問題不存在。原因例如以下:
1. 假設是長連接。1000個TCP,意味着1000個節點的集群組網,國內除了阿里等互聯網巨頭。誰有這么大的集群組網?
2. 假設是短連接,處理完畢鏈路就會關閉,資源釋放,buffer是不會被某條鏈路長期持有的。
3. 集群情況下,消息是分發到多個節點上的。
4. 內存池的應用。
實際上,你改小,依照這個公式,那我 10W個鏈路,100W個鏈路。內存還是不夠,你改小也沒用。不夠就加內存唄,假設server內存不足,那就說明支持不了這么多鏈路。
Re: Good2014年6月5日 10:09 by 林鋒 李
關於內存的問題,有兩種解決的方法:
1) 依據實際的組網計算內存,JDK的內存上限未必一定要設置成4G或者8G。
2) 內存緩沖區能夠使用內存池,消費完放回池子,不是每條鏈路都一直占用這么多內存。
實際上你說的問題不存在,原因例如以下:
1. 假設是長連接,1000個TCP。意味着1000個節點的集群組網,國內除了阿里等互聯網巨頭,誰有這么大的集群組網?
2. 假設是短連接。處理完畢鏈路就會關閉,資源釋放。buffer是不會被某條鏈路長期持有的;
3. 集群情況下,消息是分發到多個節點上的;
4. 內存池的應用。
實際上,你改小,依照這個公式,那我 10W個鏈路,100W個鏈路,內存還是不夠,你改小也沒用。不夠就加內存唄。假設server內存不足,那就說明支持不了這么多鏈路。
Re: Good2014年6月5日 10:09 by 林鋒 李
關於內存的問題。有兩種解決的方法:
1) 依據實際的組網計算內存,JDK的內存上限未必一定要設置成4G或者8G;
2) 內存緩沖區能夠使用內存池,消費完放回池子,不是每條鏈路都一直占用這么多內存。
實際上你說的問題不存在,原因例如以下:
1. 假設是長連接,1000個TCP,意味着1000個節點的集群組網。國內除了阿里等互聯網巨頭,誰有這么大的集群組網?
2. 假設是短連接,處理完畢鏈路就會關閉,資源釋放,buffer是不會被某條鏈路長期持有的。
3. 集群情況下,消息是分發到多個節點上的;
4. 內存池的應用。
實際上,你改小。依照這個公式。那我 10W個鏈路,100W個鏈路,內存還是不夠,你改小也沒用。
不夠就加內存唄,假設server內存不足,那就說明支持不了這么多鏈路。
Re: Good2014年6月5日 10:09 by 林鋒 李
關於內存的問題。有兩種解決的方法:
1) 依據實際的組網計算內存,JDK的內存上限未必一定要設置成4G或者8G;
2) 內存緩沖區能夠使用內存池,消費完放回池子。不是每條鏈路都一直占用這么多內存。
實際上你說的問題不存在,原因例如以下:
1. 假設是長連接,1000個TCP,意味着1000個節點的集群組網,國內除了阿里等互聯網巨頭,誰有這么大的集群組網?
2. 假設是短連接,處理完畢鏈路就會關閉,資源釋放,buffer是不會被某條鏈路長期持有的;
3. 集群情況下,消息是分發到多個節點上的。
4. 內存池的應用。
實際上,你改小。依照這個公式。那我 10W個鏈路,100W個鏈路,內存還是不夠,你改小也沒用。不夠就加內存唄。假設server內存不足,那就說明支持不了這么多鏈路。
Re: 求推薦2014年6月11日 09:21 by 林鋒 李
實際上,Netty 3升級到 4后架構進行了重構和優化。假設你想升級到4。還是須要認真學習下 Netty 4。
眼下,系統介紹 Netty 4和 Netty5的書籍不多。眼下市場上有兩本。
1. Netty in Action: 英文版的。亞馬遜能夠買到。大概500元左右;
2. Netty權威指南,6月份剛出版,在互動、亞馬遜、當當、京東等能夠預定。預計6月中下旬能發貨。
還有最后一個途徑就是閱讀源代碼。這個須要具備三個條件:1. 有一定的NIO編程經驗。2. 實際應用過Netty;3. 喜歡鑽研源代碼。
對於“Reactor主從多線程模型”不太理解2014年6月20日 06:23 by 徐 小蝦
做為client 使用socket短鏈接有必要使用NIO嗎?2014年6月26日 12:22 by kai shen
採用的都是短鏈接,我們即做服務端又做client,服務端我們用mina client就用的jdk 的類。請問client有必要也用Nio嗎?有什么優點嗎?對於短鏈接來講
Re: 對於“Reactor主從多線程模型”不太理解2014年6月27日 11:47 by 林鋒 李
主從多線程模型中有1個線程池。僅僅有一個Acceptor線程用於SocketChannel接入。然后將其投遞到本線程組其他的可用線程中處理興許的接入認證、黑白名單校驗、加解密、編解碼等操作,因為這些操作須要一定的時間,因為由獨立的線程負責,否則Acceptor線程無法及時處理其他的接入。
這樣的模型的ServerSocketChannel僅僅有一個。掛載在Acceptor線程上。
該模型通常常使用於海量的client接入和推送系統中。
Re: 做為client 使用socket短鏈接有必要使用NIO嗎?2014年6月27日 11:50 by 林鋒 李
不管服務端還是client,都須要操作IO,假設對方處理速度比較慢,常常超時,而你的超時時間又無法設置太短。就會導致你的client通信線程常常掛住,可靠性比較差。因此建議你使用NIO。
Re: 採用內存池的ByteBuf相比於朝生夕滅的ByteBuf。性能高23倍左右2014年7月4日 10:37 by Jesse Q
Re: 採用內存池的ByteBuf相比於朝生夕滅的ByteBuf,性能高23倍左右2014年7月4日 10:59 by 林鋒 李
by 林鋒 李 Posted2014年6月5日 10:41