版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/MBuger/article/details/83088894
在windows中使用go实现了一个服务器压力测试工具,使用的TCP协议,在调试期间,出现问题如下
Only one usage of each socket address (protocol/network address/por
t) is normally permitted.
从字面上来看是告诉我们是socket被复用了。在网上查了原因之后发现是套接字用完了,也就是同时建立的TCP连接量超过了系统的限制。但是经过验证,发现其实并不是因为同时建立的TCP连接过多造成的。
在我的测试工具中,我开启了20个协程去建立TCP连接,发送数据包,再关闭连接,并重复这个过程,也就是说同时也就最多建立20个TCP连接,远远小于windows中的tcp同时建立连接数的限制,并不可能出现TCP连接建立量超过系统限制的原因。那么又会是什么原因呢?
原来影响TCP连接建立数量的因素不止是最大建立连接数决定的。还有一系列的参数影响TCP连接的建立。在windows的注册表中的HKEY_LOCAL_MACHINE \System \CurrentControlSet \services \Tcpip \Parameters中,
系统为每个TCP 连接分配一个TCP 控制块(TCP control block or TCB),这个控制块用于缓存TCP连接的一些参数(源端口、目的端口、目的ip、序号、应答序号、对方窗口大小、己方窗口大小、tcp状态、tcp输入/输出队列、应用层输出队列、tcp的重传有关变量等),每个TCB需要分配 0.5 KB的pagepool 和 0.5KB 的Non-pagepool,也就说,每个TCP连接会占用 1KB 的系统内存。
系统的最大TCB数量由如下注册表设置决定
[HKEY_LOCAL_MACHINE \System \CurrentControlSet \Services \Tcpip \Parameters]
MaxFreeTcbs = 2000 (Default = RAM dependent, but usual Pro = 1000, Srv=2000)
这里也就表示最大可同时创建两千个TCP连接。
但是通过调整注册表中的以下参数可以改变这个值。
MaxUserPort = 65534 (Decimal)
MaxHashTableSize = 65536 (Decimal)
MaxFreeTcbs = 16000 (Decimal)
把这几项都调到最大。即可把TCP同时建立数扩大到16000。此时确实发现,这个报错会出现在当tcp连接建立到16000左右的时候。但是依然不是同时建立这么多连接,每次建立完都有关闭tcp。
tcb控制块并不是断开TCP连接后直接释放,而是要等待TCP连接time_wait时间之后再释放。
如图所示,当短时间内建立TCP连接数到16000左右的时候再次出现问题。
关闭测试工具,等待1分钟后,启动测试工具。依然报错。
关闭测试工具,在等待1分钟,也就是过了TCP默认的time_wait时间,再启动测试工具,不再报错又可以重新建立连接。
验证tcb控制块并不是断开TCP连接后直接释放,而是要等待TCP连接time_wait时间之后再释放。
注册表操作
win+R 输入regedit ,找到相关位置,右键新建参数
Socket 编程时,单机最多可以建立多少个 TCP 连接,受到操作系统的影响。
Windows 下单机的TCP连接数受多个参数影响:
最大TCP连接数
[HKEY_LOCAL_MACHINE \System \CurrentControlSet \Services \Tcpip \Parameters]
TcpNumConnections = 0x00fffffe (Default = 16,777,214)
以上注册表信息配置单机的最大允许的TCP连接数,默认为 16M。这个数值看似很大,这个并不是限制最大连接数的唯一条件,还有其他条件会限制到TCP 连接的最大连接数。
最大动态端口数
TCP客户端和服务器连接时,客户端必须分配一个动态端口,默认情况下这个动态端口的分配范围为 1024-5000 ,也就是说默认情况下,客户端最多可以同时发起3977 个Socket 连接。我们可以修改如下注册表来调整这个动态端口的范围
[HKEY_LOCAL_MACHINE \System \CurrentControlSet \Services \Tcpip \Parameters]
MaxUserPort = 5000 (Default = 5000, Max = 65534)
最大TCB 数量
系统为每个TCP 连接分配一个TCP 控制块(TCP control block or TCB),这个控制块用于缓存TCP连接的一些参数,每个TCB需要分配 0.5 KB的pagepool 和 0.5KB 的Non-pagepool,也就说,每个TCP连接会占用 1KB 的系统内存。
系统的最大TCB数量由如下注册表设置决定
[HKEY_LOCAL_MACHINE \System \CurrentControlSet \Services \Tcpip \Parameters]
MaxFreeTcbs = 2000 (Default = RAM dependent, but usual Pro = 1000, Srv=2000)
非Server版本,MaxFreeTcbs 的默认值为1000 (64M 以上物理内存)
Server 版本,这个的默认值为 2000。
也就是说,默认情况下,Server 版本最多同时可以建立并保持2000个TCP 连接。
最大TCB Hash table 数量
TCB 是通过Hash table 来管理的,下面注册表设置决定了这个Hash table 的大小
HKEY_LOCAL_MACHINE \System \CurrentControlSet \services \Tcpip \Parameters]
MaxHashTableSize = 512 (Default = 512, Range = 64-65536)
这个值指明分配 pagepool 内存的数量,也就是说,如果MaxFreeTcbs = 1000 , 则 pagepool 的内存数量为 500KB
那么 MaxHashTableSize 应大于 500 才行。这个数量越大,则Hash table 的冗余度就越高,每次分配和查找 TCP 连接用时就越少。这个值必须是2的幂,且最大为65536.
参考: IBM WebSphere Voice Server 在windows server 2003 下的典型配置
MaxUserPort = 65534 (Decimal)
MaxHashTableSize = 65536 (Decimal)
MaxFreeTcbs = 16000 (Decimal)
这里我们可以看到 MaxHashTableSize 被配置为比MaxFreeTcbs 大4倍,这样可以大大增加TCP建立的速度。