【问题标题】:Python how can I do a multithreading/asynchronous HTTP server with twistedPython如何使用twisted来做一个多线程/异步HTTP服务器
【发布时间】:2016-03-08 01:37:49
【问题描述】:

现在我通过本教程编写了 ferver: https://twistedmatrix.com/documents/14.0.0/web/howto/web-in-60/asynchronous-deferred.html 但这似乎只适用于延迟过程,实际上并不能同时处理 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 发出请求并收集结果介绍响应,因此可能需要一些时间并且不容易移植

【问题讨论】:

    标签: python multithreading http server twisted


    【解决方案1】:

    您可以在代码中使用 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()
    

    【讨论】:

      【解决方案2】:

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

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

      如果你必须做一些由于某种原因不能推迟的繁重工作,你应该使用deferToThread()在一个线程中执行这项工作。详情请见https://twistedmatrix.com/documents/15.5.0/core/howto/threading.html

      【讨论】:

      • 还是不太明白:我以为deferLater() 会先等待一段时间(在我的情况下为一秒)然后执行,阻塞循环,不是吗?我试试deferToThread()
      • deferLater() 只是注册要在给定时间后执行的调用。它会立即返回。您的整个render_GET 方法将在几毫秒内执行。当注册的执行时间到达时,make_delay() 将被调用,它会阻塞 everything 5 秒。之后,回调_delayedRender() 将完成请求。
      • deferToThread() 产生相同的结果。可能是因为NOT_DONE_YET
      • 在问题上运行当前代码示例,不,它不会产生相同的结果。这是直接从我的 shell 粘贴的:``` $ python webstuff.py & [1] 89589 $ started httpserver... $ curl localhost:8880/social & curl localhost:8880/social & [2] 89591 [3] 89592 $ Sleeping Sleeping sorry让你久等。抱歉让你久等了。 抱歉让您久等了。抱歉让您久等了。 ``
      • 有趣的事情:当我通过在浏览器中打开 2 个页面进行测试时,它的行为就像它是单线程的,但是如果我在 2 个不同的浏览器或 corl 中打开页面 - 它确实是线程的。想知道为什么?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      • 2013-09-05
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多