Lua-resty-auto-ssl: 锁定问题

创建于 2017-02-01  ·  20评论  ·  资料来源: auto-ssl/lua-resty-auto-ssl

我遇到了我们的(反向代理)nginx 服务器崩溃的问题。 他们完全停止响应请求,并且似乎不会自己摆脱这种状态。 这些服务器处理大量请求(每天超过 500 万)。

在过去的几天里,我有点不知所措,每当我通过监控收到警告时都会手动重新启动 Docker 实例,但我决定放置一个帮助程序 cron 脚本来检查 nginx 是否仍在响应如果出现问题,请通过 supervisord 重新启动它。

由于最初我正在重新启动 Docker 容器这一事实,我并没有真正获得任何形式的调试信息——日志记录会停止。 但是,在将其更改为在容器内重新启动 nginx 后,我在日志中有以下内容:

2017/02/01 01:14:16 [alert] 489#0: worker process 501 exited on signal 9
2017/02/01 01:14:16 [alert] 489#0: shared memory zone "auto_ssl" was locked by 501
2017/02/01 01:14:16 [alert] 489#0: worker process 502 exited on signal 9

我在谷歌上有过,我能找到的唯一参考是https://github.com/18F/api.data.gov/issues/325——但是看起来到期已经到位,这似乎没有正在处理我们的设置,因为我们(由于监控不佳)最近结束了大约 7 小时的停机时间。

我应该提一下,即使使用相同的 Docker 容器,我也无法在本地重新创建此错误。

我有点不知所措,我们的自动重启脚本现在已经解决了问题,但很高兴看到是否有人有想法。 我很乐意打开额外的日志记录并尝试调试日志(我有点害怕在我们的生产服务器中打开它)。

最有用的评论

在生产中也遇到了这个问题——感谢@koszik和 al。 只是为了确认,解决这个问题:

将 OpenResty 更新为>1.15.8.1

这似乎非常有害,可能值得尽快发布 f66bb61f11a654f66d35dd793ceaf0293d9c0f46,或者至少将文档更新为要求,而不是建议。

所有20条评论

哎呀,很遗憾听到这导致停电!

不幸的是,我在我们的安装中还没有看到任何类似的东西获得了大量的流量(自从你提到的去年三月的事件以来)。 但是,在#29 中报告了另一个类似的问题,我们修复了一个可能相关的问题,但它可能无法完全解释该问题。 但该问题也可能无关(它特定于注册发生的时间)。

感谢您提供帮助调试这一点,不过,深入了解肯定会很好。 我有几个初步的问题:

  • 你运行的是什么版本的 lua-resty-auto-ssl?
  • 您是在手动安装 lua 模块的情况下运行 OpenResty 还是 nginx?
  • 你运行的是什么版本的 OpenResty 或 nginx+lua?
  • 您在 lua-resty-auto-ssl(Redis、文件系统等)中使用什么存储机制?
  • 事情挂起的频率如何? 它似乎只在新证书注册或续订时发生,还是看起来是随机的?
  • 您是否正在重新加载 nginx(向主进程发送 SIGHUP 并生成新的工作进程,而不是完全重新启动主进程)?
  • 你有多少 nginx 工人正在运行(nginx 配置中的worker_processes设置)?
  • 您是否安装了任何其他 nginx 插件(如果您使用的是 OpenResty,则默认情况下除了 OpenResty 附带的插件之外)?

lua-resty-auto-ssl 是 0.10.3-1 来自 luarocks
我们使用的是 OpenResty 1.11.2.2。

