龙卷风 websocket + Redis
Tornado websocket + Redis
我想创建通知系统。当服务器将数据保存到数据库(仅限通知模型)时,它应该由 Tornado websocket 发送到客户端(浏览器)
到目前为止我配置了websocket,但我不知道如何向客户端发送数据。
class WebSocketHandler(tornado.websocket.WebSocketHandler):
def __init__(self, *args, **kwargs):
self.id = None
self.client = None
super(WebSocketHandler, self).__init__(*args, **kwargs)
def open(self, *args):
self.id = self.get_argument("Id")
self.stream.set_nodelay(True)
clients[self.id] = {"id": self.id, "object": self}
def on_message(self, message):
message = json.loads(message)
print("Client %s received a message : %s" % (self.id, message))
self.write_message("message: " + str(message['body']))
def on_close(self):
print('closed?')
if self.id in clients:
del clients[self.id]
def check_origin(self, origin):
return True
def _connect_to_redis(self):
logging.info('connect to redis...')
self._redis_client = tornadoredis.Client(host='localhost', port=6379)
self._redis_client.connect()
app = tornado.web.Application([
(r'/socket', WebSocketHandler),
])
parse_command_line()
app.listen(8888)
tornado.ioloop.IOLoop.instance().start()
我想我需要将 Redis 插入其中。有人可以帮我吗?
如果有人需要我是这样做的:
import tornado.ioloop
import tornado.web
import tornado.websocket
from tornado.options import parse_command_line
from tornado import gen
import logging
import tornadoredis
import json
from urllib.parse import urlparse
from django.core.management.base import NoArgsCommand
from django.conf import settings
logging = logging.getLogger('base.tornado')
# store clients in dictionary..
clients = dict()
# REDIS_URL = 'redis://localhost:6379/'
# REDIS_UPDATES_CHANNEL = 'django_bus'
class WebSocketHandler(tornado.websocket.WebSocketHandler):
def __init__(self, *args, **kwargs):
self.client_id = None
self._redis_client = None
super(WebSocketHandler, self).__init__(*args, **kwargs)
self._connect_to_redis()
self._listen()
def open(self, *args):
self.client_id = self.get_argument("Id")
self.stream.set_nodelay(True)
clients[self.client_id] = self
def on_message(self, message):
"""
:param message (str, not-parsed JSON): data from client (web browser)
"""
print("on message")
@gen.coroutine
def _on_update(self, message):
"""
Receive Message from Redis when data become published and send it to selected client.
:param message (Redis Message): data from redis
"""
body = json.loads(message.body)
if self.client_id == body['client_id']:
self.write_message(message.body)
@tornado.gen.engine
def _listen(self):
"""
Listening chanel 'REDIS_UPDATES_CHANNEL'
"""
yield tornado.gen.Task(self._redis_client.subscribe, settings.REDIS_UPDATES_CHANNEL)
self._redis_client.listen(self._on_update)
def on_close(self):
"""
When client will disconnect (close web browser) then shut down connection for selected client
"""
if self.client_id in clients:
del clients[self.client_id]
self._redis_client.unsubscribe(settings.REDIS_UPDATES_CHANNEL)
self._redis_client.disconnect()
def check_origin(self, origin):
"""
Check if incoming connection is in supported domain
:param origin (str): Origin/Domain of connection
"""
return True
def _connect_to_redis(self):
"""
Extracts connection parameters from settings variable 'REDIS_URL' and
connects stored client to Redis server.
"""
redis_url = settings.REDIS_URL
parsed = urlparse(redis_url)
self._redis_client = tornadoredis.Client(host=parsed.hostname, port=parsed.port)
self._redis_client.connect()
app = tornado.web.Application([
(r'/socket', WebSocketHandler),
])
class Command(NoArgsCommand):
def handle_noargs(self, **kwargs):
logging.info('Started Tornado')
parse_command_line()
app.listen(8888)
tornado.ioloop.IOLoop.instance().start()
我想创建通知系统。当服务器将数据保存到数据库(仅限通知模型)时,它应该由 Tornado websocket 发送到客户端(浏览器)
到目前为止我配置了websocket,但我不知道如何向客户端发送数据。
class WebSocketHandler(tornado.websocket.WebSocketHandler):
def __init__(self, *args, **kwargs):
self.id = None
self.client = None
super(WebSocketHandler, self).__init__(*args, **kwargs)
def open(self, *args):
self.id = self.get_argument("Id")
self.stream.set_nodelay(True)
clients[self.id] = {"id": self.id, "object": self}
def on_message(self, message):
message = json.loads(message)
print("Client %s received a message : %s" % (self.id, message))
self.write_message("message: " + str(message['body']))
def on_close(self):
print('closed?')
if self.id in clients:
del clients[self.id]
def check_origin(self, origin):
return True
def _connect_to_redis(self):
logging.info('connect to redis...')
self._redis_client = tornadoredis.Client(host='localhost', port=6379)
self._redis_client.connect()
app = tornado.web.Application([
(r'/socket', WebSocketHandler),
])
parse_command_line()
app.listen(8888)
tornado.ioloop.IOLoop.instance().start()
我想我需要将 Redis 插入其中。有人可以帮我吗?
如果有人需要我是这样做的:
import tornado.ioloop
import tornado.web
import tornado.websocket
from tornado.options import parse_command_line
from tornado import gen
import logging
import tornadoredis
import json
from urllib.parse import urlparse
from django.core.management.base import NoArgsCommand
from django.conf import settings
logging = logging.getLogger('base.tornado')
# store clients in dictionary..
clients = dict()
# REDIS_URL = 'redis://localhost:6379/'
# REDIS_UPDATES_CHANNEL = 'django_bus'
class WebSocketHandler(tornado.websocket.WebSocketHandler):
def __init__(self, *args, **kwargs):
self.client_id = None
self._redis_client = None
super(WebSocketHandler, self).__init__(*args, **kwargs)
self._connect_to_redis()
self._listen()
def open(self, *args):
self.client_id = self.get_argument("Id")
self.stream.set_nodelay(True)
clients[self.client_id] = self
def on_message(self, message):
"""
:param message (str, not-parsed JSON): data from client (web browser)
"""
print("on message")
@gen.coroutine
def _on_update(self, message):
"""
Receive Message from Redis when data become published and send it to selected client.
:param message (Redis Message): data from redis
"""
body = json.loads(message.body)
if self.client_id == body['client_id']:
self.write_message(message.body)
@tornado.gen.engine
def _listen(self):
"""
Listening chanel 'REDIS_UPDATES_CHANNEL'
"""
yield tornado.gen.Task(self._redis_client.subscribe, settings.REDIS_UPDATES_CHANNEL)
self._redis_client.listen(self._on_update)
def on_close(self):
"""
When client will disconnect (close web browser) then shut down connection for selected client
"""
if self.client_id in clients:
del clients[self.client_id]
self._redis_client.unsubscribe(settings.REDIS_UPDATES_CHANNEL)
self._redis_client.disconnect()
def check_origin(self, origin):
"""
Check if incoming connection is in supported domain
:param origin (str): Origin/Domain of connection
"""
return True
def _connect_to_redis(self):
"""
Extracts connection parameters from settings variable 'REDIS_URL' and
connects stored client to Redis server.
"""
redis_url = settings.REDIS_URL
parsed = urlparse(redis_url)
self._redis_client = tornadoredis.Client(host=parsed.hostname, port=parsed.port)
self._redis_client.connect()
app = tornado.web.Application([
(r'/socket', WebSocketHandler),
])
class Command(NoArgsCommand):
def handle_noargs(self, **kwargs):
logging.info('Started Tornado')
parse_command_line()
app.listen(8888)
tornado.ioloop.IOLoop.instance().start()