Indy TIdHTTPWebBrokerBridge的MaxConnections设置偶尔失效问题
问题描述
使用Indy的TIdHTTPWebBrokerBridge创建THireTrack_NX_API_Handler类型的WebModule时,其他功能正常,但MaxConnections设置似乎未严格生效:
- 将
MaxConnections设为1,用Postman创建2个虚拟用户持续发起并发连接,大部分时候仅存在1个WebModule实例,且能正常记录“Max Connections Exceeded”日志,但偶尔会出现2个实例。 - 将
MaxConnections设为10,用50个虚拟用户测试时,最多出现约24个WebModule实例,实例数量随创建销毁上下波动。
相关初始化代码:
FWebBrokerBridge.IOHandler := LIOHandleSSL; SSLHelper := TSSLHelper.create; FWebBrokerBridge.OnQuerySSLPort := SSLHelper.QuerySSLPort; codesite.send('Listening Port', FPort); FWebBrokerBridge.DefaultPort := FPort; // default 10055 FWebBrokerBridge.MaxConnections := FMaxConnections; FWebBrokerBridge.RegisterWebModuleClass(THireTrack_NX_API_Handler); FWebBrokerBridge.Active := True;
测试逻辑:在THireTrack_NX_API_Handler的OnCreate中递增全局计数器,OnDestroy中递减;重写DoMaxConnectionsExceeded方法添加日志输出。
问题分析与解决建议
1. 澄清对MaxConnections的功能误解
TIdHTTPWebBrokerBridge.MaxConnections限制的是同时活跃的TCP连接数,而非WebModule实例的数量。WebModule是每个请求创建一个、处理完成后销毁——如果是HTTP/1.1默认的Keep-Alive连接,同一个TCP连接会被复用处理多个请求,这时候一个连接会对应多个WebModule实例,实例数本身就会比连接数多,属于正常逻辑。
2. 偶尔超标的竞态条件无法完全避免
当新连接请求到来时,组件会先检查当前活跃连接数是否达到上限,再决定是否接受连接。但在“检查连接数”和“实际拒绝连接”的间隙,可能刚好有一个旧连接完成处理并关闭,新连接会被正常接受,短暂出现连接数(对应实例数)超过设置值的情况,这是正常的竞态条件,不会持续存在。
3. 检查连接的生命周期管理
- 确认HTTP连接是否启用Keep-Alive:如果是,空闲连接会被保留一段时间,可能导致连接数累积。可以设置
TIdHTTPWebBrokerBridge.KeepAlive为False,强制使用短连接,观察实例数是否更接近MaxConnections。 - 检查WebModule的
OnDestroy触发逻辑:如果请求处理中出现未捕获的异常,可能导致WebModule实例无法正常销毁,进而累积实例数。建议在OnDestroy中添加详细日志,确认每个实例都能被正确回收。
4. 验证实际TCP连接数
不要仅依赖WebModule实例数判断连接数是否超标,建议用系统工具(Windows用netstat、Linux用ss)查看与服务端口的实时TCP连接数,确认是否真的超过了MaxConnections设置。如果实际连接数未超标,说明实例数波动是请求复用连接导致的正常现象。
5. 调整组件超时设置
设置TIdHTTPWebBrokerBridge.IOHandler的ReadTimeout和WriteTimeout,确保空闲连接能及时关闭;同时调整MaxConnectionIdleTime属性,缩短空闲连接的保留时间,避免长期占用连接数。
内容的提问来源于stack exchange,提问作者David Rose

