最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Tornado 多進(jìn)程實(shí)現(xiàn)分析詳解

 更新時間:2018年01月12日 11:49:28   作者:mingz2013  
這篇文章主要介紹了Tornado 多進(jìn)程實(shí)現(xiàn)分析詳解,具有一定借鑒價(jià)值,需要的朋友可以參考下

引子

Tornado 是一個網(wǎng)絡(luò)異步的的web開發(fā)框架, 并且可以利用多進(jìn)程進(jìn)行提高效率, 下面是創(chuàng)建一個多進(jìn)程 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 創(chuàng)建了2個子進(jìn)程, 同時用時訪問這個 服務(wù)兩次, 分別會返回兩個相鄰的pid. 可以看到 tornado 確實(shí)使用了兩個進(jìn)程來同時完成任務(wù).

我一直很好奇 tornado 是如何將請求調(diào)度到子進(jìn)程, 多個子進(jìn)程又如何不同時處理一個請求呢?

探究

我們首先是調(diào)用 tornado.netutil.bind_sockets 來創(chuàng)建一個 socket(或一個 socket 列表),

接著我們調(diào)用 tornado.process.fork_processes 來 fork 子進(jìn)程, 閱讀此函數(shù)的代碼會發(fā)現(xiàn)這個函數(shù)僅僅是創(chuàng)建子進(jìn)程, 然后主進(jìn)程負(fù)責(zé)等待子進(jìn)程, 如果子進(jìn) 程退出則會根據(jù)條件重啟子進(jìn)程, 如果子進(jìn)程全部退出并不符合重啟條件,則主進(jìn)程退出.

調(diào)用這個函數(shù)之后, 子進(jìn)程中函數(shù)會返回, 子進(jìn)程則繼續(xù)執(zhí)行調(diào)用這個函數(shù)之后的代碼.

我們在 fork 子進(jìn)程后做了如下操作.

server = tornado.httpserver.HTTPServer(app)
  server.add_sockets(sockets)
  tornado.ioloop.IOLoop.instance().start()

我們先看看 tornado.httpserver.HTTPServer.add_sockets 發(fā)現(xiàn) HTTPServer是繼承的 tornado.netutil.TCPServer , add_sockets 也是實(shí)現(xiàn)在 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 對應(yīng)的文件描述符, 我們看看它調(diào)用的 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多路復(fù)用 在處理服務(wù)端 socket 時, 當(dāng)有連接請求過來時, 會觸發(fā) 可讀的事件, 此函數(shù)將 socket 在主事件循環(huán)中注冊讀事件(IOLoop.READ), 它的回調(diào) 會創(chuàng)建連接, 我注意到回調(diào)里的異常捕獲有這樣幾行

if e.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN):
          return
        raise

發(fā)現(xiàn)在創(chuàng)建連接的時候會跳過這個異常呢, 為什么?那么 EWOULDBLOCK 和 EAGAIN是是什么呢? 通過查找知道它的意思是在非阻塞模式下, 不需要重讀或重寫, EAGAIN 是 EWOULDBLOCK 在 Windows 上的名字, 所以看到這里就很明確了.

結(jié)論

Tornado 多進(jìn)程的處理流程是先創(chuàng)建 socket, 然后再 fork 子進(jìn)程, 這樣所有的子進(jìn)程實(shí)際都監(jiān)聽 一個(或多個)文件描述符, 也就是都在監(jiān)聽同樣的 socket.

當(dāng)連接過來所有的子進(jìn)程都會收到可讀事件, 這時候所有的子進(jìn)程都會跳到 accept_handler 回調(diào)函數(shù), 嘗試建立連接.

一旦其中一個子進(jìn)程成功的建立了連接, 當(dāng)其他子進(jìn)程再嘗試建立這個連接的時候就會觸發(fā) EWOULDBLOCK (或 EAGAIN) 錯誤. 這時候回調(diào)函數(shù)判斷是這個錯誤則返回函數(shù)不做處理.

當(dāng)成功建立連接的子進(jìn)程還在處理這個連接的時候又過來一個連接, 這時候就會有另外一個 子進(jìn)程接手這個連接.

