gunicorn 簡介


 
  gunicorn是一個python Wsgi http server,只支持在Unix系統上運行,來源於Ruby的unicorn項目。Gunicorn使用 prefork master-worker模型(在gunicorn中,master被稱為arbiter),能夠與各種wsgi web框架協作。gunicorn的文檔是比較完善的, 這里也有部分中文翻譯,不過還是建議直接讀英文文檔。筆者並沒有在項目中真正使用過gunicorn,閱讀其源碼只要是為了了解其master worker模型,如有紕漏,還請多多指教。
  gunicorn的安裝非常簡單,pip install guncorn 即可。后續如果用到異步的worker模型,還需要安裝對應的模塊(如gevent)
  在裝好gunicorn之后, 我們來看看gunicorn的hello world。代碼來自官網,將下面的代碼放到gunicorn_app.py中:
  
復制代碼
1     def app(environ, start_response):
2         data = b"Hello, World!\n"
3         start_response("200 OK", [
4             ("Content-Type", "text/plain"),
5             ("Content-Length", str(len(data)))
6         ])
7  
8         return iter([data])
復制代碼

 

  可以看到app是非常標准的wsgi應用,然后我們啟動gunicorn:gunicorn -w 2 gunicorn_app:app。 輸出如下:

  

 
  上圖展示了兩個很重要的信息:
   第一:啟動了兩個worker,這是通過"-w 2"指定(默認為1)
   第二:worker的工作模型是sync(默認),后面會詳細介紹worker模型
  然后在另外一個terminal運行:ps -ef | grep python 
  
 
  可以看出 worker進程(pid:19469, 19470)是master進程(pid:19464)的子進程。
  新起一個terminal,用curl測試:  curl 127.0.0.1:8000
  在該terminal輸出“Hello, World!”
  前面提到,官方gunicorn只能在Unix上運行(貌似也有非官網的補丁,使其能在windows上運行,未求證),主要是因為源碼中使用了 fcntl,os.fork等只在unix上存在的模塊和接口。pre-fork就是指gunicorn啟動的時候,在主進程中會預先fork出指定數量(-w)的worker進程。這里先簡介Master Worker的工作流程,后文再對代碼做詳細介紹。
  啟動gunicorn,首先初始化gunicorn.app.base.Application(或者基類,比如上面從命令行啟動時,是wsgiApplication),初始化中最重要的是讀取配置,支持文件或者命令行。然后調用Application.run(),該方法代碼如下:
  
復制代碼
    def run(self):
        try:
            Arbiter(self).run()
        except RuntimeError as e:
            print("\nError: %s\n" % e, file=sys.stderr)
            sys.stderr.flush()
            sys.exit(1)
復制代碼
  調用Arbiter(self).run()之后,主進程(master)的所有邏輯都運行在Arbiter類里面。
  Arbiter首先讀取配置項, 如worker數量,worker工作模式,監聽的地址等;然后初始化信號處理函數,然后建立socket,不過並不listen;接下來fork出所有的worker進程;最后進入循環:處理信號隊列中的信號,殺掉並重啟失去響應的子進程,如果沒事兒干,就“sleep”一會兒。
  worker進程就更加簡單一下,首先是讀取配置,初始化信號處理函數,然后進入循環:處理監聽端口上的請求(也就是會調用到wsgi app的地方),然后向master報告自己還活着。另外,worker中是在信號發生的時候直接處理信號,而不是像master一樣放入信號隊列。
  可以稍微改動一下app代碼,以便在客戶端請求的時候,服務器端能打印調用棧,下面是在我的機器上的輸出,后面將會對Arbiter和worker進行介紹。
  •  0: FUNC:app(...)                  /home/xxx/gunicorn_app.py::16
  •  1: FUNC:handle_request(...)       /usr/local/lib/python2.7/dist-packages/gunicorn/workers/sync.py::176
  •  2: FUNC:handle(...)               /usr/local/lib/python2.7/dist-packages/gunicorn/workers/sync.py::135
  •  3: FUNC:accept(...)               /usr/local/lib/python2.7/dist-packages/gunicorn/workers/sync.py::30
  •  4: FUNC:run_for_one(...)          /usr/local/lib/python2.7/dist-packages/gunicorn/workers/sync.py::68
  •  5: FUNC:run(...)                  /usr/local/lib/python2.7/dist-packages/gunicorn/workers/sync.py::124
  •  6: FUNC:init_process(...)         /usr/local/lib/python2.7/dist-packages/gunicorn/workers/base.py::132
  •  7: FUNC:spawn_worker(...)         /usr/local/lib/python2.7/dist-packages/gunicorn/arbiter.py::557
  •  8: FUNC:spawn_workers(...)        /usr/local/lib/python2.7/dist-packages/gunicorn/arbiter.py::590
  •  9: FUNC:manage_workers(...)       /usr/local/lib/python2.7/dist-packages/gunicorn/arbiter.py::524
  • 10: FUNC:run(...)                  /usr/local/lib/python2.7/dist-packages/gunicorn/arbiter.py::189
  • 11: FUNC:run(...)                  /usr/local/lib/python2.7/dist-packages/gunicorn/app/base.py::72
  • 12: FUNC:run(...)                  /usr/local/lib/python2.7/dist-packages/gunicorn/app/base.py::192
  • 13: FUNC:run(...)                  /usr/local/lib/python2.7/dist-packages/gunicorn/app/wsgiapp.py::74
  • 14: FUNC:<module>(...)             /usr/local/bin/gunicorn::11


免責聲明!

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



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