django使用gunicorn框架,客戶端請求耗時接口被中斷問題

  項目使用的是django,使用了gunicorn作爲動態web服務,使用的是supervisor作爲進程管理工具。

  由於特殊原因,最近上線了一個非常耗時的http接口,一段時間後開始有用戶陸續反饋他們的代碼調用這個接口會返回502錯誤,經過一段時間的排查排除了網關的問題,確認是系統問題。

  經過日誌信息的比對分析,發現這個接口請求的代碼只執行了大半,沒有執行完。懷疑是worker進程被強制重啓,但是沒有證據,於是在日誌中加上了進程號信息,最終排查發現這個接口的處理進程確實在某一個時間點之後開始就完全沒有日誌了(也就是說進程確實被重啓了)

  一開始以爲是supervisor強制重啓了進程,但是看到supervisor配置的等待時間是1個小時,但是這個接口的耗時遠沒有1個小時這麼久,所以排除了supervisor問題。

  結合日誌和代碼發現:每次接口請求都是在同一行代碼上出現問題。代碼本身沒什麼疑點,但這行代碼使用的第三方的sdk,肝了源碼發現這個函數會阻塞整個進程,但也不會導致內存溢出等問題,代碼問題的排查實在沒有頭緒。但柯南說過:“排除了所有可能之後,最不可能的那個可能就是真相”,那懷疑對象就落在了gunicorn身上。

  上網查吧,查到gunicorn有個參數叫timeout,是這麼描述這個參數的

gunicorn默認的timeout時間是30秒。
gunicorn的管理進程如果在timeout時間內,沒有收到worker進程的消息心跳,則會認爲worker進程出現了死亡,從而重啓相應的worker進程。會導致worker進程正在執行的任務被中斷。
worker進程處於阻塞或高CPU計算時,會出現不能及時發送心跳給管理進程的問題。

  好了,大概率抓到問題點了,我的配置參數裏面沒有設置這個參數,也就是說使用的默認30秒,但剛剛上面提到的那行阻塞代碼的阻塞時間完全在30秒以上,那這個問題也就明朗了。把timeout參數加上吧。

 

疑點:

  目前遺留了一個問題,這個進程管理用心跳感覺不太合理,實在不清楚是如何設計的,回頭再肝一下gunicorn的源碼吧

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章