Python 我怎样做一个 multithreading/asynchronous 带有扭曲的 HTTP 服务器

Python how can I do a multithreading/asynchronous HTTP server with twisted

现在我通过这个教程写了ferver: https://twistedmatrix.com/documents/14.0.0/web/howto/web-in-60/asynchronous-deferred.html 但它似乎只适用于 delayng 进程,实际上并不能同时处理 2 个或更多请求。我的完整代码是:

from twisted.internet.task import deferLater
from twisted.web.resource import Resource
from twisted.web.server import Site, NOT_DONE_YET
from twisted.internet import reactor, threads
from time import sleep


class DelayedResource(Resource):
    def _delayedRender(self, request):
        print 'Sorry to keep you waiting.'
        request.write("<html><body>Sorry to keep you waiting.</body></html>")
        request.finish()

    def make_delay(self, request):
        print 'Sleeping'
        sleep(5)
        return request


    def render_GET(self, request):
        d = threads.deferToThread(self.make_delay, request)
        d.addCallback(self._delayedRender)
        return NOT_DONE_YET

def main():
    root = Resource()
    root.putChild("social", DelayedResource())
    factory = Site(root)
    reactor.listenTCP(8880, factory)
    print 'started httpserver...'
    reactor.run()


if __name__ == '__main__':
    main()

但是当我传递 2 个请求时,控制台输出如下:

睡觉

抱歉让您久等了。

睡觉

抱歉让您久等了。

但如果它是并发的,它应该是这样的:

睡觉

睡觉

抱歉让您久等了。

抱歉让您久等了。

所以问题是如何让 twisted 不等到响应完成再处理下一步? 此外 make_delayIRL 是一个具有大量逻辑的大型函数。基本上我产生了很多线程并向其他 url 发出请求并收集结果介绍响应,所以它可能需要一些时间并且不容易移植

Twisted 在一个事件循环中处理所有事情。如果某些东西阻止了执行,它也会阻止 Twisted。所以你必须防止阻塞调用。

在你的情况下你有 time.sleep(5)。它正在阻塞。您已经在 Twisted 中找到了更好的方法:deferLater()。它 return 是一个 Deferred 将在给定时间后继续执行并释放事件循环,以便其他事情可以同时完成。一般来说,return 推迟的所有事情都是好的。

如果您必须执行由于某种原因无法推迟的繁重工作,您应该使用 deferToThread() 在线程中执行此工作。有关详细信息,请参阅 https://twistedmatrix.com/documents/15.5.0/core/howto/threading.html

您可以在代码中使用 greenlents(如线程)。

您需要安装 geventreactor - https://gist.github.com/yann2192/3394661

并使用reactor.deferToGreenlet()

还有

在您的长计算代码中需要调用 gevent.sleep() 以将上下文更改为另一个 greenlet。

msecs = 5 * 1000
timeout = 100
for xrange(0, msecs, timeout):
    sleep(timeout)
    gevent.sleep()