2015-04-17 28 views
1

我有一个Python日志处理程序spawns a new thread for each log entry,并在新线程内将日志发送到另一台服务器。但是,我发现请求会间歇性地超时。如果我禁用处理程序,问题就会消失。为什么Gunicorn同步工作者在产卵线程时会挂起?

我试过其他WSGI服务器(WSGIUtils,WSGIRef),我无法重现此问题。

任何想法?

我正在使用同步工作者和Django 1.6在Debian上运行Gunicorn 19.3。

+0

请求周期期间是否正在进行日志记录?当它正在等待将日志推出到套接字时,您确定没有阻塞该线程吗? – andrefsp

+0

我不确定新线程如何干扰gunicorn,但是为每条日志消息创建一个新线程非常昂贵。尝试创建一个队列,并在队列中处理日志条目的工作线程。日志系统的其余部分可以进入应该非常快的队列。 –

+0

@andrefsp:是的,线程中的函数可能需要很长时间才能完成,但为什么这会影响完成请求所需的时间? – Gustavo

回答

0

我认为这是GIL Global Interpreter Lock的另一种情况。假设这种情况:

  • 请求进入
  • 工人开始
  • 工人日志 - >线程启动
  • 工人做
  • 响应发送
  • 主题日志事件

看起来不错,对。但是如果线程更快地完成工作呢?然后你得到:

  • 请求进入
  • 工人开始
  • 工人日志 - >线程启动
  • 工人做
  • 主题日志事件
  • 响应发送

并取决于线程拥有哪个锁或者调用哪个OS函数,线程可能不会释放GIL一段时间,这会阻止工作人员或至少阻止完全交付响应。

查看代码时,我看到您正在为每条日志消息创建一个SSL连接。 SSL非常非常,昂贵。不要这样做。相反,创建一个工作线程,该工作线程一旦打开SSL套接字并保持打开状态。当你写入套接字时,python库应该释放GIL,以便其他代码可以工作。但是我不确定在打开套接字时Python是否会释放锁。

+0

谢谢!但是,对于使用队列的单个长时间运行的线程,不能出现同样的问题吗?既然你说“根据线程拥有哪个锁或者调用哪个OS函数,线程可能不会释放GIL一段时间”。据推测,长时间运行的线程可能会发生同样的情况,对吧? – Gustavo

+0

我也忘了问:如果是GIL,为什么其他WSGI服务器不会发生这种情况?我已经尝试过WSGIUtils和WSGIRef,并且他们没有问题。 – Gustavo

+0

您可以尝试只创建一次SSL连接吗?如果这有效,我有一个想法,为什么这是一个问题。 –