本文由做者鄭銀燕受權網易雲社區發佈。node
本文是我在測試過程當中的記錄,實現了單臺測試機發起最大的websocket長鏈接數。在一臺測試機上,鏈接到一個遠程服務時的本地端口是有限的。根據TCP/IP協議,因爲端口是16位整數,也就只能是0到 65535,而0到1023是預留端口,因此能分配的端口只是1024到65534,也就是64511個。也就是說,一臺機器一個IP只能建立六萬多個websocket長鏈接。linux
1、客戶端參數調優web
本文采用的測試機分別爲黑mac系統和linux系統(因爲黑mac機器自己性能問題,最大隻能達到2萬鏈接,因而換用linux)。下面先以mac系統爲例,闡述下客戶端參數調優,linux系統相似,這裏不作闡述。shell
一、修改全侷限制,系統默認的最大鏈接數限制安全
命令:sysctl kern.maxfilesbash
說明:全侷限制,也就是系統默認的最大鏈接數限制是12288服務器
修改大小: sudo sysctl -w kern.maxfiles=1048600websocket
說明:設置系統最大鏈接數從12288到1048600socket
二、測試腳本是一個進程,開啓上萬個長鏈接,還須要修改單個進程的最大鏈接數。性能
命令:sysctl kern.maxfilesperproc
說明:單個進程默認最大鏈接數限制是10240
修改大小:sudo sysctl -w kern.maxfilesperproc=1048576
說明:設置進程鏈接數限制,進程的最大鏈接數要小於等於全局鏈接數
三、因爲客戶端與服務端須要創建大量的socket,因此咱們須要調速一下最大文件描述符。
命令:ulimit -n
說明:「ulimit -n」命令顯示當前shell能打開的最大文件數,默認值:256,該值老是小於kern.maxfilesperproc的值,由於一個shell就是一個進程。
修改大小:ulimit -n 1048576
說明:設置當前shell能打開的最大文件數爲1048576,該值不能大於kern.maxfilesperproc,不然會提示設置失敗。
四、因爲系統默認參數,自動分配的端口數有限,因此咱們須要更改客戶端ip端口號的參數
命令:sysctl net.inet.ip.portrange,查詢獲得的系統默認的端口號分配以下:
將可分配的首個端口號設置爲1024
修改大小:sudo sysctl net.inet.ip.portrange.first=1024
五、按以上的方式設置參數有個問題,當系統重啓後,這些參數又恢復成了默認值,解決辦法就是把參數寫到/etc/sysctl.conf文件中,可是,默認這個文件是不存在的,因此首先就要建立它:
sudo touch /etc/sysctl.conf
而後把參數寫到文件裏
kern.maxfiles=1048600
kern.maxfilesperproc=1048576
net.inet.ip.portrange.first=1024
net.inet.ip.portrange.last=65535
重啓系統,查看結果,顯示成功。
至於ulimit -n的值,能夠把ulimit -n 1048576 寫到.bashrc中實現自動修改。
2、測試腳本
客戶端腳本採用nodejs編寫,之因此不採用jmeter的方式,是由於jmeter每一個鏈接都是線程的方式,而單臺測試機最好保持開啓1000個之內的線程,不然機器容易崩潰。
測試腳本以下:
var cwd = process.cwd();var WebSocketClient = require('websocket').client;var size = 10000;var host = 'example.com:80';var port = 443;var authInterval = 10;var index = 0;
setInterval(function(){ if(index < size){
uid = index; cid = index; init(uid, cid); index++; }
},authInterval);console.log('begin...');
init = function(uid, cid){ var client = new WebSocketClient();
client.connect('ws://XX.XX.XX.XX:XXXX/ws?token='+index,"","http://example.com:80"); client.on('connectFailed', function(error) { console.log('Connect Error: ' + error.toString()); }); client.on('connect', function(connection) { console.log(index+' Connected'); connection.on('error', function(error) { console.log("Connection Error: " + error.toString()); }); connection.on('close', function(error) { console.log(error + '; Connection Closed'); //client.close(); reconnect(); }); connection.on('message', function(message) { }); });
};function timeLogout(){ return setTimeout(function (){
logout(uid); }, StartTime);
}
3、測試結果
在相應的目錄下輸入命令node websocket.js,便可創建websocket鏈接。因爲機器性能問題,鏈接數達到2w左右,就沒法創建新的鏈接了。後面將機器改爲雲主機,能夠達到6萬的鏈接數。
4、後續展望
個人測試目標不是實現單臺6萬的鏈接數。個人目標是能夠達到百萬級穩定的長鏈接,而且能夠向websocket服務器收發信息,計算每一個消息從服務器發送到客戶端接收的平均耗時時間,以及查看創建百萬級鏈接,服務器的內存和cpu的使用狀況。最終限制於機器的性能,暫時還沒作到。而且業務需求繁忙,這個測試就暫時告一段落了。後續想要經過使用虛擬IP的方式來實現百萬級鏈接,好比增長了18個IP地址,這樣就能夠產生18 * 60000 = 1080000個鏈接。或者借用更多的機器數,每臺機器維持6萬鏈接。
免費領取驗證碼、內容安全、短信發送、直播點播體驗包及雲服務器等套餐
更多網易技術、產品、運營經驗分享請訪問網易雲社區。
文章來源: 網易雲社區