服务器架构: gunicorn、 Django、nginx
最近在工作中遇到一个奇怪的问题,某段逻辑偶尔会出现异常,却偏偏看不到error log。
查看代码发现里面有一段网络请求的逻辑,
resp = urlopen(url)
这里忽略一个重要的参数 - timeout, urlopen将默认读取 socket defaulttimout。 如果socket也没有设置的话,请求将一直等待,直到出错断开。
>> socket.getdefaulttimeout()
>> None
看起来就是一个疏忽,诡异的地方在于一直看不到请求报错!!没有报错就看不到错误日志,没有错误日志就无法自动报警,导致了这个问题一直没有被暴露。
继续研究日志,在很后面的地方发现一个异常,刚好与发起网络请求的log相差30s。
[2017-01-04 12:00:54 +0000] [1260] [CRITICAL] WORKER TIMEOUT (pid:19348)
[2017-01-04 12:00:54 +0000] [19348] [INFO] Worker exiting (pid: 19348)
[2017-01-04 12:00:54 +0000] [19417] [INFO] Booting worker with pid: 19417
是的,gunicorn worker 超时重启了。
原因: gunicorn worker默认 Timeout 为30秒,当网络堵塞超过30秒时,worker将自动重启,这样永远也看不到网络超时的Error
解决方法:
1、修改gunicorn 默认超时时间 (添加到启动参数,按需修改)
--timeout 60
2、非异步网络请求必须添加timeout参数,且不能大于等于gunicorn worker超时时间
总结:要关注每个view工作时间,耗时长的任务建议做成异步任务(如使用Celery)
评论 (0)