nginx version: openresty/1.11.2.2
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-11) (GCC)
built with OpenSSL 1.0.2h  3 May 2016
TLS SNI support enabled
configure arguments: --prefix=/usr/local/openresty/nginx --with-cc-opt=-O2 --add-module=../ngx_devel_kit-0.3.0 --add-module=../echo-nginx-module-0.60 --add-module=../xss-nginx-module-0.05 --add-module=../ngx_coolkit-0.2rc3 --add-module=../set-misc-nginx-module-0.31 --add-module=../form-input-nginx-module-0.12 --add-module=../encrypted-session-nginx-module-0.06 --add-module=../srcache-nginx-module-0.31 --add-module=../ngx_lua-0.10.7 --add-module=../ngx_lua_upstream-0.06 --add-module=../headers-more-nginx-module-0.32 --add-module=../array-var-nginx-module-0.05 --add-module=../memc-nginx-module-0.17 --add-module=../redis2-nginx-module-0.13 --add-module=../redis-nginx-module-0.3.7 --add-module=../rds-json-nginx-module-0.14 --add-module=../rds-csv-nginx-module-0.07 --with-ld-opt=-Wl,-rpath,/usr/local/openresty/luajit/lib --with-http_ssl_module --with-http_perl_module --with-http_v2_module --with-http_secure_link_module --add-module=/nginx-build/openresty-1.11.2.2/../testcookie-nginx-module --add-module=/nginx-build/openresty-1.11.2.2/../lua-upstream-cache-nginx-module --add-module=/nginx-build/openresty-1.11.2.2/../nginx-module-vts --with-openssl=/openssl

现在的文件系统,因为每个服务器处理的子域是分开的。
发生崩溃时似乎是完全随机的,从 3 小时到 3 天不等。
不重新加载 nginx atm,只是重新启动,但我会尝试这个,看看这是否也有效。
最初我使用了 1 个工人,但是当出现问题时我尝试将其增加到 2,以查看它是否会产生任何影响。
使用以下非 OpenResty 模块:

除了这个项目,我没有在配置代码中使用任何其他 Lua。

抱歉延迟跟进! 在搜索了更多之后,我对可能发生的事情有一些理论:

  • 您看到“退出信号 9”错误这一事实可能表明您遇到了内存不足错误,并且系统正在积极地终止进程: http :
  • 当一个进程像这样崩溃或被强行杀死时,可能会导致 nginx 认为共享内存仍然被死掉的工作进程锁定。 例如,在您最初的示例中,看起来工作进程 501 首先被杀死,但随后它仍然认为内存被 pid 501 锁定,从而导致此死锁。

    • 看起来nginx 应该在崩溃时解锁共享内存,所以我不完全确定为什么这可能不会发生。 但是如果工人被 SIGKILL (9) 杀死,那么所有的赌注都可能被取消(因为 sigkill 通常意味着强行终止进程并且没有机会清理)。

那么您是否在系统级日志中看到有关内存不足或 oom-killer 的任何信息? 您在这些服务器上是否有任何其他可能表明 nginx 内存增长或内存泄漏的监控? 我认为我们在任何 lua-resty-auto-ssl 安装中都没有看到任何内存泄漏,所以我想知道其他一些 nginx 模块是否也可能起作用(这里提到了lua-upstream-cache-nginx-module 中的内存泄漏)。

抱歉 - 我想向@GUI澄清,信号 9 上被杀死的事件与错误无关,但我们故意杀死 nginx 进程来解决这个问题。 这些服务器上的内存没有问题,它们有大约 2GB 的内存,实际使用的内存很少,其余大部分是缓存。 在 dmesg 上没有 OOM 杀死。

我应该补充一点,我已经删除了一些模块来尝试解决这个问题,不推荐使用的 lua-upstream-cache-nginx-module 并删除了 pagespeed,但这似乎没有帮助。

我还有一些可能有用的错误行,我会尽快尝试从服务器获取它们。

@ajmgh :我不完全确定它是否相关,但我想我找到了一些潜在的问题,如果配置的lua_shared_dict内存大小太小,可能会导致奇怪的错误: https :

那么您是否知道您的系统中大致有多少个证书,以及您的 nginx 配置中配置的lua_shared_dict auto_ssl有多大? 如果可能,您也可以尝试升级到 v0.10.6,因为自 0.10.3 以来有一些更新可能会解决这个问题(如果我们幸运的话),或者至少提供更好的错误处理和消息。

我正面临完全相同的错误。
我只是将 lua-resty-auto-ssl 更新到版本 0.10.6-1 并将lua_shared_dict auto_ssl_settings增加到 1000m(在设置为 64k 之前)。
lua_shared_dict auto_ssl保持不变:1000m

