0

I have a websocket server written in python tornado. the server will receive many connections from clients and as you know, we have on_message function that is fired when a websocket message is received. so, here is my question that if a message(say request from client) need 5 sec to be processed then when the server is processing some request, the server goes in blocking mode and can't accept or receive more connection or data. after some research i figure out that Asyncio can resolve my problem but i don't now know to use it. so, how do i call process method to avoid blocking?

following is my code:

class WavesClient(tornado.websocket.WebSocketHandler):
    def check_origin(self, origin):
        return True
    def open(self):
        print("New client connected")

   def on_message(self, message):
        self.process(message)

   def on_close(self):
        print("Client disconnected")
   def process(self,message):
        #it takes 5 sec to complete
Mehrdad Dadvand
  • 340
  • 4
  • 19
  • Possible duplicate of [Python Tornado - Confused how to convert a blocking function into a non-blocking function](https://stackoverflow.com/questions/32148713/python-tornado-confused-how-to-convert-a-blocking-function-into-a-non-blocking) – Fine Jul 03 '18 at 07:53
  • anyway i didn't get my answer – Mehrdad Dadvand Jul 03 '18 at 08:48
  • You asked a similar question a while back. And I answered it, and you accepted that answer. Basically, the solution was to run the blocking code in a separate thread. But it seems that you've deleted your old question now. – xyres Jul 04 '18 at 13:42

1 Answers1

4

I use tornado primarily to host my webapps, therefore I can tell you if any part of your code in tornado is blocking, the whole server will block.

Now to your code:

@tornado.gen.coroutine
def on_message(self, message):
    process_results = yield self.process(message)
    self.write_message(process_results)

@tornado.gen.coroutine
def process(self, message):
    # a long process, this is the equivalent of time.sleep(2) which is blocking
    yield tornado.gen.sleep(2)
    return 'finished'

With tornado you have to yield from a function to get the return value. Also, if your function is yielding, you must wrap it using the tornado.gen.coroutine decorator

This question is similar to yours. And the answer is informative as well.

Therenca
  • 116
  • 6
  • but, what if i want to use a function instead of `tornado.gen.sleep(2)`, for example mysql queries, i just tested a non-async function and it blocked. i just want the application server response to other clients while a client request is processing – Mehrdad Dadvand Jul 05 '18 at 11:47
  • In tornado, you are highly advised to write asynchronous functions, otherwise it will block. For mysql, use [an async driver to peform queries](https://github.com/PyMySQL/Tornado-MySQL), see the link for examples. – Therenca Jul 05 '18 at 15:53