I am trying to use gevent as wsgi server, and use tornado WSGIApplication to process requests. Here's the code
#!/usr/bin/env python
# coding=utf-8
import gevent
from gevent import monkey
monkey.patch_all(thread=False)
from gevent.pywsgi import WSGIServer
from tornado.wsgi import WSGIApplication
import tornado.web
import tornado.wsgi
import requests
class MainHandler(tornado.web.RequestHandler):
def get(self):
requests.get('http://google.com')
self.write('hello')
handlers = [
(r'/', MainHandler)
]
if __name__ == '__main__':
application = WSGIApplication(handlers)
server = WSGIServer(('', 9010), application)
server.serve_forever()
And I use apache benchmark to test the performance. Test command is
ab -n 1000 -c 100 http://127.0.0.1:9010/
This resulting 100req per second, it is too slow. In the above code, I just put a http request to other side, I think in this situation, gevent will switch to other greenlet when block, and it should has little influence on the performance, but gevent's performance decrease from 1600req per second to 100 req per second, I can't figure out why.
Could anyone explain this?
Tornado (Twisted) and gevent do the same things, and for best results you should stay within the same technology stacks and not mix the two. Either use a WSGI web framework with gevent like bottle or flask, or use twisted and tornado together.
Hi you're issue is that you aren't spawning an actual greenlet and that the tornado.web.ascynhronous decorator does nos support WSGI servers.
But the main logic works and I was able to get it working with a HTTP server (I don't know if you're tied to a WSGI server, but I guess not since you can just reverse proxy just as well).
I find a lot of people wanting to use gevent with tornado, me included (we use tornado and gevent at FriendCode), so I wrote this:
In this sample there are two key parts, the monkey patching part that you got right and then the gasync decorator that I wrote, all it does is set a method to being asynchronous (by tornado's terms, which means that the method has to call self.finish() by itself to send the response to the client, because tornado calls it automatically when the request is synchronous, but it's not what you want in async).
I hope that helps, the code works fine here I've tested it with :
Which gives :
As you can see the total time there is roughly equal to the time of the longest request, remember that when async :
Where n is the number of requests, and some_overhead a constant overhead.
Hope that helps :)
I had the same need, but i'm working with futures and gen.coroutine, so i had to modify it just a little to be compatible with my code, i'm putting it here if anyone else need it too:
Try to test
requests
package only with gevent sample application to chceck if it is truly asynchronous. Maybe the reason is that gevent doesn't patch correctly everything required byrequests
But I think that your solution is not asynchronous from gevent site: you are trying to run 2 event loops. I guess the process, you present, looks following:
get
method, which runs gevent event loop (gevent starts the event loop implicitly in a dedicated greenlet)Look also at some success combination of Tornado and greenlets: tornalet, Motor.