欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Tornado實(shí)現(xiàn)多進(jìn)程/多線程的HTTP服務(wù)詳解

 更新時(shí)間:2019年07月25日 11:35:32   作者:ZhiChao&  
這篇文章主要介紹了Tornado實(shí)現(xiàn)多進(jìn)程/多線程的HTTP服務(wù)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值

用tornado web服務(wù)的基本流程

1.實(shí)現(xiàn)處理請(qǐng)求的Handler,該類繼承自tornado.web.RequestHandler,實(shí)現(xiàn)用于處理請(qǐng)求的對(duì)應(yīng)方法如:get、post等。返回內(nèi)容用self.write方法輸出。

2.實(shí)例化一個(gè)Application。構(gòu)造函數(shù)的參數(shù)是一個(gè)Handlers列表,通過(guò)正則表達(dá)式,將請(qǐng)求與Handler對(duì)應(yīng)起來(lái)。通過(guò)dict將Handler需要的其他對(duì)象以參數(shù)的方式傳遞給Handler的initialize方法。

3.初始化一個(gè)tornado.httpserver.HTTPServer對(duì)象,構(gòu)造函數(shù)的參數(shù)是上一步的Application對(duì)象。

4.為HTTPServer對(duì)象綁定一個(gè)端口。

5.開(kāi)始IOLoop。

需要用到的特性

由于tornado的亮點(diǎn)是異步請(qǐng)求,所以這里首先想到的是將所有請(qǐng)求都改造為異步的。但是這里遇到一個(gè)問(wèn)題,就是異步函數(shù)內(nèi)一定不能有阻塞調(diào)用出現(xiàn),否則整個(gè)IOLoop都會(huì)被卡住。這就要求徹底地去改造服務(wù),將所有IO或是用時(shí)較長(zhǎng)的請(qǐng)求都改造為異步函數(shù)。這個(gè)工程量是非常大的,需要去修改已有的代碼。因此,我們考慮用線程池的方式去實(shí)現(xiàn)。當(dāng)一個(gè)線程阻塞在某個(gè)請(qǐng)求或IO時(shí),其他線程或IOLoop會(huì)繼續(xù)執(zhí)行。

另外一個(gè)瓶頸就是GIL限制了CPU的并發(fā)數(shù)量,因此考慮用子進(jìn)程的方式增加進(jìn)程數(shù),提高服務(wù)能力上限。

綜合上面的分析,大致用以下方案:

  • 通過(guò)子進(jìn)程的方式復(fù)制多個(gè)進(jìn)程,使子進(jìn)程中的只讀頁(yè)指向同一個(gè)物理頁(yè)。
  • 線程池?;乇墚惒礁脑斓墓ぷ髁浚黾覫O的并發(fā)量。

測(cè)試代碼

首先測(cè)試線程池,測(cè)試用例為:

對(duì)sleep頁(yè)面同時(shí)發(fā)出兩個(gè)請(qǐng)求:

  • 在線程池中運(yùn)行的函數(shù)(這里是self.block_task)能夠同時(shí)執(zhí)行。表現(xiàn)為在控制臺(tái)交替打印出數(shù)字。
  • 兩個(gè)get請(qǐng)求幾乎同時(shí)返回,在瀏覽器上顯示返回的內(nèi)容。

線程池的測(cè)試代碼如下:

import os
import sys
import time
 
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.gen
from tornado.concurrent import run_on_executor
from concurrent.futures import ThreadPoolExecutor
from tornado.options import define, options
 
class HasBlockTaskHandler(tornado.web.RequestHandler):
  executor = ThreadPoolExecutor(20)  #起線程池,由當(dāng)前RequestHandler持有
   
  @tornado.gen.coroutine
  def get(self):
    strTime = time.strftime("%Y-%m-%d %H:%M:%S")
    print "in get before block_task %s" % strTime
    result = yield self.block_task(strTime)
    print "in get after block_task"
    self.write("%s" % (result))
 
  @run_on_executor
  def block_task(self, strTime):
    print "in block_task %s" % strTime
    for i in range(1, 16):
      time.sleep(1)
      print "step %d : %s" % (i, strTime)
    return "Finish %s" % strTime
 
