前一段时间遇到一个问题,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