简体   繁体   中英

Tornado WebSockets non-blocking requests using threading. Am I doing it right?

I am new to Python and the problem I'm trying to solve is to have an on-going websocket connection that can take in requests, wait some time while doing calcs, return results when ready while not blocking other requests that come from other users/clients/connections. I have achieved this and it works rather nicely but wanted to check if this is the right solution. In this particular snippet they key bit is actions performed upon open: I spin off another thread with sleep.

import tornado.web
import tornado.websocket
import tornado.httpserver
import tornado.ioloop
import time
import json
from tornado import gen
from concurrent.futures import ThreadPoolExecutor
from tornado.options import define, options, parse_command_line

define("port", default=8888, type=int)

thread_pool = ThreadPoolExecutor(2)

class WebSocketHandler(tornado.websocket.WebSocketHandler):
    # Make this an asynchronous coroutine
    @gen.coroutine
    def on_message_coroutine(self, message):
        self.write_message('Message:', message)

        def worker_A(websocket, x):
            time.sleep(1)
            print('TICK', x)
            pass
            return x

        print('scheduling and yielding')
        for x in range(0, 30):
            test = yield thread_pool.submit(worker_A, self, x)
            self.write_message(json.dumps(test))

        print('done yielding')

    def open(self, *args):
        print("New connection")
        tornado.ioloop.IOLoop.current().spawn_callback(self.on_message_coroutine, 'New Msg')

    def check_origin(self, origin):
        return True

    def on_message(self, message):
        print("New message {}".format(message))
        self.write_message("You sent me this, sending it back in upper: " + message.upper())

    def on_close(self):
            print("Connection closed")

app = tornado.web.Application([
    (r'/ws/', WebSocketHandler),
])

if __name__ == '__main__':
    app.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

Output on front-end's console below. "New message" bit is when I click the buttons while websocket is continuously returning other output (TICKS):

app.component.ts:17 Response from websocket: 11
app.component.ts:17 Response from websocket: 12
app.component.ts:17 Response from websocket: 13
app.component.ts:17 Response from websocket: 14
app.component.ts:24 new message from client to websocket:  gotta be a string
app.component.ts:17 Response from websocket: You sent me this, sending it back in upper: "GOTTA BE A STRING"
app.component.ts:17 Response from websocket: 15
app.component.ts:17 Response from websocket: 16
app.component.ts:17 Response from websocket: 17
app.component.ts:24 new message from client to websocket:  gotta be a string
app.component.ts:17 Response from websocket: You sent me this, sending it back in upper: "GOTTA BE A STRING"
app.component.ts:17 Response from websocket: 18
app.component.ts:17 Response from websocket: 19
app.component.ts:17 Response from websocket: 20
app.component.ts:17 Response from websocket: 21

Yes, this looks fine to me. The key thing to remember is that in worker_A (the function you pass to executor.submit() , you must not call write_message . Instead, return a value and write it after yield executor.submit() has returned.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM