【讀後感】Netty 系列之 Netty 高性能之道 - 相比 Mina 怎樣 ?

【讀後感】Netty 系列之 Netty 高性能之道 - 相比 Mina 怎樣 ?
php

太陽火神的漂亮人生 (http://blog.csdn.net/opengl_es)node

本文遵循「署名-非商業用途-保持一致」創做公用協議react

轉載請保留此句:太陽火神的漂亮人生 -  本博客專一於 敏捷開發及移動和物聯設備研究:iOS、Android、Html五、Arduino、pcDuino不然,出自本博客的文章拒絕轉載或再轉載,謝謝合做。算法


【讀後感】
不知道這是什麼節奏,或許人家早就春意盎然了。僅僅是我方纔感受到而已!

研究 Mina 的過程當中,偶然發現了 Netty,有人說 Mina 很久不更新了,而 Netty 一直很活躍。
這僅僅能說。
Netty 在快速的無缺其中,
至於 Mina。是沒有後勁兒了呢,仍是已經很無缺了,不需要再繼續更新,這個到是不得而知,
至少眼下看。還不錯,
相比 Netty 的大數據、大併發、高效率。。。

還有什麼。請移步下文,自品其詳吧!編程


Netty系列之Netty高性能之道

1. 背景

1.1. 驚人的性能數據

近期一個圈內朋友經過私信告訴我,經過使用Netty4 + Thrift壓縮二進制編解碼技術。他們實現了10W TPS(1K的複雜POJO對象)的跨節點遠程服務調用。相比於傳統基於Java序列化+BIO(同步堵塞IO)的通訊框架,性能提高了8倍多。windows

其實。我對這個數據並不感到吃驚,依據我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)關注咱們。並與咱們的編輯和其餘讀者朋友交流。

告訴咱們您的想法

社區評論 Watch Thread

採用內存池的ByteBuf相比於朝生夕滅的ByteBuf,性能高23倍左右2014年5月30日 10:43 by Zhang Yuan

之因此會這樣,是由於ByteBUffer多是從Native Memory分配出來的。


因此分配和回收效率要遠低於在Java Heap上的對象

Good2014年5月31日 02:31 by 孫 奇輝

頂,請繼續多寫!

Re: 採用內存池的ByteBuf相比於朝生夕滅的ByteBuf。性能高23倍左右2014年5月31日 03:34 by 林鋒 李

是的。

因此ByteBuffer的最優使用方法是:
1)網絡IO讀寫,直接與Socket打交道的使用直接內存;
2)其餘的用途的ByteBuffer。建議直接使用ByteBuffer。



雖然基於堆內存分配的ByteBuffer性能已經很高。但是大塊緩衝區的開闢和回收依舊很損耗性能,
假設爲每條消息都建立一個ByteBuffer。用完就立刻回收,這不是一個好的策略,因此Netty開發和提供了ByteBuffer 內存池。

Re: Good2014年5月31日 03:35 by 林鋒 李

謝謝鼓舞。你們對實戰型的乾貨仍是很渴求的。後面我會繼續分享一些Netty的乾貨!

2014年6月2日 11:21 by yan yan

頂。繼續期待興許的文章。

支持。需要深刻了解netty2014年6月3日 10:30 by 劉 鵬

支持。正準備升級netty從3到4.x

Re: 支持,需要深刻了解netty2014年6月3日 02:14 by 林鋒 李

從Netty 3升級到4仍是有一些小麻煩,接口層面變動的有點多,沒法前向兼容。架構也重構了下。添加了一些功能,改動了一些接口設計。

升級中假設遇到什麼疑難問題,也可以發郵件給我討論下,我打算未來有空寫一篇具體點的升級指南。

Re: 贊2014年6月3日 02:18 by 林鋒 李

多謝。這些都是從實踐中提煉出來的,因此對於本身的框架設計也有指導意義。

node.js2014年6月3日 05:18 by he rn

可否分析一下node.js是否也能作到這些?

Re: node.js2014年6月4日 11:36 by 林鋒 李

這個可以由精通node.js的朋友們結合具體的性能數據和業務場景分析下。

Ding2014年6月5日 01:27 by qingyi xu

近期在作的一個遠程RPC框架也是使用的 Netty 做爲底層通訊框架,當前使用Netty3性能已經很不錯了,不知道升級Netty4後還有多大的驚喜!

