gunicorn「綠色獨角獸」是乙個被廣泛使用的高效能的python wsgi unix http伺服器,移植自ruby的獨角獸(unicorn )專案,使用pre-fork worker模式,具有使用非常簡單,輕量級的資源消耗,以及高效能等特點。
gunicorn pre-fork worker模型中有乙個管理程序以及幾個的工作程序。管理程序:master,工作程序:worker。(以下**中為了方面理解,均去除了一些干擾**)
master通過pre-fork的方式建立多個worker:
def spawn_worker(self):
self.worker_age += 1
worker = self.worker_class(self.worker_age, self.pid, self.listeners,
self.cfg, self.log)
pid = os.fork()
if pid != 0: #父程序,返回後繼續建立其他worker,沒worker後進入到自己的訊息迴圈
self.workers[pid] = worker
return pid
# process child
worker_pid = os.getpid()
try:
..........
worker.init_process() #子程序,初始化woker,進入worker的訊息迴圈,
sys.exit(0)
except systemexit:
raise
............
manager維護數量固定的worker:
def manage_workers(self):
if len(self.workers.keys()) < self.num_workers:
self.spawn_workers()
while len(workers) > self.num_workers:
(pid, _) = workers.pop(0)
self.kill_worker(pid, signal.sigquit)
建立完所有的worker後,worker和master各自進入自己的訊息迴圈。
master的事件迴圈就是收收訊號,管理管理worker程序,而worker程序的事件迴圈就是監聽網路事件並處理(如新建連線,斷開連線,處理請求傳送響應等等),所以真正的連線最終是連到了worker程序上的。(注:有關這種多程序模型的詳細介紹,可以參考
woker有很多種,包括:ggevent、geventlet、gtornado等等。這裡主要分析ggevent。
每個ggevent worker啟動的時候會啟動多個server物件:worker首先為每個listener建立乙個server物件(注:為什麼是一組listener,因為gunicorn可以繫結一組位址,每個位址對於乙個listener),每個server物件都有執行在乙個單獨的gevent pool物件中。真正等待鏈結和處理鏈結的操作是在server物件中進行的。
#為每個listener建立server物件。
for s in self.sockets:
pool = pool(self.worker_connections) #建立gevent pool
if self.server_class is not none:
#建立server物件
server = self.server_class(
handler_class=self.wsgi_handler, **ssl_args)
.............
server.start() #啟動server,開始等待鏈結,服務鏈結
.........
上面**中的server_class實際上是乙個gevent的wsgi server的子類:
class pywsgiserver(pywsgi.wsgiserver):
base_env = base_wsgi_env
需要注意的是構造pywsgiserver的引數:
self.server_class(
handler_class=self.wsgi_handler, **ssl_args)
當所有server物件建立完畢後,worker需要定時通知manager,否則會被認為是掛掉了。
while self.alive:
self.notify()
.......
這個地方的notify機制設計的比較有趣,每個worker有個與之對應的tmp file,每次notify的時候去操作一下這個tmp file(比如通過os.fchmod),這個tmp file的last update的時間戳就會更新。而manager則通過檢查每個worker對應的temp file的last update的時間戳,來判斷這個程序是否是掛掉的。
真正等待鏈結和處理鏈結的操作是在gevent的wsgiserver 和 wsgihandler中進行的。
最後再來看一下gevent的wsgiserver 和 wsgihandler的主要實現:
def do_handle(self, *args):
spawn = self._spawn
spawn(self._handle, *args)
可以看出,wsgiserver 實際上是建立乙個協程去處理該套接字,也就是說在wsgiserver 中,乙個協程單獨負責乙個http鏈結。協程中執行的self._handle函式實際上是呼叫了wsgihandler的handle函式來不斷處理http 請求:
def handle(self):
try:
while self.socket is not none:
result = self.handle_one_request()#處理http請求
if result is none:
break
if result is true:
continue
self.status, response_body = result
self.socket.sendall(response_body)#傳送回應報文
..............
self.process_result()
Gunicorn常用配置
編號 命令含義 1 srv python2 bin python python環境 2 srv gunicorn18080 gunicorn gunicorn環境 3 u www data 指定worker程序的執行使用者名稱。4 k gevent k 指定worker class模式,預設為syn...
Gunicorn 簡單使用
配置檔案如下 import multiprocessing bind 0.0.0.0 8000 workers multiprocessing.cpu count 2 1 服務連線已滿時,可容納的等待連線數,當超過該值時,服務會直接被拒絕 backlog 2048 worker class geve...
gunicorn簡單配置
coding utf 8 import os from multiprocessing import cpu count bind 127.0.0.1 9000 daemon true workers cpu count 2 worker class gevent forwarded allow i...