只是等着看这些更改是否会解决此问题:/

@ajmgh你的问题解决了吗?

@aiev auto_ssl_settings目前只存储一个短字符串和一个布尔值,所以改变它不会有任何区别。 证书存储在auto_ssl 。 所以请尝试增加它。

不,最新的更新不能解决我们的问题。 我已将 auto_ssl 大小增加到 8M,这有点矫枉过正,因为我们只使用了大约 10 个证书并且没有看到任何变化。

# Log entries after my script detects nginx is unresponsive and force kills it
2017/05/24 13:29:15 [alert] 462#0: worker process 474 exited on signal 9
2017/05/24 13:29:15 [alert] 462#0: worker process 475 exited on signal 9
2017/05/24 13:29:15 [alert] 462#0: shared memory zone "auto_ssl" was locked by 475

我遇到过几次同样的问题。
我正在使用来自 luarocks 的 OpenResty 1.11.2.3/4 和 lua-resty-auto-ssl 0.11.0-1。
出现此问题时,超过 100 个 tcp 连接卡在 CLOSE_WAIT 状态。

我们也多次遇到同样的问题。
nginx 版本:openresty/1.11.2.4
lua-resty-auto-ssl 0.11.0-1
有很多 CLOSE_WAIT 状态,nginx 无法响应了。 要么我们需要杀死 CLOSE_WAIT 连接,要么重新启动 docker 来解决这个问题。

@ajmgh你的问题解决了吗? 我们在 openresty 容器中遇到了同样的问题。 我们在 CLOSE_WAIT 状态下有大约 1200 个连接,在我们的服务器中的 /tmp 中有很多脱水文件,这些文件只运行带有 lua-resty-auto-ssl 的 openresty。

这是我们的系统配置

  • 你运行的是什么版本的 lua-resty-auto-ssl?
    0.11.0-1
  • 您是在手动安装 lua 模块的情况下运行 OpenResty 还是 nginx?
    openresty
  • 你运行的是什么版本的 OpenResty 或 nginx+lua?
    openresty 1.11.2.4
  • 您在 lua-resty-auto-ssl(Redis、文件系统等)中使用什么存储机制?
    Redis
  • 事情挂起的频率如何? 它似乎只在新证书注册或续订时发生,还是看起来是随机的?
    看起来很随意。 它刚刚发生在昨天,导致我们的系统停机 30 分钟。 上一次发生是在2个月前。
  • 您是否正在重新加载 nginx(向主进程发送 SIGHUP 并生成新的工作进程,而不是完全重新启动主进程)?
    我们刚刚更换了所有 docker 容器
  • 你有多少 nginx 工人正在运行(nginx 配置中的 worker_processes 设置)?
    2
  • 您是否安装了任何其他 nginx 插件(如果您使用的是 OpenResty,则默认情况下除了 OpenResty 附带的插件之外)?
    不,lua-resty-auto-ssl 是我们唯一安装的插件

@ronail不,但是我们在

其他人都在使用 Docker 遇到这个错误吗? 也许 Lua/OpenResty 和 Docker 的混合使用真的很奇怪。

我没有使用 docker,我也面临着同样的问题。

我想这是脱水尝试颁发证书时的问题。

我也遇到了类似的问题,不得不强制 jenkins 每 30 分钟重新启动一次 OpenResty(每隔一小时左右不断崩溃......)

我设置了很高的内存限制,但是我注意到我在 LetsEncrypt 上为失败的身份验证设置了相当多的速率限制,如果有帮助的话?

