国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

Tornado 多進程實現分析詳解

2020-02-16 11:36:36
字體:
來源:轉載
供稿:網友

引子

Tornado 是一個網絡異步的的web開發框架, 并且可以利用多進程進行提高效率, 下面是創建一個多進程 tornado 程序的例子.

#!/usr/bin/env python# -*- coding:utf-8 -*-import osimport timeimport tornado.webimport tornado.httpserverimport tornado.ioloopimport tornado.netutilimport tornado.processclass 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), 它的回調 會創建連接, 我注意到回調里的異常捕獲有這樣幾行

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 长治市| 民县| 霍城县| 攀枝花市| 株洲县| 姜堰市| 枣庄市| 巨鹿县| 安图县| 石狮市| 马山县| 剑河县| 洛浦县| 喜德县| 湘阴县| 丹凤县| 四川省| 孝感市| 富宁县| 福州市| 英吉沙县| 邻水| 高平市| 姜堰市| 武夷山市| 麻江县| 马边| 林西县| 莱阳市| 肥西县| 芦溪县| 敖汉旗| 民丰县| 鄂州市| 长丰县| 盐津县| 光山县| 宝鸡市| 遂昌县| 寿宁县| 德州市|