Golang 服务之坑:too many open files

以下内容转载自 https://pylist.com/t/1581940902

出现这个问题是因为服务的文件句柄超出系统限制。当Go服务程序出现这个问题,首先应该看系统设置,然后再看程序本身。

too many open files

大量的 accept4 错误

http: Accept error: accept tcp [::]:8080: accept4: too many open files; retrying in 1s
http: Accept error: accept tcp [::]:443: accept4: too many open files; retrying in 1s

系统设置

首先查看系统

ulimit -n

默认是 1024 ,要改大一些。

ulimit -n 524288

这是临时的修改,要永久的修改,可修改文件 /etc/security/limits.conf 参见

看系统之后还要看你的程序的句柄限制,因为你的程序部署问题,系统设置修改了,但程序的设置还没变。可以使用下面命令行查看程序的限制

cat /proc/{your_app_pid}/limits

结果可能类似这样:

设置ulimit

上图的 Solft Limit 还是 1024,我用的是 supervisor ,必须重启 supervisor。重启后参数如下图:

设置ulimit

程序设置

如果不注意,代码里可能存在一些连接泄漏。常见的泄漏是在 http.Response 调用之后忘记调用 resp.Body.Close(),或者是放置位置不对。

空闲连接可能是另一个可能的原因。 默认情况下,会使用缓存来重用连接。访问许多主机时,这可能会留下许多打开的连接。 可以使用 Transport 的 CloseIdleConnections 方法以及MaxIdleConnsPerHost 和 DisableKeepAlives 字段来管理此行为。

如果是这种情况,可以尝试在传输句柄上显式调用 CloseIdleConnections 或减小MaxIdleConnsPerHost 的值。

还应该在 http server/client 添加超时机制来避免连接泄漏,如:

srv := &http.Server{
    ReadTimeout:  5 * time.Second,
    WriteTimeout: 10 * time.Second,
    IdleTimeout:  120 * time.Second,
    TLSConfig:    tlsConfig,
    Handler:      serveMux,
}

var tr = &http.Transport{
		TLSClientConfig:       &tls.Config{InsecureSkipVerify: true},
		TLSHandshakeTimeout:   5 * time.Second,
		ResponseHeaderTimeout: 10 * time.Second,
		ExpectContinueTimeout: 1 * time.Second,
	}
var httpClient = &http.Client{
		Timeout:   time.Second * 30,
		Transport: tr,
	}

下面的命令可以让你判断是不是连接池中的连接有没有正确关闭

# cat /proc/19213/net/sockstat
sockets: used 109
TCP: inuse 4 orphan 0 tw 14 alloc 9 mem 2
UDP: inuse 5 mem 16
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0

如果 TCP inuse 很大,就很有可能是连接没有正确关闭。

本文标签: 之坑 files Golang open 服务

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值