if __name__ == "__main__":
  tornado.options.parse_command_line()
  app = tornado.web.Application(handlers=[(r"/sleep", HasBlockTaskHandler)], autoreload=False, debug=False)
  http_server = tornado.httpserver.HTTPServer(app)
  http_server.bind(8888)
  tornado.ioloop.IOLoop.instance().start()

整個(gè)代碼里有幾個(gè)位置值得關(guān)注:

1.executor = ThreadPoolExecutor(20)。這是給Handler類初始化了一個(gè)線程池。其中concurrent.futures不屬于tornado,是python的一個(gè)獨(dú)立模塊,在python3中是內(nèi)置模塊,python2.7需要自己安裝。

2.修飾符@run_on_executor。這個(gè)修飾符將同步函數(shù)改造為在executor(這里是線程池)上運(yùn)行的異步函數(shù),內(nèi)部實(shí)現(xiàn)是將被修飾的函數(shù)submit到executor,返回一個(gè)Future對(duì)象。

3.修飾符@tornado.gen.coroutine。被這個(gè)修飾符修飾的函數(shù),是一個(gè)以同步函數(shù)方式編寫的異步函數(shù)。原本通過(guò)callback方式編寫的異步代碼,有了這個(gè)修飾符,可以通過(guò)yield一個(gè)Future的方式來(lái)寫。被修飾的函數(shù)在yield了一個(gè)Future對(duì)象后將會(huì)被掛起,F(xiàn)uture對(duì)象的結(jié)果返回后繼續(xù)執(zhí)行。

運(yùn)行代碼后,在兩個(gè)不同瀏覽器上訪問(wèn)sleep頁(yè)面,得到了想要的效果。這里有一個(gè)小插曲,就是如果在同一瀏覽器的兩個(gè)tab上進(jìn)行測(cè)試,是無(wú)法看到想要的效果。第二個(gè)get請(qǐng)求會(huì)被block,直到第一個(gè)get請(qǐng)求返回,服務(wù)端才開(kāi)始處理第二個(gè)get請(qǐng)求。這讓我一度覺(jué)得多線程沒(méi)有生效,用了半天時(shí)間查了很多資料,才看到是瀏覽器把相同的第二個(gè)請(qǐng)求block了,具體鏈接參考這里。

由于tornado很方便地支持多進(jìn)程模型,多進(jìn)程的使用要簡(jiǎn)單很多,在以上例子中,只需要對(duì)啟動(dòng)部分稍作改動(dòng)即可。具體代碼如下所示:

if __name__ == "__main__":
  tornado.options.parse_command_line()
  app = tornado.web.Application(handlers=[(r"/sleep", HasBlockTaskHandler)], autoreload=False, debug=False)
  http_server = tornado.httpserver.HTTPServer(app)
  http_server.bind(8888)
  print tornado.ioloop.IOLoop.initialized()
  http_server.start(5)
  tornado.ioloop.IOLoop.instance().start()

需要注意的地方有兩點(diǎn):

1.app = tornado.web.Application(handlers=[(r"/sleep", HasBlockTaskHandler)], autoreload=False, debug=False),在生成Application對(duì)象時(shí),要將autoreload和debug兩個(gè)參數(shù)至為False。也就是需要保證在fork子進(jìn)程之前IOLoop是未被初始化的。這個(gè)可以通過(guò)tornado.ioloop.IOLoop.initialized()函數(shù)來(lái)跟。