我们昨天遇到了同样的问题,发现这些报告(#43、#136)没有包含可能是根本原因的指示。 我们无法在我们的测试系统上重现该问题,因此我们被迫在生产系统上进行调试。 “幸运的是”,挂起的频率足够高,所以我们可以快速迭代我们的调试方法。 首先,它只是所有 nginx 进程上的 strace -fp $pid ,这表明所有进程都在等待 futex() - 与其中一个 pid 始终在 shdict 上保持锁定的事实一致。 接下来,我添加了每个进程的 gdb 回溯的转储,在向图像添加调试符号后,很明显,问题出在以下代码路径上:

#3  0x00007f8f4ea50219 in ngx_shmtx_lock (mtx=0x7f8f31a0c068) at src/core/ngx_shmtx.c:111
#4  0x00007f8f4eb7afbe in ngx_http_lua_shdict_set_helper (L=0x418257a0, flags=0) at ../ngx_lua-0.10.13/src/ngx_http_lua_shdict.c:1016
#5  0x00007f8f4eb7a4a4 in ngx_http_lua_shdict_delete (L=0x418257a0) at ../ngx_lua-0.10.13/src/ngx_http_lua_shdict.c:632
#6  0x00007f8f4debd2f3 in lj_BC_FUNCC () from /usr/local/openresty/luajit/lib/libluajit-5.1.so.2
#7  0x00007f8f4dec0b9f in gc_call_finalizer (g=0x418063b8, L=0x418257a0, mo=0x7ffc7592da00, o=0x40e11948) at lj_gc.c:475
#8  0x00007f8f4dec0e2b in gc_finalize (L=0x418257a0) at lj_gc.c:509
#9  0x00007f8f4dec15d9 in gc_onestep (L=0x418257a0) at lj_gc.c:659
#10 0x00007f8f4dec16ef in lj_gc_step (L=0x418257a0) at lj_gc.c:689
#11 0x00007f8f4ded8c3d in lua_pushlstring (L=0x418257a0, str=0x7f8f330a6066 "0\202\002\v\n\001", len=527) at lj_api.c:639
#12 0x00007f8f4eb7a225 in ngx_http_lua_shdict_get_helper (L=0x418257a0, get_stale=0) at ../ngx_lua-0.10.13/src/ngx_http_lua_shdict.c:538
#13 0x00007f8f4eb79eb6 in ngx_http_lua_shdict_get (L=0x418257a0) at ../ngx_lua-0.10.13/src/ngx_http_lua_shdict.c:419

快速浏览 ngx_http_lua_shdict_get_helper() 后,问题的根本原因就变得清晰了:shdict 被锁定,并且 lua_pushlstring 有时会调用垃圾收集器,它可能想要从同一个 shdict 中删除项目,从而导致死锁。

我的快速而肮脏的解决方案是这样的(它太丑了,我不打算发布补丁);

    case SHDICT_TSTRING:
{
int len = value.len;
char *tmp = malloc(len);
if(!tmp) {
    ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "dict get: malloc: out of memory");
    return luaL_error(L, "out of memory");
}
ngx_memcpy(tmp, value.data, value.len);
ngx_shmtx_unlock(&ctx->shpool->mutex);
lua_pushlstring(L, tmp, len);
free(tmp);
}
        break;

到目前为止,这运行完美 - 对系统内部运作有更深入了解的人可能想要产生更好的修复。

有趣的是,这是众所周知的事实!
https://github.com/openresty/lua-nginx-module/issues/1207#issuecomment -350745592

这确实很有趣。 根据你提到的问题,使用 lua-resty-core 可以解决这个问题,根据它的文档,它从 openresty 1.15.8.1 开始自动加载,所以这个错误在那个版本中被默默地修复了。 我们将升级我们的代理并报告。

看起来它运行良好 - 假设导致它挂起的条件仍然存在,我会说这个错误已经修复。

经过 3 年多的平稳运行,刚刚遇到了这个问题。

在生产中也遇到了这个问题——感谢@koszik和 al。 只是为了确认,解决这个问题:

将 OpenResty 更新为>1.15.8.1

这似乎非常有害,可能值得尽快发布 f66bb61f11a654f66d35dd793ceaf0293d9c0f46,或者至少将文档更新为要求,而不是建议。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

brendon picture brendon  ·  9评论

ronaldgetz picture ronaldgetz  ·  10评论

n11c picture n11c  ·  13评论

serathius picture serathius  ·  21评论

sahildeliwala picture sahildeliwala  ·  16评论