我有一个实时的and应用程序,客户端接收来自多个Redis PubSub通道的更新,它是用和redis-py构建的。
我正在查看views.py,l.26中的姜戈-蒂克托德示例。当客户端为一个频道发送订阅消息时,它会产生一个新的“绿色”。然后,绿包订阅Redis PubSub频道并阻塞,直到收到消息为止。
class GameNamespace(BaseNamespace):
def listener(self, chan):
red = redis.StrictRedis(REDIS_HOST)
red = red.pubsub()
red.subscribe(chan)
print 'subscribed on chan ', chan
while True:
for i in red.listen():
self.send({'message': i}, json=True)
def recv_message(self, message):
action, pk = message.split(':')
if action == 'subscribe':
Greenlet.spawn(self.listener, pk)据我理解,如果不生成新的Greenlet或取消订阅,就不可能添加订阅。
如何有效地处理频繁订阅和取消订阅?
更新:我正在构建的是一个理论上无限二维地图上的HTML5实时MMO游戏。由于地图的大小,不可能将整个地图的状态发送到浏览器。地图是在tiles中分区的,在播放器拖放地图时会动态加载这些块(比如Google )。
每当拖动映射时,客户机/浏览器都会订阅刚刚变得可见的瓷砖的更新,并且在短暂的延迟之后,取消对不可见瓷砖上的更新的订阅。订阅的更改应该每秒钟发生一次,所以频率是相对的。
客户的数量(希望)会很大。理论上,所有玩家都可以看到地图的同一部分,使得订阅和取消订阅非常昂贵,因为它们是"O(N) where N is the number of clients already subscribed to a channel“。在实践中,它将均匀地分布在世界各地,所以这不应该是一个问题。
但是,我的主要问题是Python实现阻塞了listen,在上面的示例中调用了red.listen(),在消息到达之前,我不能再更改订阅。上面的示例代码启动了一个新的Greenlet,每个订阅都有一个新的Redis连接,这可能是个坏主意。
发布于 2012-04-19 21:45:47
您没有说明跨订阅的分区原理/需求是什么,也就是说,哪些信息在订阅中必须与其他订阅保持分离,所以很难确定地回答。我会用一些假设..。
如果您有少量或固定数量的客户端管理多个订阅,则最好通过单个长期订阅来复用多个不同的事件,由Redis客户端对最终的事件使用者进行分解。从Redis的角度来看,这种方法可能比重复设置和删除每个用户的订阅更具有表现力。
像这样的方案需要发布者提供一些额外的情报,这样他们就可以为每条消息选择正确的队列,但这有时很容易实现,例如,通过散列客户机ID模N,其中N是pub/子队列的数目。
我希望这和你问的有关.
https://stackoverflow.com/questions/10232824
复制相似问题