單機下如何讓Java程序支持百萬長連接,你知道嗎?

單機下能不能讓我們的Java網絡應用支持百萬連接?

當然可以!但是有很多的工作要做。

操作系統

首先就是要突破操作系統的限制。

在Linux平臺上,無論編寫客戶端程序還是服務端程序,在進行高併發TCP連接處理時,最高的併發數量都要受到系統對用戶單一進程同時可打開文件數量的限制(這是因為系統為每個TCP連接都要創建一個socket句柄,每個socket句柄同時也是一個文件句柄)。

單機下如何讓Java程序支持百萬長連接,你知道嗎?

可使用ulimit命令查看系統允許當前用戶進程打開的文件數限制:

<code>`$ ulimit -n`

`1024`
/<code>

這表示當前用戶的每個進程最多允許同時打開1024個文件,這1024個文件中還得除去每個進程必然打開的標準輸入,標準輸出等等文件,那麼剩下的可用於socket連接的文件數就只有大概1010個左右。也就是說缺省情況下,基於Linux的通訊程序最多允許同時1010個TCP併發連接。

對於想支持更高數量的TCP併發連接的通訊處理程序,就必須修改Linux對當前用戶的進程同時打開的文件數量。

修改單個進程打開最大文件數限制的最簡單的辦法就是使用ulimit命令:

<code>$ ulimit –n 1000000
/<code>

如果系統回顯類似於"Operation not permitted"之類的話,說明上述限制修改失敗,實際上是因為在中指定的數值超過了Linux系統對該用戶打開文件數的軟限制或硬限制。因此,就還需要修改Linux系統對用戶的關於打開文件數的軟限制和硬限制。

軟限制(soft limit):是指Linux在當前系統能夠承受的範圍內進一步限制用戶同時打開的文件數;

硬限制(hardlimit):是根據系統硬件資源狀況(主要是系統內存)計算出來的系統最多可同時打開的文件數量。

第一步,修改/etc/security/limits.conf文件,在文件中添加如下行:

<code>  * soft nofile 1000000

  * hard nofile 1000000
/<code>

'*'號表示修改所有用戶的限制;

soft或hard指定要修改軟限制還是硬限制;1000000則指定了想要修改的新的限制值,即最大打開文件數(請注意軟限制值要小於或等於硬限制)。修改完後保存文件。

第二步,修改/etc/pam.d/login文件,在文件中添加如下行:

<code>  session required /lib/security/pam_limits.so 
/<code>

這是告訴Linux在用戶完成系統登錄後,應該調用pam_limits.so模塊來設置系統對該用戶可使用的各種資源數量的最大限制(包括用戶可打開的最大文件數限制),而pam_limits.so模塊就會從/etc/security/limits.conf文件中讀取配置來設置這些限制值。修改完後保存此文件。

第三步,查看Linux系統級的最大打開文件數限制,使用如下命令:

<code>  cat /proc/sys/fs/file-max

  12158
/<code>

這表明這臺Linux系統最多允許同時打開(即包含所有用戶打開文件數總和)12158個文件,是Linux系統級硬限制,所有用戶級的打開文件數限制都不應超過這個數值。通常這個系統級硬限制是Linux系統在啟動時根據系統硬件資源狀況計算出來的最佳的最大同時打開文件數限制,如果沒有特殊需要,不應該修改此限制,除非想為用戶級打開文件數限制設置超過此限制的值。

如何修改這個系統最大文件描述符的限制呢?修改sysctl.conf文件

<code>vi /etc/sysctl.conf

\\# 在末尾添加

fs.file_max = 1000000

\\# 立即生效

sysctl -p
/<code>

JVM層面相關性能優化

當客戶端的併發連接數達到數十萬或者數百萬時,系統一個較小的抖動就會導致很嚴重的後果,例如服務端的GC導致應用暫停。GC持續幾秒,就會導致海量的客戶端設備掉線或者消息積壓,一旦系統恢復,會有海量的設備接入或者海量的數據發送很可能瞬間就把服務端沖垮。

JVM層面的調優主要涉及GC參數優化,GC參數設置不當會導致頻繁GC,甚至OOM異常,對服務端的穩定運行產生重大影響。

1.確定GC優化目標

GC(垃圾收集)有三個主要指標。

(1)吞吐量:是評價GC能力的重要指標,在不考慮GC引起的停頓時間或內存消耗時,吞吐量是GC能支撐應用程序達到的最高性能指標。

(2)延遲:GC能力的最重要指標之一,是由於GC引起的停頓時間,優化目標是縮短延遲時間或完全消除停頓(STW),避免應用程序在運行過程中發生抖動。

(3)內存佔用:GC正常時佔用的內存量。

JVM GC調優的三個基本原則如下。

(1) Minor go回收原則:每次新生代GC回收儘可能多的內存,減少應用程序發生Full GC的頻率。

2)GC內存最大化原則:垃圾收集器能夠使用的內存越大,垃圾收集效率越高,應用程序運行也越流暢。但是過大的內存一次 Full GC耗時可能較長,如果能夠有效避免FullGC,就需要做精細化調優。

(3)3選2原則:吞吐量、延遲和內存佔用不能兼得,無法同時做到吞吐量和暫停時間都最優,需要根據業務場景做選擇。對於大多數應用,吞吐量優先,其次是延遲。當然對於時延敏感型的業務,需要調整次序。

2.確定服務端內存佔用

在優化GC之前,需要確定應用程序的內存佔用大小,以便為應用程序設置合適的內存,提升GC效率。內存佔用與活躍數據有關,活躍數據指的是應用程序穩定運行時長時間存活的Java對象。活躍數據的計算方式:通過GC日誌採集GC數據,獲取應用程序穩定時老年代佔用的Java堆大小,以及永久代(元數據區)佔用的Java堆大小,兩者之和就是活躍數據的內存佔用大小。

3.GC優化過程

1、GC數據的採集和研讀

2、設置合適的JVM堆大小

3、選擇合適的垃圾回收器和回收策略

當然具體如何做,請參考JVM相關知識。而且GC調優會是一個需要多次調整的過程,期間不僅有參數的變化,更重要的是需要調整業務代碼。


寫在最後,如果覺得本文不錯! 記得轉發+關注一下,後續小編會給大家帶來更多原創的精彩技術內容。 也歡迎大家在下方留言,說出你的看法~


分享到:


相關文章: