在aiohttp应用程序中断开与Redis(aioredis)的连接

时间:2016-09-11 19:40:27

标签: python-3.x redis publish-subscribe aiohttp

我正在text/event-stream中构建基于aiohttp的视图,并在aioredis实现中使用Redis中的pub-sub。它看起来像:

从服务器获取一些数据并发布到chanell

的脚本
def main(host, port):
    server_logger.info('Got params connection host {0}, port {1}'.format(host, port))
    loop = asyncio.get_event_loop()
    title = None
    redis = loop.run_until_complete(create_redis(('localhost', 6379)))
    while True:
        new_title = loop.run_until_complete(get_title(host, port))
        if new_title != title:
            loop.run_until_complete(redis.publish('CHANNEL', new_title))
            title = new_title
    loop.close()
    return False

aiohttp视图,订阅频道并将其写入Stream响应

stream = web.StreamResponse()
stream.headers['Content-Type'] = 'text/event-stream'
stream.headers['Cache-Control'] = 'no-cache'
stream.headers['Connection'] = 'keep-alive'

await stream.prepare(request)

redis = await create_redis(('localhost', 6379))
channel = (await redis.subscribe('CHANNEL'))[0]

while await channel.wait_message():
        message = await channel.get()
        if message:
            stream.write(b'event: track_update\r\n')
            stream.write(b'data: ' + message + b'\r\n\r\n')
        else:
            continue

我有很多次这样的事情:

DEBUG:aioredis:Creating tcp connection to ('localhost', 6379)

因此丢失了sonnection,这也导致concurrent.futures.CancelledError并且保持连接将丢失。 连接经常丢失可以吗?我期待有持久的联系,抱歉,如果我错过了什么。

1 个答案:

答案 0 :(得分:1)

首先在请求处理程序中创建新的redis连接是个坏主意。 请根据应用程序使用连接池。

您可能会将https://github.com/KeepSafe/aiohttp/blob/master/demos/polls/aiohttpdemo_polls/main.py作为推荐设计原则的草图。

关于保持连接 - 它们不是很持久但默认情况下在75秒不活动时间后关闭。

您可以通过将keep_alive=300参数传递到app.make_handler()调用来增加时间段,但设置非常大的值并不健壮 - 在TCP性质连接期间可能会在某些情况下无法通知而中断连接。 如果没有数据要通过,最好保持合理的慢速超时并定期向服务器发送自定义ping请求。