在 Tornado 中处理 Redis 连接的正确方法是什么? (异步 - 发布/订阅)
我将 Redis 与我的 Tornado 应用程序和异步客户端 Brukva 一起使用,当我查看 Brukva 网站上的示例应用程序时,它们正在 websocket 中的“init”方法上建立新连接,
class MessagesCatcher(tornado.websocket.WebSocketHandler):
def __init__(self, *args, **kwargs):
super(MessagesCatcher, self).__init__(*args, **kwargs)
self.client = brukva.Client()
self.client.connect()
self.client.subscribe('test_channel')
def open(self):
self.client.listen(self.on_message)
def on_message(self, result):
self.write_message(str(result.body))
def close(self):
self.client.unsubscribe('test_channel')
self.client.disconnect()
在 websocket 的情况下效果很好但是如何在常见的Tornado RequestHandler post方法中处理它说长轮询操作(发布-订阅模型)。我正在更新处理程序的每个帖子方法中建立新的客户端连接,这是正确的方法吗?当我检查 redis 控制台时,我发现每次新的后期操作中客户端都会增加。
这是我的代码示例。
c = brukva.Client(host = '127.0.0.1')
c.connect()
class MessageNewHandler(BaseHandler):
@tornado.web.authenticated
def post(self):
self.listing_id = self.get_argument("listing_id")
message = {
"id": str(uuid.uuid4()),
"from": str(self.get_secure_cookie("username")),
"body": str(self.get_argument("body")),
}
message["html"] = self.render_string("message.html", message=message)
if self.get_argument("next", None):
self.redirect(self.get_argument("next"))
else:
c.publish(self.listing_id, message)
logging.info("Writing message : " + json.dumps(message))
self.write(json.dumps(message))
class MessageUpdatesHandler(BaseHandler):
@tornado.web.authenticated
@tornado.web.asynchronous
def post(self):
self.listing_id = self.get_argument("listing_id", None)
self.client = brukva.Client()
self.client.connect()
self.client.subscribe(self.listing_id)
self.client.listen(self.on_new_messages)
def on_new_messages(self, messages):
# Closed client connection
if self.request.connection.stream.closed():
return
logging.info("Getting update : " + json.dumps(messages.body))
self.finish(json.dumps(messages.body))
self.client.unsubscribe(self.listing_id)
def on_connection_close(self):
# unsubscribe user from channel
self.client.unsubscribe(self.listing_id)
self.client.disconnect()
如果您提供一些类似案例的示例代码,我将不胜感激。
I am using Redis along with my Tornado application with asyc client Brukva, when I looked at the sample apps at Brukva site they are making new connection on "init" method in websocket
class MessagesCatcher(tornado.websocket.WebSocketHandler):
def __init__(self, *args, **kwargs):
super(MessagesCatcher, self).__init__(*args, **kwargs)
self.client = brukva.Client()
self.client.connect()
self.client.subscribe('test_channel')
def open(self):
self.client.listen(self.on_message)
def on_message(self, result):
self.write_message(str(result.body))
def close(self):
self.client.unsubscribe('test_channel')
self.client.disconnect()
its fine in the case of websocket but how to handle it in the common Tornado RequestHandler post method say long polling operation (publish-subscribe model). I am making new client connetion in every post method of update handler is this the right approach ?? When I checked at the redis console I see that clients increasing in every new post operation.
Here is a sample of my code.
c = brukva.Client(host = '127.0.0.1')
c.connect()
class MessageNewHandler(BaseHandler):
@tornado.web.authenticated
def post(self):
self.listing_id = self.get_argument("listing_id")
message = {
"id": str(uuid.uuid4()),
"from": str(self.get_secure_cookie("username")),
"body": str(self.get_argument("body")),
}
message["html"] = self.render_string("message.html", message=message)
if self.get_argument("next", None):
self.redirect(self.get_argument("next"))
else:
c.publish(self.listing_id, message)
logging.info("Writing message : " + json.dumps(message))
self.write(json.dumps(message))
class MessageUpdatesHandler(BaseHandler):
@tornado.web.authenticated
@tornado.web.asynchronous
def post(self):
self.listing_id = self.get_argument("listing_id", None)
self.client = brukva.Client()
self.client.connect()
self.client.subscribe(self.listing_id)
self.client.listen(self.on_new_messages)
def on_new_messages(self, messages):
# Closed client connection
if self.request.connection.stream.closed():
return
logging.info("Getting update : " + json.dumps(messages.body))
self.finish(json.dumps(messages.body))
self.client.unsubscribe(self.listing_id)
def on_connection_close(self):
# unsubscribe user from channel
self.client.unsubscribe(self.listing_id)
self.client.disconnect()
I appreciate if you provide some sample code for similar case.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
有点晚了,但是,我一直在使用 tornado-redis。它与tornado的ioloop和
tornado.gen
模块一起使用安装tornadoredis
它可以通过pip
或setuptools
安装,但你真的不应该这样做。您还可以克隆存储库并提取它。然后运行
连接到redis
以下代码放入您的main.py或等效的
redis.connect中仅被调用一次。这是一个阻塞调用,因此应该在启动主 ioloop 之前调用它。所有处理程序之间共享相同的连接对象。
您可以将其添加到您的应用程序设置中,例如
使用tornadoredis。
连接可以在处理程序中用作
self.settings['redis']
,也可以作为属性添加BaseHandler 类。您的请求处理程序是该类的子类并访问该属性。为了与 Redis 通信,使用了
tornado.web.asynchronous
和tornado.gen.engine
装饰器额外信息
更多示例和其他功能,例如连接池和管道可以在 github 存储库中找到。
A little late but, I've been using tornado-redis. It works with tornado's ioloop and the
tornado.gen
moduleInstall tornadoredis
It can be installed from pip
or with setuptools
but you really shouldn't do that. You could also clone the repository and extract it. Then run
Connect to redis
The following code goes in your main.py or equivalent
redis.connect is called only once. It is a blocking call, so it should be called before starting the main ioloop. The same connection object is shared between all the handlers.
You could add it to your application settings like
Use tornadoredis
The connection can be used in handlers as
self.settings['redis']
or it can be added as a property of the BaseHandler class. Your request handlers subclass that class and access the property.To communicate with redis, the
tornado.web.asynchronous
and thetornado.gen.engine
decorators are usedExtra information
More examples and other features like connection pooling and pipelines can be found at the github repo.
您应该在应用程序中汇集连接。因为 brukva 似乎不自动支持这一点(redis-py 支持这一点,但本质上是阻塞的,所以它与龙卷风不兼容),所以您需要编写自己的连接池。
不过,模式非常简单。沿着这些思路(这不是真正的操作代码):
它可能有点棘手,但这就是主要思想。
you should pool the connections in your app. since it seems like brukva doesn't support this automatically (redis-py supports this, but is blocking by nature so it doesn't go well with tornado), you need to write your own connection pool.
the pattern is pretty simple, though. something along these lines (this is not real operational code):
it can be a bit more tricky, but that's the main idea.