本文由作者郑银燕授权网易云社区发布。

本文是我在测试过程中的记录,实现了单台测试机发起最大的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万连接。

免费领取验证码、内容安全、短信发送、直播点播体验包及云服务器等套餐

更多网易技术、产品、运营经验分享请访问网易云社区

相关文章:
【推荐】 邪恶的三位一体:机器学习、黑暗网络和网络犯罪

实现单台测试机6万websocket长连接的更多相关文章

  1. 当web应用包含了websocket长连接,如何在web应用前加一层nginx转发

    1 通过在web应用的前面加一层nginx ,可以实现一台主机部署多个应用,每个应用都可以用不同的域名去访问,并且端口都是80 2 nignx 转发websocket长连接 1 每个web应用,他们运 ...

  2. Spring+Stomp+ActiveMq实现websocket长连接

    stomp.js+spring+sockjs+activemq实现websocket长连接,使用java配置. pom.xml(只列出除了spring基本依赖意外的依赖,spring-version为 ...

  3. WebSocket长连接

    WebSocket长连接 1.概述 1.1 定义 1.2 原理 2.Django中配置WebSocket 2.1安装第三方法包 pip install channels 2.2 Django 中的配置 ...

  4. Python WebSocket长连接心跳与短连接

    python websocket 安装 pip install websocket-client 先来看一下,长连接调用方式: ws = websocket.WebSocketApp("ws ...

  5. WebSocket 长连接 及超时问题解决

    <?phpset_time_limit(0); class SocketService { private $address = 'localhost'; private $port = 80; ...

  6. 雨露均沾的OkHttp—WebSocket长连接的使用&源码解析

    前言 最近老板又来新需求了,要做一个物联网相关的app,其中有个需求是客户端需要收发服务器不定期发出的消息. 内心OS:

  7. Django websocket 长连接使用

    下载  pip install dwebsocket WebSocket是一种在单个TCP连接上进行全双工通信的协议 WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客 ...

  8. Browser 與 Server 持續同步的作法介紹 (Polling, Comet, Long Polling, WebSocket)长连接

    對 Comet 的懵懂 記得兩年多前,第一次看到 Gmail 中的 GTalk 覺得很好奇:「咦?線上聊天且是 Google 的熱門系統,只用傳統的 AJAX 應該會操爆伺服器吧?」很幸運的,當時前公 ...

  9. 微信小程序 实现websocket长连接 以及断开连接之后自动重连

    app.js let socketMsgQueue = [] let isLoading = false App({ globalData: { userInfo: null, localSocket ...

随机推荐

  1. iOS - OC - 字典快速遍历

    1. [dic enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop ...

  2. centos7 二进制安装包安装 mysql5.6

    centos7 二进制安装包安装 mysql5.6 一.下载mysql5.6二进制安装包 http://mirrors.sohu.com/mysql/MySQL-5.6/ 如:mysql-5.6.34 ...

  3. vi编辑时出现E325:ATTENTION

    我们用vi编辑文件时,系统会提示E325:ATTENTION. 这是由于在编辑该文件的时候异常退出了,因为vi在编辑文件时会创建一个交换文件swap file以保证文件的安全性. 但是每次打开文件时都 ...

  4. 使用springmvc从页面中获取数据,然后根据获得的参数信息进行修改,如果修改的数据中含有不是基本数据类型的参数。比如传的参数中有Date类型的数据时,需要我们进行参数类型转换。

    1.1 需求 在商品修改页面可以修改商品的生产日期,并且根据业务需求自定义日期格式. 1.2 需求分析 由于日期数据有很多格式,所以springmvc没办法把字符串转换成日期类型.所以需要自定义参数绑 ...

  5. 只有自己看的懂的vue 二叉树的3级联动

    我是在vue做的数据 actions mutations state index页面获取值 传递给子页面 子页面的操作 <template> <div class='cascade_ ...

  6. Vim基础教程

    一.简介 世界上只有三种编辑器,EMACS.VIM和其它. 我们所处的时代是非常幸运的,有越来越多的编辑器,相对于古老的VIM和EMACS,它们被称为现代编辑器.我们来看看这两个古董有多大年纪了: * ...

  7. OpenSCManager

    添加服务程序 执行级别:必须管理员

  8. windows驱动

    DriveEntry() 启动 停止 接口函数 驱动程序名 驱动程序版本号 异常处理 是否运行 声明LPOReceive类型的函数 声明函数指针(外部传进来的回调函数) 存放配置字符串 本机IP 串口 ...

  9. python while语句写法

    count=5 while count>0: print 'i love python' count=count-1 else: print 'over'

  10. python函数嵌套的实用技术

    def fun(): def fun1(): print () fun1() fun() fun1()#总结老男孩python里面讲过,这个是函数的嵌套,很有用, #效果就是给函数一个自己的小函数.然 ...