2.http_server.start(5)在啟動(dòng)IOLoop之前通過(guò)start函數(shù)設(shè)置進(jìn)程數(shù)量,如果設(shè)置為0表示每個(gè)CPU都啟動(dòng)一個(gè)進(jìn)程。
最后的效果是可以看到n+1個(gè)進(jìn)程在運(yùn)行,且公用同一個(gè)端口。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Python使用CMD模塊更優(yōu)雅的運(yùn)行腳本

    Python使用CMD模塊更優(yōu)雅的運(yùn)行腳本

    這篇文章主要介紹了Python使用CMD模塊更優(yōu)雅的運(yùn)行腳本的方法,實(shí)例分析了Python中cmd模塊的相關(guān)使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-05-05
  • OpenCV半小時(shí)掌握基本操作之濾波器

    OpenCV半小時(shí)掌握基本操作之濾波器

    這篇文章主要介紹了OpenCV基本操作之濾波器,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • Django 框架模型操作入門教程

    Django 框架模型操作入門教程

    這篇文章主要介紹了Django 框架模型操作,結(jié)合實(shí)例形式分析了Django框架相關(guān)的數(shù)據(jù)庫(kù)配置、數(shù)據(jù)增刪改查等操作技巧,需要的朋友可以參考下
    2019-11-11
  • PyQt5使用mimeData實(shí)現(xiàn)拖拽事件教程示例解析上

    PyQt5使用mimeData實(shí)現(xiàn)拖拽事件教程示例解析上

    這篇文章主要為大家介紹了PyQt中如何使用mimeData實(shí)現(xiàn)拖拽事件的示例解析過(guò)程,有需要的朋友可以借鑒參考下希望能夠有所幫助,祝大家多多進(jìn)步
    2021-10-10
  • Python自動(dòng)化測(cè)試筆試面試題精選

    Python自動(dòng)化測(cè)試筆試面試題精選

    在本篇文章里小編給大家整理的是一篇關(guān)于Python自動(dòng)化測(cè)試筆試面試時(shí)常見(jiàn)的編程題,需要的朋友們可以學(xué)習(xí)參考下。
    2020-03-03
  • 詳解使用python crontab設(shè)置linux定時(shí)任務(wù)

    詳解使用python crontab設(shè)置linux定時(shí)任務(wù)

    本篇文章主要介紹了使用python crontab設(shè)置linux定時(shí)任務(wù),具有一定的參考價(jià)值,有需要的可以了解一下。
    2016-12-12
  • 使用python os模塊復(fù)制文件到指定文件夾的方法

    使用python os模塊復(fù)制文件到指定文件夾的方法

    今天小編就為大家分享一篇使用python os模塊復(fù)制文件到指定文件夾的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-08-08
  • Python高效處理大文件的方法詳解

    Python高效處理大文件的方法詳解

    在這篇文章中,我們將學(xué)習(xí)如何使用multiprocessing、joblib和tqdm?Python包減少大文件的處理時(shí)間。這是一個(gè)簡(jiǎn)單的教程,可以適用于任何文件、數(shù)據(jù)庫(kù)、圖像、視頻和音頻,感興趣的可以了解一下
    2022-07-07
  • python實(shí)現(xiàn)畫循環(huán)圓

    python實(shí)現(xiàn)畫循環(huán)圓

    今天小編就為大家分享一篇python實(shí)現(xiàn)畫循環(huán)圓,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-11-11
  • Python利用fitz庫(kù)提取pdf中的圖片

    Python利用fitz庫(kù)提取pdf中的圖片

    Fitz庫(kù)是一個(gè)Python圖像處理庫(kù),主要用于打開(kāi)、編輯和保存PDF、TIFF和JPEG格式的圖像,它可以幫助用戶讀取和寫入PDF文件,提取PDF頁(yè)面以及在頁(yè)面上進(jìn)行標(biāo)記和注釋,本文主要介紹了如何通過(guò)Python的fitz庫(kù)提取pdf中的圖片,需要的朋友可以參考下
    2023-05-05

最新評(píng)論