ag娱乐平台
你好,游客 登录 注册
背景:
阅读新闻

Tornado实现多进程/多线程的HTTP服务

[日期:2019-04-09] 来源:Linux社区  作者:zhichaoma [字体: ]

ag娱乐平台,现代投资银行是中国特色国防金融生态的核心中介,除了弥补财政资金不足、为军工集团筹措资金外,最重要的作用是发挥金融优化资源配置的核心职能,在借鉴欧美资本市场“以军促民、以民养军”的实践经验基础上,结合我国政治、经济、地缘等实际情况,灵活利用股权、债权、衍生品等现代金融工具,做好国防工业产业链投资的“金融过滤器”,提高武器研发资金的使用效率,并促进军用技术融入宏观经济新常态下的供给侧结构改革,为持续全面的尖端武器研发和军民融合提供机制与资金的保障。▲(作者是中航证券有限公司首席经济学家)

随后,淘宝上开始出现大量提供“掌上电力绑定”服务的店铺,他们给各省电力公司提供关注、注册、绑定等服务,为各省的掌上电力迅速增加“用户量”。记者通过qq联系上一位可以提供此类服务的商户,据商户介绍,只需提供户号和户号密码,手机号码商铺自己搞定,做完提供清单。穆里尼奥:曼联今夏不会买攻击手 媒体别编故事了以开车为职业的人都有这样的职业病,颈椎增生、腰肌劳损等;其实这些都是因为错误的驾驶姿势造成的。那怎样的坐姿可以减少对人体的伤害呢?平常大家开车又有哪些错误的驾驶姿势?下面我们一起来看一下。

用Tornado Web服务的基本流程

1.实现处理请求的Handler,该类继承自tornado.web.RequestHandler,实现用于处理请求的对应方法如:get、post等。返回内容用self.write方法输出。

2.实例化一个Application。构造函数的参数是一个Handlers列表,通过正则表达式,将请求与Handler对应起来。通过dict将Handler需要的其他对象以参数的方式传递给Handler的initialize方法。

3.初始化一个tornado.httpserver.HTTPServer对象,构造函数的参数是上一步的Application对象。

4.为HTTPServer对象绑定一个端口。

5.开始IOLoop。

需要用到的特性

由于tornado的亮点是异步请求,所以这里首先想到的是将所有请求都改造为异步的。但是这里遇到一个问题,就是异步函数内一定不能有阻塞调用出现,否则整个IOLoop都会被卡住。这就要求彻底地去改造服务,将所有IO或是用时较长的请求都改造为异步函数。这个工程量是非常大的,需要去修改已有的代码。因此,我们考虑用线程池的方式去实现。当一个线程阻塞在某个请求或IO时,其他线程或IOLoop会继续执行。

另外一个瓶颈就是GIL限制了CPU的并发数量,因此考虑用子进程的方式增加进程数,提高服务能力上限。

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

1.通过子进程的方式复制多个进程,使子进程中的只读页指向同一个物理页。

2.线程池。回避异步改造的工作量,增加IO的并发量。

测试代码

首先测试线程池,测试用例为:

对sleep页面同时发出两个请求:

1.在线程池中运行的函数(这里是self.block_task)能够同时执行。表现为在控制台交替打印出数字。

2.两个get请求几乎同时返回,在浏览器上显示返回的内容。

线程池的测试代码如下:

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)  #起线程池,由当前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()

整个代码里有几个位置值得关注:

1.executor = ThreadPoolExecutor(20)。这是给Handler类初始化了一个线程池。其中concurrent.futures不属于tornado,是Python的一个独立模块,在python3中是内置模块,python2.7需要自己安装。

2.修饰符@run_on_executor。这个修饰符将同步函数改造为在executor(这里是线程池)上运行的异步函数,内部实现是将被修饰的函数submit到executor,返回一个Future对象。

3.修饰符@tornado.gen.coroutine。被这个修饰符修饰的函数,是一个以同步函数方式编写的异步函数。原本通过callback方式编写的异步代码,有了这个修饰符,可以通过yield一个Future的方式来写。被修饰的函数在yield了一个Future对象后将会被挂起,Future对象的结果返回后继续执行。

