gunicorn geventworker 解析

 

正文

  在前面的文章曾介绍过gunicorn的syncworker,本文介绍其中一种asyncworker:GeventWorker。类图如下:

 
  可见GeventWorker重载了init_process(这个方法是Worker唯一暴露给外界的接口),源码如下:
复制代码
 1         def init_process(self):
 2             # monkey patch here
 3             self.patch()
 4 
 5             # reinit the hub
 6             from gevent import hub
 7             hub.reinit()
 8 
 9             # then initialize the process
10             super(GeventWorker, self).init_process()
复制代码

  首先是monkey-patch,这个是使用gevent所必须的的;然后调用hub.reinit,这个在fork子进程之后必须调用;最后调用基类的init_process。关于gevent hub的reinit,在gevent源码的doc里写的很清楚:

  This should be called *immediately* after :func:`os.fork` in the child process. This is done automatically by :func:`gevent.os.fork` or if the :mod:`os` module has beenmonkey-patched. If this function is not called in a forked process, symptoms may include hanging of functions like :func:`socket.getaddrinfo`, and the hub's threadpool is unlikelyto work.

  前面也提到了init_process会带用到run方法,进入循环,我们看看GeventWorker.run:

  

复制代码
 1     def run(self):
 2         servers = []
 3         ssl_args = {}
 4 
 5         if self.cfg.is_ssl:
 6             ssl_args = dict(server_side=True, **self.cfg.ssl_options)
 7 
 8         for s in self.sockets:
 9             s.setblocking(1)
10             pool = Pool(self.worker_connections) # Pool是Gevent.Pool
11             if self.server_class is not None:
12                 environ = base_environ(self.cfg)
13                 environ.update({
14                     "wsgi.multithread": True,
15                     "SERVER_SOFTWARE": VERSION,
16                 })
17                 server = self.server_class(
18                     s, application=self.wsgi, spawn=pool, log=self.log,
19                     handler_class=self.wsgi_handler, environ=environ,
20                     **ssl_args)
21             else:
22                 hfun = partial(self.handle, s) # self.handle为请求到达时候的处理函数
23                 server = StreamServer(s, handle=hfun, spawn=pool, **ssl_args)
24 
25             server.start()
26             servers.append(server)
27 
28         while self.alive: # 每隔1s告知Arbiter自己还活着
29             self.notify() 
30             gevent.sleep(1.0)   # 切换回hub
复制代码

   逻辑也比较简单,首先是建立TCP Server(gevent.StreamServer),并且传入tcp连接到达时得处理函数self.handle, 然后TCP Server开始工作(server.start), 关于gevent具体怎么在多个协程之间调度,可以参加之前的文章。最后的while循环(28行)用于向Arbiter发心跳,并通过gevent.sleep立即切回hub。再来看看上述代码的第10行:pool = Pool(self.worker_connections) ,这个worker_connections属性来自gunicorn的配置,默认为1000,表明单个worker可以维持的连接数目。然后gevent.Pool的作用可以再gevent tutorial查看,简单来说,就是规定了可以在单个线程内可以并发的greenlet.greenlet的数目。当TCP server接受到请求之后,调用self.handle处理请求,源代码在基类AsyncWorker,实现基本同SyncWorker。

   

references:

http://www.cnblogs.com/xybaby/p/6297147.html

http://www.cnblogs.com/xybaby/p/6370799.html

http://docs.gunicorn.org/en/latest/settings.html

http://sdiehl.github.io/gevent-tutorial/#groups-and-pools 

 

posted @   xybaby  阅读(4568)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示