Python tornado web server: How to use multiprocess

2019-04-17 07:53发布

问题:

I have a web application that runs fine when used by one user, but as more clients start using it, it is unbearably slow. The server side is written in python and uses tornado. I noticed that while the server it's running on has 4 cores, only 1 is being used, so I've started looking at python's multiprocessing. I've seen the basic example from: http://sebastianraschka.com/Articles/2014_multiprocessing_intro.html and the tornado processors from: http://tornado.readthedocs.org/en/latest/_modules/tornado/process.html (which seems a bit more complicated), but I'm still not sure this is what I'm looking for. Will running this code with 4 processors speed it up when say 50 users are viewing it at once? And if so are one of these options the way to go for implementation when using tornado web server?

Sorry for the vague and poorly written question - my lack of experience with multiprocessing is to blame for this, even after extensive research. If any example code will help with answering this question, please let me know.

Thanks!

回答1:

You can run multiple tornado workers with code like this:

import tornado.web
import tornado.httpserver
import tornado.ioloop

class MyHandler(tornado.web.RequestHandler):

    @tornado.web.asynchronous
    def get(self):
        self.write('OK')
        self.finish()

if __name__=='__main__':
    app = tornado.web.Application([(r'/', MyHandler)])

    server = tornado.httpserver.HTTPServer(app)
    server.bind(8888)

    server.start(4) # Specify number of subprocesses

    tornado.ioloop.IOLoop.current().start()

Although it's pretty strange that your app have problems serving 50 users even on one core. Do you have some heavy computations there, or do you use any blocking libs?

Make sure you use @tornado.web.asynchronous or @tornado.gen.coroutine decorators on your handler methods, otherwise you are just running your code synchronously.

UPDATE: In order to do the heavy-lifting work in a separate process you can use concurrent.futures.ProcessPoolExecutor. Take a look at this answer: https://stackoverflow.com/a/25208213/1525432.