关于 django 中使用 asyncio 的一个疑问

2019-04-01 00:08:09 +08:00
 welkinzh

在 django view 中使用 asyncio 去调用十次外部 api,经过测试确实比同步请求快,但是搜索 django asyncio 相关问题时,发现有人说:在 django view 中使用 asyncio,会阻塞整个 django worker,这一点有些不能理解,有人能解释一下吗,如果不使用异步请求,用 celery 的 group 去做,这两者有什么区别?

问题来源: https://stackoverflow.com/questions/44667242/python-asyncio-in-django-view#comment88445130_44683173

3305 次点击
所在节点    Python
9 条回复
so1n
2019-04-01 00:24:37 +08:00
django 是同步的啊,自己本来的 request/response 周期也就是同步的(也就是一个 view )。如果你这个周期里面有十个外部 API 请求,那这个周期的时间能减少,但没有办法做到先返回响应,再去异步请求,可以使用 Django channel 来让 view 异步
welkinzh
2019-04-01 00:33:04 +08:00
@so1n 如果这个 view 的过程就是请求这些 api,然后处理返回的结果最后响应,那使用 asyncio 是不是就达到了减少响应时间这个目的呢,这样看的话,和使用 celery 的效果是一样的,我的理解对吗
welkinzh
2019-04-01 00:44:33 +08:00
我想我可能理解错那条评论的意思了,run_until_complete 会阻塞当前请求,而不会影响其他请求。贴上评论


@Juanvulcano it works faster because you run async requests concurrently. However, loop.run_until_complete(main(language1, language2)) blocks further execution until async actions are complete. That means django worker won't be able to serve other requests till this one is complete.
so1n
2019-04-01 00:57:12 +08:00
@welkinzh run_until_complete 阻塞当前线程,一个请求开一个线程,应该不会阻塞到其他请求的。
welkinzh
2019-04-01 00:59:12 +08:00
@so1n 谢谢,理解了
so1n
2019-04-01 01:02:33 +08:00
@welkinzh 不过最好自己测试一下
neoblackcap
2019-04-01 07:22:03 +08:00
@welkinzh 可以的,你的用法是正确的。你的使用相当于收集了好几个远程 API 的结果。不过嘛,一般我们不会这样使用 asyncio。如果你的处理牵涉到大量的网络请求,我建议你使用 Tornado 之类的框架进行网络 IO 重写,让 Tornado/asyncio 负责处理网络 IO,Django 这边就单纯地使用一个 requests 去请求 Tornado/asyncio 暴露出来的 API 就好了。
Qzier
2019-04-01 11:07:57 +08:00
loop.run_until_complete() 是同步代码,当然会阻塞,再说了 Django 本来就是同步框架,如果你不想阻塞,要么用再开一个线程,要么把任务交给 Celery。
welkinzh
2019-04-01 11:58:23 +08:00
@Qzier 嗯嗯,只阻塞当前请求的线程就是我期望的结果了,因为我需要批量请求外部 api 然后处理 api 返回的结果。虽然会阻塞,但是比同步去请求快很多。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/550636

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX