gunicorn syncworker 源碼解析
阿新 • • 發佈:2017-05-15
_for html bit int 文件的 ini exc mks list gunicorn支持不同的worker類型,同步或者異步,異步的話包括基於gevent、基於eventlet、基於Aiohttp(python版本需要大於3.3),也有多線程的版本。下面是gunicorn當前版本(19.6.0)支持的Worker類型:
run方法根據監聽的端口數量進行區分,如果只在一個端口監聽,那麽調用accept; 如果是多個端口,那麽用select輪訓再accept。不管哪種方式,新的連接請求到達後 都調用handle_request函數處理,源代碼如下:
sync
eventlet
- Requires eventlet >= 0.9.7gevent
- Requires gevent >= 0.13tornado
- Requires tornado >= 0.2gthread
- Python 2 requires the futures package to be installedgaiohttp
- Requires Python 3.4 and aiohttp >= 0.21.5
def run(self): if len(self.sockets) > 1: self.run_for_multiple(timeout) # 使用select else: self.run_for_one(timeout) # 如果只有一個監聽socket,那麽阻塞accept就行了
def handle_request(self, listener, req, client, addr): environ = {} resp = None try: self.cfg.pre_request(self, req) request_start = datetime.now() resp, environ = wsgi.create(req, client, addr, listener.getsockname(), self.cfg) # Force the connection closed until someone shows # a buffering proxy that supports Keep-Alive to # the backend. resp.force_close() self.nr += 1 if self.nr >= self.max_requests: self.log.info("Autorestarting worker after current request.") self.alive = False respiter = self.wsgi(environ, resp.start_response) try: if isinstance(respiter, environ[‘wsgi.file_wrapper‘]): resp.write_file(respiter) else: for item in respiter: resp.write(item) resp.close() request_time = datetime.now() - request_start self.log.access(resp, req, environ, request_time)
其中,調用到App的是下面這行代碼
respiter = self.wsgi(environ, resp.start_response)前面提到worker通過notify來向master進程做心跳,具體的代碼在WorkerTmp.py。原理很簡單: (1)首先通過tempfile.mkstemp創建一個臨時文件 (2)worker進程在每次輪訓的時候修改該臨時文件的屬性
def notify(self): try: self.spinner = (self.spinner + 1) % 2 os.fchmod(self._tmp.fileno(), self.spinner) except AttributeError: # python < 2.6 self._tmp.truncate(0) os.write(self._tmp.fileno(), b"X")
(3)master進程檢查臨時文件最新一次修改時間是否超過閾值
def last_update(self): return os.fstat(self._tmp.fileno()).st_ctime
references: http://docs.gunicorn.org/en/stable/ http://docs.gunicorn.org/en/stable/signals.html https://github.com/benoitc/gunicorn
gunicorn syncworker 源碼解析