【原創】uwsgi中多進程+多線程原因以及串行化accept() - thunder_lock說明


如有不對,請詳細指正。

  最近再研究uwsgi如何部署python app,看uwsgi的文檔,里面有太多的參數,但每個參數的解釋太蒼白,作為菜鳥的我實在是不懂。想搞清楚uwsgi的工作原因以及里面的一些參數的意義,只能通過英文的文檔和源碼來入手,雖然慢,但是理解更深刻。

  本文根據代碼閱讀以及參照多種文檔,描述了uwsgi的啟動多進程+多線程工作原因,以及thunder_lock參數的作用:

  • uwsgi是用c語言寫的一個webserver,可以啟動多個進程,進程里面可以啟動多個線程來服務。進程分為主進程和worker進程,worker里面可以有多個線程。
  • 一開始進入main函數,啟動這個就是主進程了,uwsgi_setup函數(主進程)里面針對選項參數做一些處理,執行環境設置,執行一些hook,語言環境初始化(python),如果沒有設置延遲加載app,則app在主進程加載;如果設置了延遲加載,則在每一個worker進程中都會加載一次。uwsgi_setup函數還執行了插件的初始化(當前我只關心http、python:http是gateway類型的插件,這種插件是向外暴露http服務的,python的requests類型的插件,用來服務請求的)、tcp socket的綁定與監聽(這個是指http與work之間的通信,且它的端口是自動產生的)。最后uwsgi主進程fork了指定worker進程用來接收(accept)請求。雖然在setup中就fork了子進程,但是現在還沒有開始accept。
  • wsgi_run函數就是真正的開始執行了,這個函數分為倆個部分,主進程執行部分和worker進程執行部分。主進程執行部分是一個無限循環,他可以執行特定的hook以及接收信號等,總之是用來管理worker進程以及一些定時或者事件觸發任務。worker部分:注冊型號處理函數,執行一些hook,循環接收(accept)請求。在啟動woker時可以根據--threads參數指定要產生的線程個數,否則只在當前進程啟動一個線程。這些線程循環接收請求並處理。
  • 在worker中接收請求的函數wsgi_req_accept有一個鎖:thunder_lock,這個鎖用來串行化accept,防止“驚群”現象:參考這里
    •   驚群現象出現在這樣的情況:主進程綁定並監聽socket,然后調用fork,在各個子進程進行accept。無論任何時候,只要有一個連接嘗試連接,所有的子進程都將被喚醒,但只有一個會連接成功,其他的會得到一個EAGAIN的錯誤,浙江導致巨大的CPU資源浪費,如果在進程中使用線程,這個問題被再度放大。一個解決方法是串行化accept,在accept前防止一個鎖。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM