我正在使用Redis以及我的Tornado应用程序与asyc客户端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方法中处理它说长轮询操作(发布 - 订阅模型)。我在更新处理程序的每个post方法中创建新的客户端连接这是正确的方法吗?当我在redis控制台上检查时,我发现每个新的post操作都会增加客户端。
以下是我的代码示例。
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()
如果您提供类似案例的示例代码,我们表示感谢。
答案 0 :(得分:11)
有点晚了,但我一直在使用tornado-redis。它适用于龙卷风的ioloop和tornado.gen
模块
安装tornadoredis
可以从pip
安装pip install tornadoredis
或使用setuptools
easy_install tornadoredis
但你真的不应该这样做。您还可以克隆存储库并将其解压缩。然后运行
python setup.py build
python setup.py install
连接到redis
以下代码包含在main.py或等效内容中
redis_conn = tornadoredis.Client('hostname', 'port')
redis_conn.connect()
redis.connect仅被调用一次。这是一个阻塞调用,所以应该在启动主ioloop之前调用它。所有处理程序之间共享相同的连接对象。
您可以将其添加到
等应用程序设置中settings = {
redis = redis_conn
}
app = tornado.web.Application([('/.*', Handler),],
**settings)
使用tornadoredis
连接可以作为self.settings['redis']
在处理程序中使用,也可以作为BaseHandler类的属性添加。您的请求处理程序将该类子类化并访问该属性。
class BaseHandler(tornado.web.RequestHandler):
@property
def redis():
return self.settings['redis']
要与redis通信,请使用tornado.web.asynchronous
和tornado.gen.engine
装饰器
class SomeHandler(BaseHandler):
@tornado.web.asynchronous
@tornado.gen.engine
def get(self):
foo = yield gen.Task(self.redis.get, 'foo')
self.render('sometemplate.html', {'foo': foo}
额外信息
更多示例和其他功能,如连接池和管道,可以在github repo找到。
答案 1 :(得分:2)
您应该在应用中汇集连接。因为看起来brukva不会自动支持这个(redis-py支持这个,但是它本质上是阻塞的,因此它不适合龙卷风),你需要编写自己的连接池。
但是,这种模式非常简单。沿着这些方向的东西(这不是真正的操作代码):class BrukvaPool():
__conns = {}
def get(host, port,db):
''' Get a client for host, port, db '''
key = "%s:%s:%s" % (host, port, db)
conns = self.__conns.get(key, [])
if conns:
ret = conns.pop()
return ret
else:
## Init brukva client here and connect it
def release(client):
''' release a client at the end of a request '''
key = "%s:%s:%s" % (client.connection.host, client.connection.port, client.connection.db)
self.__conns.setdefault(key, []).append(client)
它可能有点棘手,但这是主要的想法。