我尝试在Tornado和Redis上构建具有两个API端点的简单系统:
BRPOP
:value = yield from redis.brpop("test")
)LPUSH
:redis.lpush("test", "the value")
)。因此,我希望能够以任何顺序调用这些API。确实,如果我调用2,然后调用1.,它会按预期工作,则调用1.会立即返回该值。
问题是,如果我先拨打1.然后2.,这两个请求都会阻塞,永不返回。
同时,在请求阻塞的同时,我仍然可以直接在Redis中LPUSH
/ BRPOP
,即使是相同的密钥。同样,我可以在Tornado中调用其他处理程序。所以我想这个方块既不在Redis中也不在Tornado中,而是在我使用aioredis时?也许异步循环?但是我不明白我在哪里弄错了。有提示吗?
感谢您的帮助。
这是我的代码:
import tornado.ioloop
import tornado.web
from tornado import web, gen
from tornado.options import options, define
import aioredis
import asyncio
class WaitValueHandler(tornado.web.RequestHandler):
@asyncio.coroutine
def get(self):
redis = self.application.redis
value = yield from redis.brpop("test")
self.write("I received a value: %s" % value)
class WriteValueHandler(tornado.web.RequestHandler):
@asyncio.coroutine
def get(self):
redis = self.application.redis
res = yield from redis.lpush("test", "here is the value")
self.write("Ok ")
class Application(tornado.web.Application):
def __init__(self):
tornado.ioloop.IOLoop.configure('tornado.platform.asyncio.AsyncIOMainLoop')
handlers = [
(r"/get", WaitValueHandler),
(r"/put", WriteValueHandler)
]
super().__init__(handlers, debug=True)
def init_with_loop(self, loop):
self.redis = loop.run_until_complete(
aioredis.create_redis(('localhost', 6379), loop=loop)
)
if __name__ == "__main__":
application = Application()
application.listen(8888)
loop = asyncio.get_event_loop()
application.init_with_loop(loop)
loop.run_forever()
答案 0 :(得分:2)
好吧,我明白了为什么,as the doc states:
在共享模式下的阻塞操作(例如blpop,brpop或长期运行的LUA脚本)将阻塞连接,从而可能导致整个程序故障。
通过将排他连接用于此类操作,可以轻松解决此阻塞问题:
redis = await aioredis.create_redis_pool(
('localhost', 6379),
minsize=1,
maxsize=1)
async def task():
# Exclusive mode
with await redis as r:
await r.set('key', 'val')
asyncio.ensure_future(task())
asyncio.ensure_future(task())
# Both tasks will first acquire connection.