运行代码后,在两个不同浏览器上访问sleep页面,得到了想要的效果。这里有一个小插曲,就是如果在同一浏览器的两个tab上进行测试,是无法看到想要的效果。第二个get请求会被block,直到第一个get请求返回,服务端才开始处理第二个get请求。这让我一度觉得多线程没有生效,用了半天时间查了很多资料,才看到是浏览器把相同的第二个请求block了,具体链接参考这里。

由于tornado很方便地支持多进程模型,多进程的使用要简单很多,在以上例子中,只需要对启动部分稍作改动即可。具体代码如下所示:

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()

需要注意的地方有两点:

app = tornado.web.Application(handlers=[(r"/sleep", HasBlockTaskHandler)], autoreload=False, debug=False),在生成Application对象时,要将autoreload和debug两个参数至为False。也就是需要保证在fork子进程之前IOLoop是未被初始化的。这个可以通过tornado.ioloop.IOLoop.initialized()函数来跟。
http_server.start(5)在启动IOLoop之前通过start函数设置进程数量,如果设置为0表示每个CPU都启动一个进程。

最后的效果是可以看到n+1个进程在运行,且公用同一个端口。

Linux公社的RSS地址/wwwc0b7linuxidcc0b7com/rssFeed.aspx

本文永久更新链接地址/wwwc0b7linuxidcc0b7com/Linux/2019-04/158006.htm

linux
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款
英国两名IS成员在美受审 英罕见称不反对死刑 王毅:“一带一路”不仅惠及中国 更要造福世界 日本千叶县发生5.3级地震 无发生海啸危险 朝因美韩军演暂停朝韩会谈 告诫美珍视朝美峰会 美国务卿:伊朗领导人是“黑手党”“披羊皮的狼” 全国人大代表欧阳昌琼:应大力支持新经济企业上市 中国金洋:预期港股表现仍反复 行业板块料个别发展 国务院批复同意将河北蔚县列为国家历史文化名城 荣昊:曹赟定受伤我联系了申花 身体状况没问题 林书豪为Jr. NBA世界冠军赛赴美球员打气 香港赛马史上第一例闸箱事故 赛事董事退上亿赛注 一文读懂国务院机构改革方案
波音就贸易战发声明:航空工业强大对中美都很重要 NASA将发冷原子实验室 探测地球无法观察的量子现象 外媒:美国最快可能8月轰炸伊朗 这两国将协助 人民陪审员法草案二审:影响重大案件纳入参审范围 微商卖网红神药销售上千万 客服扮多个角色推销产品 货币新趋势?波兰将开发国家加密货币 肖亚庆:鼓励央企“走出去” 加大国际化力度 中甲-桑达扎破僵土炮开火 黄海3-0黑龙江保持不败 吕斌微博宣布从体制内退役 未来将转型职业赛场 拼多多最终定价19美元 IPO认购或超募20倍 利用假证假人骗公证屡有发生 多部门将综合整治 留美女博士死亡内幕曝光:导师迟迟不准许毕业
库里低迷并非因为伤病 火箭这招真的奏效了 苹果期货大幅上涨 全国人大代表董明珠:中国制造有一天能服务全世界 皮蓬家里被盗损失5万刀!但为啥这东西会有人偷 “创维e家”山寨术:厂家申请11个商标轮流“碰瓷” 泰国快艇爆炸事件13名受伤中国游客回国 凤凰新媒体第四季度营收4.6亿元 净利同比降70% 男子连续出脚踹碎玻璃门后 扭头鞠躬“致敬” 二百年老死不相往来 两个村庄终于一酒泯“世仇” 马尔代夫总统宣布全国实行紧急状态 为期15天 汾渭平原代替珠三角 首次列为大气污染防治主战场 吴键汪文展当选西安市政协副主席 万字长文解读|亚马逊的AI革命:从追随者到巨头 ag娱乐平台