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

Now I wrote ferver by this tutorial: https://twistedmatrix.com/documents/14.0.0/web/howto/web-in-60/asynchronous-deferred.html But it seems to be good only for delayng process, not actually concurently process 2 or more requests. My full code is:

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()

But when I passing 2 requests console output is like:

Sleeping

Sorry to keep you waiting.

Sleeping

Sorry to keep you waiting.

But if it was concurrent it should be like:

Sleeping

Sleeping

Sorry to keep you waiting.

Sorry to keep you waiting.

So the question is how to make twisted not to wait until response is finished before processing next? Also make_delayIRL is a large function with heavi logic. Basically I spawn lot of threads and make requests to other urls and collecting results intro response, so it can take some time and not easly to be ported

Answers


Twisted processes everything in one event loop. If somethings blocks the execution, it also blocks Twisted. So you have to prevent blocking calls.

In your case you have time.sleep(5). It is blocking. You found the better way to do it in Twisted already: deferLater(). It returns a Deferred that will continue execution after the given time and release the events loop so other things can be done meanwhile. In general all things that return a deferred are good.

If you have to do heavy work that for some reason can not be deferred, you should use deferToThread() to execute this work in a thread. See https://twistedmatrix.com/documents/15.5.0/core/howto/threading.html for details.


You can use greenlents in your code (like threads).

You need to install the geventreactor - https://gist.github.com/yann2192/3394661

And use reactor.deferToGreenlet()

Also

In your long-calculation code need to call gevent.sleep() for change context to another greenlet.

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

Need Your Help

How to send information from android app to SOTI MobiControl?

android mdm soti

I have a setup with an android device managed by the MDM Soti / MobiControl.

Java - Human playable Server/Client Multiplayer

java eclipse networking

I'm currently trying to implement the game of Nim using Java, I want to be able to have one player act as the server and another as the player.