我有一个已经使用 select.epoll() 的面向事件的服务器。
现在应该解决一个新要求:应该获取 URL(异步)。
到现在我一直在使用requests库,而且我一直都是同步使用的,从来没有异步使用过。
如何将请求库(或不同的 urllib)与 linux epoll 结合使用?
requests 库文档对此有注释,但只提到了异步框架(不是 select.epoll()):http://docs.python-requests.org/en/master/user/advanced/#blocking-or-non-blocking
我没有和 select.epoll() 结婚。它一直工作到现在。如果可行,我可以使用不同的解决方案。
背景:更大的问题是“我应该使用 select.epoll() 还是 python 拥有的众多异步框架之一?”。但是 StackOverflow 上的问题不能太宽泛。这就是为什么这个问题侧重于“通过 select.epoll() 检索多个 URL”。如果您对更大的问题有任何提示,请发表评论。
如果你好奇,我在业余时间开发的一个小项目中需要这个问题:https://github.com/guettli/ipo(IPO是一个基于PostgreSQL的开源异步作业队列。)
最佳答案
如何将请求库(或不同的 urllib)与 linux epoll 结合使用?
不幸的是,除非这样的库是在考虑到这种集成的情况下构建的,否则你不能这样做。 epoll 以及 select / poll / kqueue 等都是 I/O 复用系统调用,需要围绕它构建整体程序架构。
简单来说,一个典型的程序结构可以归结为以下
之后这是处理这些描述符的外部代码的工作,即确定有多少数据可用,调用一些回调等。
如果库使用常规阻塞套接字,并行化它的唯一方法是使用线程/进程
这是关于这个主题的一个很好的 article,示例使用 C 语言,这很好,因为它更容易理解幕后实际发生的事情
异步框架和请求库
让我们看看有什么建议 here
请求线程 - 使用线程
grequests - 与 gevent 集成(这是一个不同的故事,见下文)
请求 future - 实际上也是线程/进程
它们都与真正的异步性无关
我应该使用 select.epoll() 还是 python 拥有的众多异步框架之一
请注意, epoll 是特定于 linux 的野兽,它不会工作,即在具有称为 kqueue 的不同机制的 OS X 上。由于您似乎正在编写通用作业队列,这似乎不是一个好的解决方案。
现在回到python。您有以下选择:
线程/进程/concurrent.futures - 这不太可能是你的目标,因为你的应用程序是一个典型的 C10K 服务器
epoll/kqueue - 你必须自己做所有事情。在获取 HTTP url 的情况下,您不仅需要处理 http/ssl,还需要处理异步 DNS 解析。还可以考虑使用提供一些基本基础设施的 asyncore []
扭曲/ Tornado - 基于回调的框架,已经为您完成所有低级工作
gevent - 如果您要重用现有的阻塞库(urllib、请求等)并同时使用 python 2.x 和 python 3.x,这可能是您喜欢的。但是这个解决方案是设计上的一个黑客。对于您这种规模的应用程序,它可能没问题,但我不会将它用于任何更大的应用程序,它应该坚如磐石并在产品中运行
异步
它拥有您可能需要的一切。
还有一堆库使用流行的 RDBM 和 http
https://github.com/aio-libs
但它缺乏对 python 2.x 的支持。 python 2.x 有 asyncio 的 ports 但不确定它们有多稳定
最后
因此,如果我可以牺牲 python 2.x,我会亲自使用 asyncio 和相关库
如果您真的需要 python 2.x,请根据所需的稳定性和假设的峰值负载使用上述方法之一
关于Python:通过 select.epoll() 检索多个 URL,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48066225/