2015-04-17 48 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連接嗎?如果這有效,我有一個想法,爲什麼這是一個問題。 –