tornado 实现 将阻塞函数 改变为非阻塞 助力并发开发

背景

python 并发最强大的地方 就是使用协程。 tornado 基于事件循环, 轮询的方式来实现并发, 在阅读本篇文章的时候 默认为你有了一定的 基础知识, 使用过yield yield from async await 并充分理解了。 django 每创建一个连接就会创建一个线程, 这样对服务器的要求比较高, 服务器的压力比较大。 tornado 充分利用协程实现并发, 使用各种异步库来实现并发。 但是还有很多没有优秀的异步库, 或者说是不稳定。 例如mysql 目前没有敢用的 异步操作mysql的库。 现在最好的办法就是 将这样的阻塞函数 通过一定的方法给转化为非阻塞的。

一、在for 循环中使用

比如下载的时候网络IO流 是阻塞的 一种方法是变为非阻塞的, 一种方法是使用异步访问库。

直接将方法变为非阻塞的函数

from concurrent import futures
from flags import save_flag, get_flag, show, main

MAX_WORKERS = 20
def download_one(cc):
    image = get_flag(cc)
    show(cc)
    save_flag(image, cc.lower() + '.gif')
    return cc
def download_many(cc_list):
    workers = min(MAX_WORKERS, len(cc_list))
    with futures.ThreadPoolExecutor(workers) as executor:
        res = executor.map(download_one, sorted(cc_list))
    return len(list(res))
if __name__ == '__main__':
    main(download_many) 

以上是伪代码,内部使用的是多线程。使用map过后 能直接得到结果, 是一个生成器。 要获取到具体的值要调用迭代器, 进行循环获取。 map的优点是 能够保证顺序, 按照进去的顺序出来 res 的值。 确定是, 等到所有的任务排定完再执行 任务。 这样不能达到最快, 拆分的话 不能保证顺序但是 是当任务出来之后就会执行。 用比较官网的说法。

map 方法的作用与内置的map函数类型类似, 不过download_one 函数会在多个线程中并发调用; map 方法返回一个生成器, 因此可以迭代,, 获取各个函数返回的值。
注意: 编写并发代码时候经常这样重构: 把依次for 循环体改成函数, 以便这样并发调用。

为了了解future (期物) 现在来慢慢介绍下
我们目前用的库是concurrent.futures

标准库中有两个名为Future 的类: concurrent.futures.Future 和asyncio.Future. 两个类的作用相同:两个类都表示可能已经完成或

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Tornado可以通过`@tornado.web.stream_request_body`装饰器来实现异步并行非阻塞的Server-Sent Events。具体步骤如下: 1. 创建一个继承自`tornado.web.RequestHandler`的类,添加`@tornado.web.stream_request_body`装饰器。 ```python import tornado.web class SSEHandler(tornado.web.RequestHandler): @tornado.web.stream_request_body def post(self): pass ``` 2. 在`post`方法中,使用`tornado.ioloop.IOLoop.current().spawn_callback`方法来异步执行数据的生成和推送,并使用`tornado.web.RequestHandler.flush`方法将数据发送给客户端。 ```python import tornado.web import tornado.ioloop class SSEHandler(tornado.web.RequestHandler): @tornado.web.stream_request_body def post(self): self.set_header('Content-Type', 'text/event-stream') self.set_header('Cache-Control', 'no-cache') self.set_header('Connection', 'keep-alive') def generate_data(): data = 'data: Hello, world!\n\n' self.write(data) self.flush() tornado.ioloop.IOLoop.current().spawn_callback(generate_data) ``` 在这个例子中,我们设置了响应头,告诉客户端我们要发送的是Server-Sent Events。然后在`generate_data`函数中,生成一条消息并使用`write`方法将其写入响应中,再使用`flush`方法将数据发送给客户端。最后,在`post`方法中使用`IOLoop.current().spawn_callback`方法来异步执行`generate_data`函数。 3. 在客户端使用`EventSource`对象来接收推送的数据。 ```javascript var source = new EventSource('/sse'); source.onmessage = function(event) { console.log(event.data); }; ``` 在客户端中,我们使用`EventSource`对象来向服务器发送请求,并监听`onmessage`事件来接收推送的数据。在接收到数据时,我们可以在控制台中打印出来。 以上就是使用Tornado实现异步并行非阻塞的Server-Sent Events的步骤。在实际应用中,可以在`generate_data`函数中根据需要生成不同的数据,并使用`write`和`flush`方法将数据推送给客户端。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值