Tornado 多进程实现分析详解
作者:mingz2013 发布时间:2022-06-13 20:51:56
引子
Tornado 是一个网络异步的的web开发框架, 并且可以利用多进程进行提高效率, 下面是创建一个多进程 tornado 程序的例子.
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import os
import time
import tornado.web
import tornado.httpserver
import tornado.ioloop
import tornado.netutil
import tornado.process
class LongHandler(tornado.web.RequestHandler):
def get(self):
self.write(str(os.getpid()))
time.sleep(10)
if __name__ == "__main__":
app = tornado.web.Application(([r'/', LongHandler], ))
sockets = tornado.netutil.bind_sockets(8090)
tornado.process.fork_processes(2)
server = tornado.httpserver.HTTPServer(app)
server.add_sockets(sockets)
tornado.ioloop.IOLoop.instance().start()
上面代码使用 tornado.process.fork_processes 创建了2个子进程, 同时用时访问这个 服务两次, 分别会返回两个相邻的pid. 可以看到 tornado 确实使用了两个进程来同时完成任务.
我一直很好奇 tornado 是如何将请求调度到子进程, 多个子进程又如何不同时处理一个请求呢?
探究
我们首先是调用 tornado.netutil.bind_sockets 来创建一个 socket(或一个 socket 列表),
接着我们调用 tornado.process.fork_processes 来 fork 子进程, 阅读此函数的代码会发现这个函数仅仅是创建子进程, 然后主进程负责等待子进程, 如果子进 程退出则会根据条件重启子进程, 如果子进程全部退出并不符合重启条件,则主进程退出.
调用这个函数之后, 子进程中函数会返回, 子进程则继续执行调用这个函数之后的代码.
我们在 fork 子进程后做了如下操作.
server = tornado.httpserver.HTTPServer(app)
server.add_sockets(sockets)
tornado.ioloop.IOLoop.instance().start()
我们先看看 tornado.httpserver.HTTPServer.add_sockets 发现 HTTPServer是继承的 tornado.netutil.TCPServer , add_sockets 也是实现在 TCPServer 中
tornado.netutil.TCPServer.add_sockets
def add_sockets(self, sockets):
if self.io_loop is None:
self.io_loop = IOLoop.instance()
for sock in sockets:
self._sockets[sock.fileno()] = sock
add_accept_handler(sock, self._handle_connection,
io_loop=self.io_loop)
主要是映射了下 socket 和 socket 对应的文件描述符, 我们看看它调用的 add_accept_handler
def add_accept_handler(sock, callback, io_loop=None):
if io_loop is None:
io_loop = IOLoop.instance()
def accept_handler(fd, events):
while True:
try:
connection, address = sock.accept()
except socket.error as e:
if e.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN):
return
raise
callback(connection, address)
io_loop.add_handler(sock.fileno(), accept_handler, IOLoop.READ)
我们知道 I/O多路复用 在处理服务端 socket 时, 当有连接请求过来时, 会触发 可读的事件, 此函数将 socket 在主事件循环中注册读事件(IOLoop.READ), 它的回调 会创建连接, 我注意到回调里的异常捕获有这样几行
if e.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN):
return
raise
发现在创建连接的时候会跳过这个异常呢, 为什么?那么 EWOULDBLOCK 和 EAGAIN是是什么呢? 通过查找知道它的意思是在非阻塞模式下, 不需要重读或重写, EAGAIN 是 EWOULDBLOCK 在 Windows 上的名字, 所以看到这里就很明确了.
结论
Tornado 多进程的处理流程是先创建 socket, 然后再 fork 子进程, 这样所有的子进程实际都监听 一个(或多个)文件描述符, 也就是都在监听同样的 socket.
当连接过来所有的子进程都会收到可读事件, 这时候所有的子进程都会跳到 accept_handler 回调函数, 尝试建立连接.
一旦其中一个子进程成功的建立了连接, 当其他子进程再尝试建立这个连接的时候就会触发 EWOULDBLOCK (或 EAGAIN) 错误. 这时候回调函数判断是这个错误则返回函数不做处理.
当成功建立连接的子进程还在处理这个连接的时候又过来一个连接, 这时候就会有另外一个 子进程接手这个连接.
Tornado 就是通过这样一种机制, 利用多进程提升效率, 由于连接只能由一个子进程成功创建, 同一个请求也就不会被多个子进程处理.
后记
写完才发现, 我所使用的代码是 tornado-2.4.post2 版本, 当前最新代码是 3.3.0, 查看了下最新代码, 最新代码 TCPServer 写到单独 tornado.tcpserver 里了, 其他和本文 相关的并没有什么大的变化.
Category:PythonTagged:Pythonfork_processestornado多进程web提升效率
来源:http://blog.csdn.net/mingzznet/article/details/52929781
猜你喜欢
- 阅读之前:在看文章具体内容之前,希望你可以 先打开IE8,打开http://www.taobao.com,然后在地址栏里输入:javascr
- Python实现新版正方系统滑动验证码识别算法和方案步骤一:点击数据分析点击滑动按钮,将发送一个请求到 /zfcaptchaLogin请求内
- 前言在搜集了很多文本语料之后,会开始漫长的数据清洗过程,通常要不断迭代。1. 问题描述有些文本数据中,会包含一些特殊符号。猜想可能是从某些富
- python3 shelve模块的详解一、简介在python3中我们使用json或者pickle持久化数据,能dump多次,但只能load一
- 如何在线查询本地机的文件?看看下面的例子,默认子目录与子虚拟目录为同一级别且名称一致,另我们使用了"http://intels.n
- numpy 中 的random模块有多个函数用于生成不同类型的随机数,常见的有 uniform、rand、random、randint、ra
- 一、背景我们日常测试中存在大量重复的造数操作,且流程较长,为了提升测试效率,我们搭建了数据构造平台。平台采用了前端 + 脚本分离的形式,数据
- 正文开始:服务器端代码:# 再来简单的测试,这个是服务器端import socketimport sysBUF_SIZE = 1024ip_
- 散点图散点图是指在 回归分析中,数据点在直角坐标系平面上的 分布图,散点图表示因变量随 自变量而 变
- 本文实例为大家分享了python3.6.1安装教程,供大家参考,具体内容如下1、安装编译环境所需包#yum install zlib-dev
- //定义一个对象数组 var data = [{ name: "jiang", age: 22 }, { name: &
- javascript的分号代表语句的结束符,但由于javascript具有分号自动插入规则,所以它是一个十分容易让人模糊的东西,在一般情况下
- 一、定义协程asyncio 执行的任务,称为协程,但是Asyncio 并不能带来真正的并行Python 的多线程因为 GIL(全局解释器锁)
- 【先锋缓存类】Ver2004作者:孙立宇、apollosun、ezhonghua官方网站:http://www.lkstar.com 技术支
- DataFrame 是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型值)。DataFrame 既有行
- 本文实例为大家分享了JS实现拖动模糊框特效的具体代码,供大家参考,具体内容如下需求:在图片上拖动按钮,图片蒙层慢慢覆盖,当蒙层边缘碰到左右下
- 这是一篇关于怎样精简代码和Asp 特征以获得最快执行速度的详细文章。对于一个急燥的用户来说,任何在按下用户按钮到结果出现在它们的屏幕之间的延
- 1.问题描述2.解决方案(1)Dataloader里面不用cv2.imread进行读取图片,用cv2.imread还会带来一系列的不方便,比
- 官方文档https://developers.weixin.qq.com/miniprogram/dev/framework/open-ab
- ptb数据集是语言模型学习中应用最广泛的数据集,常用该数据集训练RNN神经网络作为语言预测,tensorflow对于ptb数据集的读取也定义