Django 踩坑系列 (一):网络请求超时

服务器架构: 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)

你可能感兴趣的:(Django 踩坑系列 (一):网络请求超时)