我有一个已经使用 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 复用系统调用,需要围绕它构建整体程序架构。

简单来说,一个典型的程序结构可以归结为以下

  • 需要有一堆文件描述符(在您的情况下为非阻塞模式的套接字)
  • 系统调用( man epoll_wait epoll 的情况下)阻塞,直到在一个或多个描述符上发生指定的事件
  • 返回可用于 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/

    10-12 18:47