• tornado 11 异步编程


    tornado 11 异步编程

    一、同步与异步

      同步

    #含义:指两个或两个以上随时间变化的量在变化过程中保持一定的相对关系
    
    #现象:有一个共同的时钟,按来的顺序一个一个处理
    
    #直观感受:需要等待,效率低下

      异步

    #含义:双方不需要共同的时钟,就是接收方不知道发送方什么时候发送,所以在发送的信息中就要有提示接收方开始接受的信息,如开始位,同时在结束时有结束位
    
    #现象:没有共同的时钟,不考虑顺序来了就处理
    
    #直观感受:不需要等待,效率高

    二、阻塞与非阻塞

      阻塞调用

    #含义:阻塞调用是指在调用结果返回之前,当前线程会被挂起(线程进入非可执行状态,在这个状态下,CPU不会给线程分配时间片,即线程暂停运行)。函数只有在得到结果之后才会返回
    
    #现象:读套接字是没用数据等数据来,写套接字时写不下了也一直等,等能写下了往下写(套接字被写满的原因不在本地,在于网络另一头的套接字被写满了来不及读出去,导致本地的套接字内容发不出来,堵住了)
    
    #直观感受:执着

      非阻塞调用

    #含义:非阻塞调用是指没有调用结果立即返回,当前线程不被挂起,可以继续做其他工作
    
    #现象:读套接字是没有数据,不等直接返回干别得事情去了,写套接字写不下了也不写了,直接返回干别的事情去了
    
    #直观感受:勤奋

    三、异步编程

    #tornado是单线程的,一次只能处理一个请求;但是由于他是异步的,所以是高并发的
    
    #那么在tornado中,同时有多个请求发送过来时,而且其中还有请求发生阻塞,会产生什么样的后果呢?
    #在实现第四种异步方法的时候需要导入两个模块
    
    futures requests
    import time
    import tornado.ioloop
    import tornado.options
    import tornado.web
    from tornado.options import define,options
    from tornado.web import authenticated
    import tornado.websocket
    import tornado.httpclient
    import tornado.gen
    from tornado.concurrent import run_on_executor
    from concurrent.futures import ThreadPoolExecutor
    import requests
    import util.ui_methods
    import util.ui_modules
    from data.user_modules import User #导入module包
    from pycket.session import SessionMixin
    import  datetime
    
    
    
    define('port',default=8080,help = 'run port',type=int)
    
    class BaseHandler(tornado.web.RequestHandler,SessionMixin):
        def get_current_user(self):
            current_user = self.session.get('user')
            if current_user:
                return current_user
            return None
    
    class AbcHandler(BaseHandler):
        def get(self):
            self.write('abc ok')
    
    class SyncHandler(BaseHandler):
        def get(self):
            client = tornado.httpclient.HTTPClient()
            response = client.fetch('http://127.0.0.1:8080/sync?id=2') #这是模拟阻塞的接口,该接口代码里面有sleep用来模拟阻塞
            print(response)
            self.write(response.body)
    
    #1、通过回调函数实现异步
    class CallbcakHandler(BaseHandler): #这便是异步的方法,在阻塞的时候就直接处理其他的请求
        @tornado.web.asynchronous  #必须得装上装饰器
        def get(self):
            client = tornado.httpclient.AsyncHTTPClient()
            response = client.fetch('http://127.0.0.1:8080/sync?id=2',callback=self.on_response) #当这个地方发生阻塞时,并没有在这个地方等待,而是后面的全部处理完了才来处理这个
            self.write('ok') #这便是通过回调函数实现异步,先出现ok,在回到上面
    
        def on_response(self,res):
            print(res)
            self.write(res.body)
            self.finish() #在这个回调函数中必须加上finish,不加上的话就会不知道上面的接口函数什么时候结束
    
    #2、通过协程实现异步
    class GenHandler(BaseHandler):
        @tornado.web.asynchronous
        @tornado.gen.coroutine #协程
        def get(self):
            client = tornado.httpclient.AsyncHTTPClient()
            response = yield tornado.gen.Task(client.fetch,'http://127.0.0.1:8080/sync?id=2') #yield生成器,有等待、暂停的功能
            self.write(response.body)
    
    #3、通过协程实现异步(自定义函数) 更加灵活
    class FuncHandler(BaseHandler):
        @tornado.web.asynchronous
        @tornado.gen.coroutine #协程
        def get(self):
            response = yield self.func()
            self.write(response.body)
    
        @tornado.gen.coroutine
        def func(self):
            client = tornado.httpclient.AsyncHTTPClient()
            response = yield tornado.gen.Task(client.fetch, 'http://127.0.0.1:8080/sync?id=2')  # yield生成器,有等待、暂停的功能
            raise tornado.gen.Return(response)
    
    #4、通过requests包来实现异步,都是使用装饰器
    class MyHandler(BaseHandler):
        executor = ThreadPoolExecutor()
        @tornado.web.asynchronous
        @tornado.gen.coroutine
        def get(self):
            response = yield self.func()
            self.write(response.text)
    
        @run_on_executor
        def func(self):
            res = requests.get('http://127.0.0.1:8080/sync?id=2')
            return res
    
    application = tornado.web.Application(
            handlers=[
                (r'/abc',AbcHandler),
                (r'/sync', SyncHandler),
                (r'/call', CallbcakHandler),
                (r'/gen', GenHandler),
                (r'/func', FuncHandler),
                (r'/my', MyHandler),
    
            ],
            template_path = 'templates',
            static_path= 'static',
            autoescape = None,
            ui_methods=util.ui_methods,
            ui_modules=util.ui_modules,
            cookie_secret = 'lidang',
            login_url = '/login',
            pycket = {
                'engine':'redis',
                'storage':{
                    'host':'localhost',
                    'port':6379,
                    'db_sessions':5,
                    'db_notifications':11,
                    'max_connections':2 ** 33,
                },
                'cookie':{
                    'expires_days':38,
                    'max_age':100
                }
            },
            debug=True
        )
    
    if __name__ == '__main__':
        tornado.options.parse_command_line()
        http_server = tornado.httpserver.HTTPServer(application)
        http_server.listen(options.port)
        tornado.ioloop.IOLoop.instance().start()
  • 相关阅读:
    用spring tool suite插件创建spring boot项目时报An internal error occurred during: "Building UI model". com/google/common/
    Eclipse卸载插件SpringSoource-tool-suite
    spring-tool-suite使用教程,并创建spring配置文件
    MySQL获取指定长度的字符串的函数left(s,n)和right(s,n)
    maven web项目配置log4j,及log4j参数设置
    Caused by: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'zoneId' in 'class java.lang.String'
    ifconfig 输出里没有IP地址
    maven web项目生成WebContent或WebRoot目录
    Window 命令行神器:cmder
    Filezilla Download for Linux (deb, rpm, txz, xz, amd64, i386, i486, i586, i686, x86_64)
  • 原文地址:https://www.cnblogs.com/xuchengcheng1215/p/9074204.html
Copyright © 2020-2023  润新知