Python3学习(五十九):Python的Tornado框架的异步任务与AsyncHTTPClient

编程入门 行业动态 更新时间:2024-10-23 03:28:34

Python3学习(五十九):Python的Tornado<a href=https://www.elefans.com/category/jswz/34/1770644.html style=框架的异步任务与AsyncHTTPClient"/>

Python3学习(五十九):Python的Tornado框架的异步任务与AsyncHTTPClient

转载自.html

 

高性能服务器Tornado
Python的web框架名目繁多,各有千秋。正如光荣属于希腊,伟大属于罗马。Python的优雅结合WSGI的设计,让web框架接口实现千秋一统。WSGI 把应用(Application)和服务器(Server)结合起来。Django 和 Flask 都可以结合 gunicon 搭建部署应用。

 

与 django 和 flask 不一样,tornado 既可以是 wsgi 应用,也可以是 wsgi 服务。当然,选择tornado更多的考量源于其单进程单线程异步IO的网络模式。高性能往往吸引人,可是有不少朋友使用之后会提出疑问,tornado号称高性能,实际使用的时候却怎么感受不到呢?

实际上,高性能源于Tornado基于Epoll(unix为kqueue)的异步网络IO。因为tornado的单线程机制,一不小心就容易写出阻塞服务(block)的代码。不但没有性能提高,反而会让性能急剧下降。因此,探索tornado的异步使用方式很有必要。

Tornado 异步使用方式
简而言之,Tornado的异步包括两个方面,异步服务端和异步客户端。无论服务端和客户端,具体的异步模型又可以分为回调(callback)和协程(coroutine)。具体应用场景,也没有很明确的界限。往往一个请求服务里还包含对别的服务的客户端异步请求。

服务端异步方式
服务端异步,可以理解为一个tornado请求之内,需要做一个耗时的任务。直接写在业务逻辑里可能会block整个服务。因此可以把这个任务放到异步处理,实现异步的方式就有两种,一种是yield挂起函数,另外一种就是使用类线程池的方式。请看一个同步例子:

1

2

3

4

5

6

class SyncHandler(tornado.web.RequestHandler):

 

  def get(self, *args, **kwargs):

    # 耗时的代码

    os.system("ping -c 2 www.google")

    self.finish('It works')

 

使用ab测试一下:

1

ab -c 5 -n 5 http://127.0.0.1:5000/sync

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

Server Software:    TornadoServer/4.3

Server Hostname:    127.0.0.1

Server Port:      5000

 

Document Path:     /sync

Document Length:    5 bytes

 

Concurrency Level:   5

Time taken for tests:  5.076 seconds

Complete requests:   5

Failed requests:    0

Total transferred:   985 bytes

HTML transferred:    25 bytes

Requests per second:  0.99 [#/sec] (mean)

Time per request:    5076.015 [ms] (mean)

Time per request:    1015.203 [ms] (mean, across all concurrent requests)

Transfer rate:     0.19 [Kbytes/sec] received

 

qps 仅有可怜的 0.99,姑且当成每秒处理一个请求吧。

下面祭出异步大法:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

class AsyncHandler(tornado.web.RequestHandler):

  @tornado.web.asynchronous

  @tornado.gen.coroutine

  def get(self, *args, **kwargs):

 

    tornado.ioloop.IOLoop.instance().add_timeout(1, callback=functools.partial(self.ping, 'www.google'))

 

    # do something others

 

    self.finish('It works')

 

  @tornado.gen.coroutine

  def ping(self, url):

    os.system("ping -c 2 {}".format(url))

    return 'after'

 

尽管在执行异步任务的时候选择了timeout 1秒,主线程的返回还是很快的。ab压测如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

Document Path:     /async

Document Length:    5 bytes

 

Concurrency Level:   5

Time taken for tests:  0.009 seconds

Complete requests:   5

Failed requests:    0

Total transferred:   985 bytes

HTML transferred:    25 bytes

Requests per second:  556.92 [#/sec] (mean)

Time per request:    8.978 [ms] (mean)

Time per request:    1.796 [ms] (mean, across all concurrent requests)

Transfer rate:     107.14 [Kbytes/sec] received

 

上述的使用方式,通过tornado的IO循环,把可以把耗时的任务放到后台异步计算,请求可以接着做别的计算。可是,经常有一些耗时的任务完成之后,我们需要其计算的结果。此时这种方式就不行了。车道山前必有路,只需要切换一异步方式即可。下面使用协程来改写:

1

2

3

4

5

6

7

8

9

10

11

12

13

class AsyncTaskHandler(tornado.web.RequestHandler):

  @tornado.web.asynchronous

  @tornado.gen.coroutine

  def get(self, *args, **kwargs):

    # yield 结果

    response = yield <

更多推荐

Python3学习(五十九):Python的Tornado框架的异步任务与AsyncHTTPClient

本文发布于:2024-02-06 18:39:27,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1751071.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:框架   五十九   Python   AsyncHTTPClient   Tornado

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!