python - Tornado websocket + Redis

标签 python websocket redis tornado

我想创建通知系统。当服务器将数据保存到数据库(仅限通知模型)时,它应该通过 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()

关于python - Tornado websocket + Redis,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31222718/

相关文章:

python - 反转给定索引之间的数组

python - 有没有人有 gevent-socketio 的工作示例?

events - 移动和桌面设备的实时消息服务

c# - 从 Redis 连接丢失中恢复

Redis 快速填满内存,运行 --bigkeys 释放内存

redis - 从 redis 排序集中,检索分数小于给定分数的最高值的排名

python - 如何诊断 Python 程序中潜在的内存泄漏?

python - 通过 Pandas Data-Reader 获取 Quandl 数据

python - 在 PyMAPDL 中围绕另一个关键点创建关键点

python - 如何单元测试 Flask websocket 服务器 (Flask-SocketIO)