侧边栏壁纸
  • 累计撰写 781 篇文章
  • 累计创建 1 个标签
  • 累计收到 1 条评论
标签搜索

长连接

Dettan
2021-07-10 / 0 评论 / 0 点赞 / 112 阅读 / 1,351 字
温馨提示:
本文最后更新于 2022-04-30,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。
异常时导致连接断开会导致断开期间消息丢失


linux系统单机支持的tcp连接数主要受三个方面的限制:
1.
文件描述符的限制
因为每个tcp连接都对应一个socket对象,而每个socket对象本身就占用一个文件描述符,文件描述符的限制在前文已经分析过,单机可以达到20+亿,如果不考虑其他限制,单机支持的tcp长连接数就是20+亿,这个值是非常可观的,它绝对可以满足世界上任何一个系统对长连接的需求,只要一台机器就可以哦。
2.
tcp本身的限制
谈到tcp本身的限制,就涉及到 TCP四元组(远端IP,远端端口号,本地IP,本地端口号),它标识一个tcp连接。根据常识理解,IP地址限定了一台主机(准确的说是网卡),端口号则限定了这个IP上的tcp连接。对于两个tcp连接,四个参数中必然是有一个不同的,因此四元组的数目决定了tcp连接的个数。对于服务端程序来,一般来说,本地ip和本地端口号固定,因此它上面可接受的的连接数=2^32*65536=2^48 = 560万亿(不考虑少量的特殊ip和特殊端口号),这也是个海量数字,基本可以支持世界上任何系统。对于客户端程序来说,一般本地ip、远端ip、远端口号都是固定的,因此可以支持的长连接数最多只有65536个,所以作为客户端的tcp代理比较容易出现端口号耗尽问题。
3.
系统内存限制

所以只要内存够, 单机长连接是不存在固定限制的, 只要能处理的过来.

关于系统内存限制,主要是两方面,一是tcp元数据的大小,包含sock、inode、file等结构;二是tcp缓存占用空间,这又包含系统缓存和用户缓存,系统缓存是系统调用read/write使用的缓存,用户的缓存是码农在写代码时设计的缓冲区,在异步服务端程序里面用于把读写和数据解析处理分离。
我做过测试,写两个程序,服务端只接收连接,客户端只发起连接,不读写数据,客户端和服务端分别部署在两个虚拟机上,当建立50w个连接时,服务端消耗2g内存,大概每个socket占用4kb,这个4kb是内核申请的空间,并不增加用户进程的内存。至于这个4kb是由哪个部分占用的,我还么找到答案,sock、inode、file这些元数据结构加起来也就一两百字节,由于没有收发数据因此跟tcp读写缓存关系不大,而且系统默认的读写缓冲区大小均为80k+。
由于虚拟机内存有限,不能进行更多连接的测试。不过从理论上分析,在内存足够的情况下,单机应该能达到20+亿的连接,也就是文件描述符的上限。由此可见单机最大连接数主要受内存限制,至于每个连接占用多少内存,每个系统,每个应用可能都不太一样,有的应用的数据流量比较大,占用的用户缓存和系统缓存也相应的会比较大,还要以实际压测的结果为准。


(在压测过程中出现一个问题:当连接达到一定数目时,连接的速度开始变得非常慢,查看系统message日志,会看到“kernel nf_conntrack:table full, dropping packet”输出,这时候需要调整一下这个参数/proc/sys/net/netfilter/nf_conn_track_count,这是系统用来记录tcp连接的哈希表的大小)。
由于一个socket连接一般占用8kb内存,所以百万连接至少需要差不多8GB内存.
0

评论区