gunicorn工作原理

2021-08-22 18:02:20 字數 3912 閱讀 2558

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...