lua tcp socket read timed out

来源:互联网 发布:2016网络流行词及意思 编辑:程序博客网 时间:2024/06/05 15:50

线上机器在晚高峰 20:00 ~ 00:00 点之间 CPU 负载很高,且 nginx 的 error.log 日志中有大量类似如下内容:

2017/10/16 22:19:48 [error] 16583#0: *137334081 lua tcp socket read timed out, client: 61.148.244.157, server: localhost, request: "GET /live_xxx_v2/_LC_XY0_non_2161933815081577631496373_OX.flv HTTP/1.1", host: "xxx-flv.live.xxx.com"2017/10/16 22:19:48 [error] 16583#0: *137334081 attempt to send data on a closed socket: u:0000000041CAF7B0, c:0000000000000000, ft:0 eof:0, client: 61.148.244.157, server: localhost, request: "GET /live_xxx_v2/_LC_XY0_non_2161933815081577631496373_OX.flv HTTP/1.1", host: "xxx-flv.live.xxx.com"

代码逻辑如下:

local redis = require "resty.redis"local red = redis:new()red:set_timeout(1000)local ok, err = red:connect("127.0.0.1", 6379)if not ok then    ngx.log(ngx.ERR, "failed to connect redis: ", err)    return falseendreq = red:incr(token)red:set_keepalive(10000, 100)

可能的原因:

  • redis 操作没有检查返回值
  • 通过 lua_shared_dict 共享了 redis 对象
  • redis backlog 设置过小

一. lua tcp socket read timed out

https://github.com/openresty/lua-nginx-module#lua_socket_log_errors

This directive can be used to toggle error logging when a failure occurs for the TCP or UDP cosockets. If you are already doing proper error handling and logging in your Lua code, then it is recommended to turn this directive off to prevent data flushing in your nginx error log files (which is usually rather expensive).

根据lua_socket_log_errors的描述来看,应该在 Lua 中处理 socket 错误,并在nginx.conf中配置下面语句来关闭错误日志:

lua_socket_log_errors off;

二. attempt to send data on a closed socket

第二行错误日志表示没有检查套接字操作的返回值,但是却继续使用已经关闭的套接字。

正确的方法是通过调用set_keepalive方法将连接重新连接回池。通过将连接放回到池中可以允许其他并发请求重用这些连接,这样更有效率。

另外,还应该检查 redis 操作的返回值,当有错误发生时需要处理,连接可能会因错误自动关闭,防止在出错后调用 set_keepalive。

三. redis 对象共享问题

另外程序内部有使用 lua_shared_dict 共享 redis,这里也存在问题。

查找资料得到如下结论:

要避免在多个请求间共享一个 resty.redis 对象(比如把对象保存在 Lua 模块级别的变量中)。须确保每个请求都使用自己的 resty.redis 实例,否则在并发较高时会出现访问冲突。

在 lua-resty-redis 的文档中也有明确说明:
https://github.com/openresty/lua-resty-redis#limitations

这个 cache 是 nginx 所有 worker 之间共享的。

参考

https://github.com/openresty/lua-resty-redis/issues/27
https://github.com/openresty/lua-resty-redis/issues/28
https://groups.google.com/forum/#!topic/openresty/WBFW2E1hSXA
https://groups.google.com/forum/#!topic/openresty/hB90bWd0k3c

原创粉丝点击