前一段時間遇到一個問題,gunicorn在啓動以後worker一直報timeout的錯誤,而且一直不斷地重啓。開始覺得是worker內部遇到什麼錯誤才致使gunicorn不斷地重啓worker。
先說一下配置,worker_class咱們採用的是gevent,數據庫鏈接採用的mysql+sqlalchemy。由於在app啓動時須要鏈接不少個數據庫,遇到這個問題就一直在糾結是否是程序的bug,數據庫鏈接太多會有問題,但程序沒有任何日誌打出來啊!?可是將鏈接數據庫的數量改小一點,就不會再出現worker重啓的現象了。爲何數據庫鏈接數變小就不會timeout了呢?是否是master以爲worker的啓動時間太長了,過了必定時間就直接幹掉並重啓?後來將配置中的timeout改大,數據庫鏈接數改成原來的值,問題解決!mysql
爲何會這樣? 看gunicorn源碼:
def run(self): servers = [] ssl_args = {} if self.cfg.is_ssl: ssl_args = dict(server_side=True, **self.cfg.ssl_options) for s in self.sockets: s.setblocking(1) pool = Pool(self.worker_connections) if self.server_class is not None: environ = base_environ(self.cfg) environ.update({ "wsgi.multithread": True, "SERVER_SOFTWARE": VERSION, }) **server = self.server_class( s, application=self.wsgi, spawn=pool, log=self.log, handler_class=self.wsgi_handler, environ=environ, **ssl_args)** else: hfun = partial(self.handle, s) server = StreamServer(s, handle=hfun, spawn=pool, **ssl_args) server.start() servers.append(server) while self.alive: **self.notify()** gevent.sleep(1.0)
重點在server初始化的過程當中,因爲數據庫鏈接數量過多,這裏耗費時間太久,self.notify在timeout時間內一直沒有執行,致使主進程master在timeout時間事後當即回收並重啓worker進程,因此會致使上面的問題。sql