Re: Ding2014年6月5日 10:47 by 林鋒 李

可以這樣說,有 "驚" 也有 "喜" ,相信你升級的時候就會有深切體會了。

Re: node.js2014年6月5日 04:11 by zhang frank

NodeJS採用的是「Reactor多線程模型」,即一個Acceptor線程負責接收請求。所有的IO操做由系統IO線程池完畢。並且Node針對不一樣平臺的IO策略進行了優化,在windows下是用IOCP,而*nix下採用的是本身定義的IO線程池。

Good2014年6月5日 07:28 by 穆 曉林

1) SO_RCVBUF和SO_SNDBUF:一般建議值爲128K或者256K;
爲何要設置這麼大的緩衝區呢,保持1000tcp連接可否夠以爲(256k+128K)*1000的內存

Re: node.js2014年6月5日 09:57 by 林鋒 李

嗯。IO線程模型幾乎相同。只是Netty的IO線程模型可以由用戶定製,支持多種模式。Netty也作了許多底層的優化。好比優化了Selector的選擇鍵列表,它有一些性能開關。

只是過度追求性能也是把雙刃劍,好比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內存不足,那就說明支持不了這麼多鏈路。

很差意思,剛纔點擊回覆沒有反應。我連續點了屢次,沒想到竟然反覆發了5份,杯具啊。

2014年6月5日 10:41 by 林鋒 李

如題,也沒有濾重功能......

求推薦2014年6月9日 04:16 by qingyi xu

博主有沒有Netty4或者最新的5的學習書籍?Netty遷移中需要注意的。也包括Netty新版本號的新特性介紹的

Re: 求推薦2014年6月11日 09:21 by 林鋒 李

網上有一些Netty 3到 Netty4的 API差別對照,感興趣你可以看下。
實際上,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 徐 小蝦

在上面的「Reactor主從多線程模型」中有幾個線程池?會生成一個ServerSocketChannel仍是多個ServerSocketChannel呢?

作爲client 使用socket短連接有必要使用NIO嗎?2014年6月26日 12:22 by kai shen

我剛接觸網絡編程不久,以前僅僅知道MINA。想問一下jetty更主流些嗎? 還有咱們系統接收socket報文後還要經過 socket 請求另一個系統,而後依據請求結果返回給client請求的處理結果。

採用的都是短連接,咱們即作服務端又作client,服務端咱們用mina client就用的jdk 的類。請問client有必要也用Nio嗎?有什麼優勢嗎?對於短連接來說

Re: 對於「Reactor主從多線程模型」不太理解2014年6月27日 11:47 by 林鋒 李

你的問題很好,看來你對NIO編程仍是比較熟悉的。

主從多線程模型中有1個線程池。僅僅有一個Acceptor線程用於SocketChannel接入。而後將其投遞到本線程組其餘的可用線程中處理興許的接入認證、黑白名單校驗、加解密、編解碼等操做,由於這些操做需要必定的時間,由於由獨立的線程負責,不然Acceptor線程沒法及時處理其餘的接入。

這樣的模型的ServerSocketChannel僅僅有一個。掛載在Acceptor線程上。



該模型一般常使用於海量的client接入和推送系統中。

Re: 作爲client 使用socket短連接有必要使用NIO嗎?2014年6月27日 11:50 by 林鋒 李

Jetty是輕量級的HTTP協議棧和Web容器,比較流行。

無論服務端仍是client,都需要操做IO,假設對方處理速度比較慢,經常超時,而你的超時時間又沒法設置過短。就會致使你的client通訊線程經常掛住,可靠性比較差。所以建議你使用NIO。

Re: 採用內存池的ByteBuf相比於朝生夕滅的ByteBuf。性能高23倍左右2014年7月4日 10:37 by Jesse Q

菜鳥一枚,請教一個問題:在堆外分配的內存是由full gc 來釋放的?,那麼假設堆的內存比較充足的時候長時間不觸發full gc。是否是堆外的內存就被佔用着,是否是意味着堆外的機器內存將會耗光?

Re: 採用內存池的ByteBuf相比於朝生夕滅的ByteBuf,性能高23倍左右2014年7月4日 10:59 by 林鋒 李

這篇文章寫得很清楚。建議你可以參考下: blog.csdn.net/xieyuooo/article/details/7547435
相關文章
相關標籤/搜索