Quantcast
Channel: CNode:Node.js专业中文社区
Viewing all articles
Browse latest Browse all 14821

解决使用 KeepAlive Agent 遇到的 ECONNRESET

$
0
0

问题背景

自从 Node.js 8.0 开始,http server 增加了一个默认配置keepAliveTimeout = 5000,它会自动销毁超过 5 秒的空闲连接。

通过 node-modules/agentkeepalive#58的示例代码,非常容易重现出服务端 Keep Alive 超时的效果,就是客户端复用「Keep Alive」 的 socket connection 会立刻触发 ECONNRESET异常,因为此 socket 已经被服务端认为空闲超时强制断开了。

现状

在 Egg 里面为了尽可能避免此问题的发生,综合 Node.js 的 keepAliveTimeout和 Nginx 的 keepalive_timeout 常规配置,将 httpclient 的 freeSocketKeepAliveTimeout配置为 4 秒,尽可能避免 ECONNRESET异常发生。

缺点:无法 100% 解决所有问题。由于这是一个靠约定俗成的配置,和一些不稳定性因素的存在,还是有可能遇到本文所描述的问题。例如服务端 keepalive_timeout 被配置为 4 秒,默认的 Egg 配置也就失效。

更好的解决方案

如果服务端告诉客户端当前 socket connection 会被保留多长时间呢?是否就能解决这个问题了? 如服务端在 Response header 中告诉客户端,当前 socket connection 还可以使用 5 秒,那么客户端通过计算,加上网络延迟 500 毫秒,最终得出当前 socket connection 只能用 4.5 秒。

下一个请求间隔在 4.5 秒内,则客户端继续使用这个 socket connection; 下一个请求间隔在 4.5 秒外,则客户端创建一个新的 socket connection 来请求。

业界事实标准:Keep-Alive Header

Google 一番发现业界有一个事实标准:The Keep-Alive Header。它竟然被所有浏览器都支持!

例如,通过 Response Header 告诉客户端当前 socket connection 还可以使用 5 秒,示例如下:

"Keep-Alive: timeout=5"

nginx 开启

配置 keepalive_timeout 的第二个参数:

keepalive_timeout 5 5;

_特别提示:_nginx 一旦配置了 keepalive_timeout,那么它会覆盖 web server 返回的 Keep-Alive header。所以你的应用前面有 nginx,那么必须配置第二个参数才会让 Keep-Alive header 返回给客户端。

Egg 开启

升级到 Egg 的最新版本,默认已经支持。

通过以下 2 个 PR 支持:

参考

原文

原始文章来自 egg.js 团队的 Node.js 经验分享:Node.js 专栏

蚂蚁金服实习生招聘

蚂蚁金服2019届实习生校园招聘已经开启,非常欢迎大家加入我们!详情请查看 https://cnodejs.org/topic/5a9627e32580af301494a8f8招聘帖子。


Viewing all articles
Browse latest Browse all 14821

Trending Articles