You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang基准测试REST API时报socket: too many open files错误

socket: too many open files 错误排查与修复

错误现象

对基于Golang实现的REST API做基准测试时,程序抛出文件描述符耗尽错误:
错误截图

根因分析

该错误本质是单进程可打开的文件描述符(FD)配额被耗尽,每个TCP Socket连接都会占用1个FD,高并发压测场景下FD消耗速度超过回收速度就会触发该错误,结合现有代码具体诱因有3个:

  • 客户端实例重复创建:如果NewHttpCardPaymentService()不是在服务启动时全局单例初始化,而是每次处理请求时都调用,会导致每次请求都新建独立的resty客户端实例,各实例的连接池完全隔离,连接无法复用,还会产生大量孤立连接造成FD泄漏。
  • 强制短连接配置加剧FD消耗:代码中显式设置了Connection: close请求头,强制每次请求完成后关闭TCP连接,关闭的连接会进入TIME_WAIT状态,默认Linux内核会保留该状态60秒才释放对应的FD,压测QPS较高时TIME_WAIT连接会快速堆积耗尽FD。
  • 系统默认FD配额不足:Linux系统默认单进程open files配额通常为1024,完全无法支撑高并发压测场景的连接需求。

修复方案

1. 修正HTTP客户端使用逻辑,启用连接复用

  • 将HttpCardPaymentService改为服务启动时初始化的全局单例,禁止每次处理请求时新建实例,保证全局共用同一个resty客户端,让连接池机制正常生效。
  • 删除请求配置中的SetHeader("Connection", "close")代码,移除强制短连接逻辑,允许TCP连接复用。
  • 显式给resty客户端配置合理的连接池参数,参考实现:
func NewHttpCardPaymentService() *HttpCardPaymentService {
    client := resty.New().
        SetTimeout(5 * time.Second).
        SetTransport(&http.Transport{
            MaxIdleConns:        100, // 全局最大空闲连接数
            MaxIdleConnsPerHost: 100, // 单目标主机最大空闲连接数
            IdleConnTimeout:     90 * time.Second, // 空闲连接超时回收时间
        })
    return &HttpCardPaymentService{
        Client: client,
    }
}

2. 调大系统文件描述符上限

压测环境需要将单进程FD上限调大到足够支撑并发量:

  • 临时生效(当前shell会话有效,重启后失效):执行命令ulimit -n 65535,再在该会话中启动服务与压测程序。
  • 永久生效:编辑/etc/security/limits.conf文件,添加以下配置:
* soft nofile 65535
* hard nofile 65535

保存后重新登录服务器即可生效。

3. 压测环境可选TCP参数优化

如果存在大量TIME_WAIT连接堆积,可调整内核参数加快连接回收:
编辑/etc/sysctl.conf添加以下配置:

net.ipv4.tcp_tw_reuse = 1 // 允许将TIME_WAIT状态的连接重新用于新的TCP连接
net.ipv4.tcp_fin_timeout = 30 // 缩短FIN-WAIT-2状态连接的回收时间

执行sysctl -p命令让配置立即生效。

注意:Linux 4.12及以上版本内核已移除tcp_tw_recycle参数,请勿配置该参数;上述TCP参数调整仅建议在压测环境使用,生产环境需根据实际业务场景评估后配置。

内容的提问来源于stack exchange,提问作者Vinicius Barbosa de Medeiros

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 00:03:34