實現單台測試機6萬websocket長連接


本文由作者鄭銀燕授權網易雲社區發布。


本文是我在測試過程中的記錄,實現了單台測試機發起最大的websocket長連接數。在一台測試機上,連接到一個遠程服務時的本地端口是有限的。根據TCP/IP協議,由於端口是16位整數,也就只能是0到 65535,而0到1023是預留端口,所以能分配的端口只是1024到65534,也就是64511個。也就是說,一台機器一個IP只能創建六萬多個websocket長連接。

一、客戶端參數調優


本文采用的測試機分別為黑mac系統和linux系統(由於黑mac機器本身性能問題,最大只能達到2萬連接,於是換用linux)。下面先以mac系統為例,闡述下客戶端參數調優,linux系統類似,這里不做闡述。

1、修改全局限制,系統默認的最大連接數限制


命令:sysctl kern.maxfiles


說明:全局限制,也就是系統默認的最大連接數限制是12288

修改大小: sudo sysctl -w kern.maxfiles=1048600



說明:設置系統最大連接數從12288到1048600

2、測試腳本是一個進程,開啟上萬個長連接,還需要修改單個進程的最大連接數。

命令:sysctl kern.maxfilesperproc


說明:單個進程默認最大連接數限制是10240

修改大小:sudo sysctl -w kern.maxfilesperproc=1048576


說明:設置進程連接數限制,進程的最大連接數要小於等於全局連接數

3、由於客戶端與服務端需要建立大量的socket,所以我們需要調速一下最大文件描述符。


命令:ulimit -n


說明:“ulimit -n”命令顯示當前shell能打開的最大文件數,默認值:256,該值總是小於kern.maxfilesperproc的值,因為一個shell就是一個進程。

修改大小:ulimit n 1048576

說明:設置當前shell能打開的最大文件數為1048576,該值不能大於kern.maxfilesperproc,否則會提示設置失敗。

4、由於系統默認參數,自動分配的端口數有限,所以我們需要更改客戶端ip端口號的參數


 命令:sysctl net.inet.ip.portrange,查詢得到的系統默認的端口號分配如下:


將可分配的首個端口號設置為1024

修改大小:sudo sysctl net.inet.ip.portrange.first=1024



5、按以上的方式設置參數有個問題,當系統重啟后,這些參數又恢復成了默認值,解決辦法就是把參數寫到/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中實現自動修改。


二、測試腳本


客戶端腳本采用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);
}


三、測試結果


在相應的目錄下輸入命令node websocket.js,即可建立websocket連接。由於機器性能問題,連接數達到2w左右,就無法建立新的連接了。后面將機器改成雲主機,可以達到6萬的連接數。

四、后續展望

我的測試目標不是實現單台6萬的連接數。我的目標是可以達到百萬級穩定的長連接,並且可以向websocket服務器收發信息,計算每個消息從服務器發送到客戶端接收的平均耗時時間,以及查看建立百萬級連接,服務器的內存和cpu的使用情況。最終限制於機器的性能,暫時還沒做到。並且業務需求繁忙,這個測試就暫時告一段落了。后續想要通過使用虛擬IP的方式來實現百萬級連接,比如增加了18個IP地址,這樣就可以產生18 * 60000 = 1080000個連接。或者借用更多的機器數,每台機器維持6萬連接。


免費領取驗證碼、內容安全、短信發送、直播點播體驗包及雲服務器等套餐

更多網易技術、產品、運營經驗分享請訪問網易雲社區



相關文章:
【推薦】 考拉消息中心消息盒子處理重構(策略模式)
【推薦】 windows系統下npm升級的正確姿勢以及原理
【推薦】 網易雲易盾與A10 Networks達成戰略合作 攜手打造抗DDoS攻擊的解決方案


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM