我爱WP

Supervisord 修改ulimit 限制

supervisord管理着好几个程序,其中有个swoole-php的IM服务和golang编译的处理推送的程序,但是发现程序每隔几小时到几十小时不等的时间时就会自动重启。
排查:
经过排查发现重启的原因大概率是资源耗尽,被系统杀死。通过lsof -p 程序pid 命令查看到有很多的tcp链接(ESTABLISHED)。代码逻辑是php调用golang 写的一个程序apns开启的一个socket监听,并发送要推送的数据。apns接收到数据后链接苹果的apns服务器进行发送。流程结束后链接应该回收,结果有很多的连接到苹果服务器的tcp链接并没有销毁。因此初步判定是链接资源耗尽导致的重启。
接下来排查golang代码,发现调用推送方法后没有手动关闭链接。最后添加关闭链接的方法调用。重新编译成可执行文件上传服务器-在supervisord中重启该程序。运行了一天没有再次重启的现象发生,现已不间断运行了1周时间,再次查看lsof -p apns的pid 发现只有零星一两个链接存在,而且重复运行该命令,会发现之前的链接已经没有了,是动态变化的,于是可以断定apns重启的问题得到了解决。
于是考虑swoole-php重启应该也是同样的问题,即程序代码有bug导致程序所使用的资源(比如:php与MySQL的链接、与Redis的链接、ws与远程客户端的链接(是这个的可能性比较小,因为swoole内部已经有对客户端断开的处理了))得不到释放。我觉得是Redis链接导致的问题可能性较大,因为聊天处理逻辑中频繁的用到了Redis的读写操作。
代码修改:
swoole im的整体逻辑是启动swoole websocket监听后,会开启几个worker,在workerstart回调中引入了php文件用来处理消息。这里面包含了数据库读写、Redis读写。而且是每个worker都有自己的php引用。通过之前的日志查看可以发现个别的worker可能会遇到程序bug或者其他异常时重启。所以可能的情况是worker重启时并没有释放对之前文件的引用和数据库、Redis的链接。
所以,
在Swoole worker stop回调中添加了对资源引用的释放。例如:$server->handler = null;而在handler类的析构函数__destruct()方法中显式调用了对Redis的链接的关闭方法。$this->redis->close();
最后重新部署了程序,并在supervisord中重启该IM程序。结果运行几个小时后发现问题依然存在。又又又自动重启了。
所以就想到如何获取重启时的异常信息,于是查看supervisord log ,并没有发现什么PHP程序抛出的异常信息。这就让人很郁闷了。
继续找办法
通过查看swoole官方文档,发现可以通过coredump文件来查看崩溃信息,甚至可以通过bt 、source xxx(php的一个配置文件)等命令查看到明确的堆栈信息。所以就着手找看看有没有im程序的core文件(如果有的话,文件的默认位置跟程序目录一致),结果啥都没有找到。
于是又通过度娘检索如何解决没有core文件的问题,通过阅读+实践,大致有如下步骤来控制core文件的生成:
1.ulimit -c unlimited 设置当前登录shell的core文件大小限制为无限制,当然了也可以设置为100 比如 ulimit -c 100
2.设置core文件的生成路径
echo "/tmp/core-%e-%p-%t" > core_pattern
这样就可以得到程序崩溃时的core文件了,存放在/tmp文件夹下。
但是,经过以上设置,我还是没得到swoole-php的core文件。问题出在哪里呢?
继续学习后再来补充。。。

参考:https://vsmvc.com/p_5f73fb9ff068b5464a1c96e1

未经允许不得转载:我爱WP » Supervisord 修改ulimit 限制

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址