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_delay
IRL 是一个具有大量逻辑的大型函数。基本上我产生了很多线程并向其他 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()
现在我通过这个教程写了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_delay
IRL 是一个具有大量逻辑的大型函数。基本上我产生了很多线程并向其他 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()