Tornado 就是通過這樣一種機(jī)制, 利用多進(jìn)程提升效率, 由于連接只能由一個子進(jìn)程成功創(chuàng)建, 同一個請求也就不會被多個子進(jìn)程處理.

后記

寫完才發(fā)現(xiàn), 我所使用的代碼是 tornado-2.4.post2 版本, 當(dāng)前最新代碼是 3.3.0, 查看了下最新代碼, 最新代碼 TCPServer 寫到單獨(dú) tornado.tcpserver 里了, 其他和本文 相關(guān)的并沒有什么大的變化.

Category:PythonTagged:Pythonfork_processestornado多進(jìn)程web提升效率

以上就是本文關(guān)于Tornado 多進(jìn)程實(shí)現(xiàn)分析詳解的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!

相關(guān)文章

  • Python tkinter label 更新方法

    Python tkinter label 更新方法

    今天小編就為大家分享一篇Python tkinter label 更新方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-10-10
  • 如何輕松實(shí)現(xiàn)Python數(shù)組降維?

    如何輕松實(shí)現(xiàn)Python數(shù)組降維?

    歡迎來到Python數(shù)組降維實(shí)現(xiàn)方法的指南!這里,你將探索一種神秘又強(qiáng)大的編程技術(shù),想要提升你的Python編程技巧嗎?別猶豫,跟我一起深入探索吧!
    2024-01-01
  • Python處理圖片并實(shí)現(xiàn)生成天際線

    Python處理圖片并實(shí)現(xiàn)生成天際線

    天際線(SkyLine)顧名思義就是天空與地面的邊界線,這篇文章主要為大家介紹了如何使用Python實(shí)現(xiàn)處理圖片并實(shí)現(xiàn)生成天際線,感興趣的可以了解下
    2024-01-01
  • Python讀取二進(jìn)制文件代碼方法解析

    Python讀取二進(jìn)制文件代碼方法解析

    這篇文章主要介紹了Python讀取二進(jìn)制文件代碼方法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • python shell根據(jù)ip獲取主機(jī)名代碼示例

    python shell根據(jù)ip獲取主機(jī)名代碼示例

    這篇文章主要介紹了python shell根據(jù)ip獲取主機(jī)名代碼示例,涉及用socket模塊和shell中hostname命令獲取等相關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • 解決pycharm中的run和debug失效無法點(diǎn)擊運(yùn)行

    解決pycharm中的run和debug失效無法點(diǎn)擊運(yùn)行

    這篇文章主要介紹了解決pycharm中的run和debug失效無法點(diǎn)擊運(yùn)行方式,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-06-06
  • python3實(shí)現(xiàn)網(wǎng)絡(luò)爬蟲之BeautifulSoup使用詳解

    python3實(shí)現(xiàn)網(wǎng)絡(luò)爬蟲之BeautifulSoup使用詳解

    這篇文章主要介紹了python3實(shí)現(xiàn)網(wǎng)絡(luò)爬蟲之BeautifulSoup使用詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12
  • python模塊restful使用方法實(shí)例

    python模塊restful使用方法實(shí)例

    這篇文章主要介紹了python模塊restful使用方法,大家參考使用吧
    2013-12-12
  • Python正則表達(dá)式如何匹配中文

    Python正則表達(dá)式如何匹配中文

    這篇文章主要介紹了Python正則表達(dá)式如何匹配中文,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • python主動拋出異常raise的方法實(shí)現(xiàn)

    python主動拋出異常raise的方法實(shí)現(xiàn)

    本文主要介紹了python主動拋出異常raise的方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-12-12

最新評論

滨州市| 新干县| 公主岭市| 上蔡县| 友谊县| 海原县| 垫江县| 吴江市| 赞皇县| 宽城| 尉氏县| 都昌县| 莎车县| 商丘市| 麦盖提县| 德格县| 巴彦县| 犍为县| 榆社县| 会同县| 武清区| 秭归县| 噶尔县| 朝阳县| 昭苏县| 赣榆县| 孟津县| 四川省| 白玉县| 旬阳县| 崇信县| 奈曼旗| 鸡西市| 浙江省| 灵宝市| 习水县| 抚宁县| 航空| 长阳| 保德县| 玉树县|