简单记录一下问题的排除过程,和对应的处理方式!
周末监控告警,发现有一个容器服务,占用了大量的内存(几十个GB
的内存)资源,导致服务节点有些卡顿,影响其他服务的使用。随即,登录服务器查看,发现有大量的 gunicorn
进程(一百多个)。依据该服务的历史数据分析,正常情况下,应该在 4-6
个之间才比较合理。找开发确认之后,发现并没有开启大量并发任务。
root@6123d6c9a23e:/app# ps -ef | grep gunicorn
app /usr/bin/python3 /usr/local/bin/gunicorn -c python:app.worker.gunicorn_conf
app /usr/bin/python3 /usr/local/bin/gunicorn -c python:app.worker.gunicorn_conf
app /usr/bin/python3 /usr/local/bin/gunicorn -c python:app.worker.gunicorn_conf
app /usr/bin/python3 /usr/local/bin/gunicorn -c python:app.worker.gunicorn_conf
......
看了下服务日志,发现大量如下所示的信息,比较奇怪。确认该服务并不会影响客户使用,手动删除部分进程(1/5
),发现并没有新增,后续将其恢复到合理范围之内。
# 服务log日志信息
I[autoreload.py:199]: /app/data/xxx.py modified; restarting server
I[autoreload.py:199]: /app/plugins/xxx.py modified; restarting server
......
确认之前该服务都可以正常运行,怀疑是开发提交代码导致该问题的出现,随即看了下最近提交的代码。看了比较久的时候,才发现 tornado
框架有一个 autoreload
的特性,与服务启动时,所使用的 gunicorn
和 supervisor
工具有冲突,都是重载服务。
正常情况下,调试使用的 debug
功能,只能在开发本地测试的时候使用才对,线上环境是不应该开启的(误提交了)。且如果开启了 debug
功能,会默认开启 autoreload
特性,这就导致服务不断重载和重启,导致占用了大量内存资源。
class Application(tornado.web.Application):
def __init__(self):
handlers = route.init_handlers()
settings = {}
tornado.web.Application.__init__(self, handlers, debug=config.get_config("debug", True), **settings)
- [1] 直接关闭 autoreload 特性
class Application(tornado.web.Application):
def __init__(self):
handlers = route.init_handlers()
settings = {'autoreload': False}
tornado.web.Application.__init__(self, handlers, debug=config.get_config("debug", True), **settings)
- [2] 直接关闭 debug 功能 - 包含 autoreload 特性 - 推荐直接关闭
class Application(tornado.web.Application):
def __init__(self):
handlers = route.init_handlers()
settings = {}
tornado.web.Application.__init__(self, handlers, debug=config.get_config("debug", False), **settings)
到这里,可能你已经知道了,为什么日志里面会出现大量的 restart
信息了。是因为,同步服务代码时变更新了代码文档,然后 tornado
配置了 autoreload
特性,导致服务重载。然后 supervisor
发现服务挂了,再来一次。
变更了多少文档,就导致重载了几次,然后会被重复拉几次,最后 CI
推送完成发送 HUP
信号给 gunicorn
再 reload
一次,这就出现了上文中所说的,一百多个进程 的出现。
# 服务log日志信息
I[autoreload.py:199]: /app/data/xxx.py modified; restarting server
I[autoreload.py:199]: /app/plugins/xxx.py modified; restarting server
......