Netty的優化備記

OnitaC01 8年前發布 | 35K 次閱讀 Netty 網絡工具包

1.當心“日志隱形殺手”

通常情況下,大家都知道不能在Netty的I/O線程上做執行時間不可控的操作,例如訪問數據庫、發送Email等。但是有個常用但是非常危險的操作卻容易被忽略,那便是記錄日志。

通常,在生產環境中,需要實時打印接口日志,其它日志處于ERROR級別,當推送服務發生I/O異常之后,會記錄異常日志。如果當前磁盤的WIO比較高,可能會發生寫日志文件操作被同步阻塞,阻塞時間無法預測。這就會導致Netty的NioEventLoop線程被阻塞,Socket鏈路無法被及時關閉、其它的鏈路也無法進行讀寫操作等。

以最常用的log4j為例,盡管它支持異步寫日志(AsyncAppender),但是當日志隊列滿之后,它會同步阻塞業務線程,直到日志隊列有空閑位置可用,相關代碼如下:

synchronized (this.buffer) {
      while (true) {
        int previousSize = this.buffer.size();
        if (previousSize < this.bufferSize) {
          this.buffer.add(event);
          if (previousSize != 0) break;
          this.buffer.notifyAll(); break;
        }
        boolean discard = true;
        if ((this.blocking) && (!Thread.interrupted()) && (Thread.currentThread() != this.dispatcher)) //判斷是業務線程
        {
          try
          {
            this.buffer.wait();//阻塞業務線程
            discard = false;
          }
          catch (InterruptedException e)
          {
            Thread.currentThread().interrupt();
          }
}

類似這類BUG具有極強的隱蔽性,往往WIO高的時間持續非常短,或者是偶現的,在測試環境中很難模擬此類故障,問題定位難度非常大。這就要求讀者在平時寫代碼的時候一定要當心,注意那些隱性地雷。

2.TCP參數優化

常用的TCP參數,例如TCP層面的接收和發送緩沖區大小設置,在Netty中分別對應ChannelOption的SO_SNDBUF和SO_RCVBUF,需要根據推送消息的大小,合理設置,對于海量長連接,通常32K是個不錯的選擇。

另外一個比較常用的優化手段就是軟中斷,如圖所示:如果所有的軟中斷都運行在CPU0相應網卡的硬件中斷上,那么始終都是cpu0在處理軟中斷,而此時其它CPU資源就被浪費了,因為無法并行的執行多個軟中斷。

大于等于2.6.35版本的Linux kernel內核,開啟RPS,網絡通信性能提升20%之上。RPS的基本原理:根據數據包的源地址,目的地址以及目的和源端口,計算出一個hash值,然后根據這個hash值來選擇軟中斷運行的cpu。從上層來看,也就是說將每個連接和cpu綁定,并通過這個hash值,來均衡軟中斷運行在多個cpu上,從而提升通信性能。

3.JVM參數

最重要的參數調整有兩個:

-Xmx:JVM最大內存需要根據內存模型進行計算并得出相對合理的值;

GC相關的參數: 例如新生代和老生代、永久代的比例,GC的策略,新生代各區的比例等,需要根據具體的場景進行設置和測試,并不斷的優化,盡量將Full GC的頻率降到最低。

4.內存池

推送服務器承載了海量的長鏈接,每個長鏈接實際就是一個會話。如果每個會話都持有心跳數據、接收緩沖區、指令集等數據結構,而且這些實例隨著消息的處理朝生夕滅,這就會給服務器帶來沉重的GC壓力,同時消耗大量的內存。

最有效的解決策略就是使用內存池,每個NioEventLoop線程處理N個鏈路,在線程內部,鏈路的處理時串行的。假如A鏈路首先被處理,它會創建接收緩沖區等對象,待解碼完成之后,構造的POJO對象被封裝成Task后投遞到后臺的線程池中執行,然后接收緩沖區會被釋放,每條消息的接收和處理都會重復接收緩沖區的創建和釋放。如果使用內存池,則當A鏈路接收到新的數據報之后,從NioEventLoop的內存池中申請空閑的ByteBuf,解碼完成之后,調用release將ByteBuf釋放到內存池中,供后續B鏈路繼續使用。

 

 

 

來自:http://blog.edagarli.com/2016/09/24/Netty的優化備記/

 

 本文由用戶 OnitaC01 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!