04-Windows频繁打开和关闭端口可能引发的问题 | 07.杂项

简介:

04-Windows频繁打开和关闭端口可能引发的问题

郑昀 20100810 隶属于《07.杂项》小节

老赵写了一篇《关于Windows频繁打开关闭端口时出现的问题》,论述了他从 Windows Web Server 2008 R2 通过 TCP 连接对 Cent OS 下的 MongoDB 数据库服务做压力测试,遇到了 Socket 连接资源耗尽,导致程序报告“由于系统缓冲区空间不足或队列已满,不能执行套接字上的操作。”错误的情况。

Socket 连接资源耗尽,在 Windows Server 下很常见,如果使用者程序写得没问题的话,一般都是微软(或其他软件厂商)设置的一些默认参数不合时宜导致的。

我以前写过一篇《02-Twisted 构建 Web Server 的 Socket 长链接问题 | 07.杂项 | Python》,记述了另外一种 Windows Server 常见问题:在 Python 开发语言下,用 twisted 框架编写一个 Web Server ,接收 Google PubSubHubbub 的 Hub Server 推送过来的 Google Reader 文章共享信息时,遇到了文件描述符到达上限的现象。这个模式的特点是,用 twisted.web.server 对接 PubSubHubbub Hub Server ,双方都支持重用连接,照理说,既然保持长连接并且重用 socket 连接,不应该出现这种“too many file descriptors in select”错误。这里的知识点是 Windows 下 select module 文件描述符(file descriptor)最多是512个,而在 Linux 下这个限制为 32767 ,如果超过这个限制值,就会出现类似上面的异常。

 

老赵的文章指出了一个有意思的知识点:临时端口号可分配范围, 

临时端口号范围定义

当一个客户端程序(比如说一个浏览器)初始化一个 connection 连接远端服务(比如一个网站)时,客户端会打开一个“ephemeral(临时)”端口,端口号一般是随机分配的。你可以用微软工具 TCPView 来查看。

那么这个进程为出站连接(outbound connection)分配端口号时,端口号的可分配范围与操作系统有关。其中一个主要影响因素是 MaxUserPort ,位于注册表的 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters 下。

下面这张表列出了不同 Windows 操作系统所能分配的端口范围:

操作系统

MaxUserPort
数值的
含义

端口范围,如果MaxUserPort
没有定义

端口范围,如果MaxUserPort
已定义

最小值

最大值

Windows NT/2000/XP/2003

Ending Port

1025 to 5000

1025 to [MaxUserPort]

5000

65535

Windows 2000/XP/2003 withKB951748/KB951746

Ending Port

49152 to 65535

1025 to [MaxUserPort]

5000

65535

Windows Vista/2008

Number of Ports

49152 to 65535

49152 to [49152 + MaxUserPort − 1]

255

16384

表1 端口范围

当然,你如果在服务器上安装了微软的一些服务,还是会自动修改这个 MaxUserPort 参数的,比如Small Business Server 2000/2003 会修改为 60000, ISA Server 会修改为 65535, Exchange Server 2003 会改为 60000 。

看了这张表后,你会知道:

1、不要使用小于1025的端口号;

2、尽量使用系统临时端口范围(ephemeral port range)之外的端口,比如你定义自己应用程序要打开的端口号为8000,而不是5000。

3、重用连接。

查看了我的笔记本电脑(Win XP)和服务器(Windows 2003),注册表里都没有设置过这个MaxUserPort参数,所以端口范围就是默认的,在服务器上,可分配的临时端口是从1025到5000。

 

回到我的文件描述符打开过多的问题上,

重用端口失败+保持长连接生效

如果监听的 Google Reader User 足够多,这些用户又在一个时段集中分享文章,那么 Google PubSubHubub Hub Server 就会以极快的速度把数据推送过来,此时如果重用 socket 端口失败,而保持长连接策略又起作用,于是很快在 twisted web server 监听的端口上打开的文件描述符又爆了。

处理办法:

1、参考《02-Twisted 构建 Web Server 的 Socket 长链接问题 | 07.杂项 | Python》,

twisted.web.server.Site 类的初始化函数有一个可选参数 timeout ,它的默认值是 60*60*12 ,也就是12小时,它的目的是闲置端口超时自动关闭。在我们的情景下,超时时间太长,所以才会有许多处于 ESTABLISHED 状态的 Socket Connections 积累。

所以我们缩短为 15 分钟(也可以更短),让没有得到重用的 Connections 尽快自动关闭。只需要在开始执行: 
reactor.listenTCP(8080, Site(MyWebResource.setup() ,timeout=60*15 )) 
即可。

2、参考《03-PubSubHubbub 和 twisted 的 Persistent connections 能力 | 07.杂项 | Python》,接收到对方 Server 推送过来的数据后,异步扔给另一个方法解析和处理,render_POST 方法立刻 return NOT_DONE_YET 标志, 等异步处理数据成功了,回调里再 finish 掉当前的 request 。

 

目录
相关文章
|
2月前
|
Linux 虚拟化 Windows
Linux、Windows上还不会端口映射的网工,请低调看过来!
Linux、Windows上还不会端口映射的网工,请低调看过来!
|
5月前
|
Windows
windows环境下根据端口号查询进程编号并杀掉此进程
windows环境下根据端口号查询进程编号并杀掉此进程
|
11月前
|
Windows
Windows查看端口占用以及关闭相应的进程
Windows查看端口占用以及关闭相应的进程
249 0
|
网络协议 Linux 数据安全/隐私保护
如何在Windows本地快速搭建SFTP文件服务器,并通过端口映射实现公网远程访问
如何在Windows本地快速搭建SFTP文件服务器,并通过端口映射实现公网远程访问
|
2月前
|
Windows
Windows中如何查看被占用的端口、杀掉对应的进程
这篇文章介绍了在Windows系统中如何查看被占用的端口号以及如何杀掉占用端口的进程,包括使用命令提示符的`netstat -ano | findstr 端口号`命令查找进程PID,然后通过任务管理器或`taskkill /PID PID号`命令来结束进程。
Windows中如何查看被占用的端口、杀掉对应的进程
|
4月前
|
Windows
windows端口冲突解决办法
windows端口冲突解决办法
149 1
windows端口冲突解决办法
|
2月前
|
Windows
Windows——80端口被系统占用
Windows——80端口被系统占用
58 0
|
2月前
|
Linux Windows
Windows查找监听端口对应的进程及其路径
Windows查找监听端口对应的进程及其路径
|
4月前
|
缓存 数据安全/隐私保护 虚拟化
windows端口被占用,无法通过netstat找到进程,占用的端口又不能修改,该怎么办?
项目运行时服务器8080端口被占用,常规`netstat`命令找不到占用进程。解决方法包括:1) 强制关机重启释放端口;2) 使用`netstat -anobq`或Windows 10的`Get-NetTCPConnection` PowerShell命令查找BOUND状态的进程;3) 调整Windows动态端口范围,避免冲突。注意,强制关机可能影响数据安全。
903 2
|
4月前
|
网络协议 安全 Docker
windows环境下的设置docker远程访问(开放2375端口)
windows环境下的设置docker远程访问(开放2375端口)
808 0