python redis subscribe tcp keepalive(redis订阅保活)
如果你不知道要到哪儿去,那通常你哪儿也去不了。
这三天,一直在弄一件事情,就是redis订阅时,怎么在订阅的连接上,给server端发保活报文。
1. 问题
redis subscribe有时候会有死链,但server端该连接已经不存在。
2. 复现方法
在redis订阅成功后,client上添加iptables规则,把与server端通信报文丢弃。
240s后,(因为server端的tcp-keepalive 设置的是120s),server端因为保活无回应,关闭了该连接。
而client端一直保持一个established的连接,且一直保持,永不断开。
3. 解决方法
把py-redis版本升级到2.10.3后,该版本拥有socket-keepalive参数,能够在订阅后对该通道保活。
配置参数如下:
1
2
3
4
5
6
7 r=redis.StrictRedis(host=self.srvip,port=self.port,password=self.passwd,socket_connect_timeout=15,socket_keepalive=True,socket_keepalive_options={
socket.TCP_KEEPIDLE:120,
socket.TCP_KEEPCNT:2,
socket.TCP_KEEPINTVL:30
})
rl=r.pubsub()
rl.subscribe(self.subch)关键参数:
socket_keepalive,socket_keepalive_options
**socket_keepalive**为True时代表开启TCP保活功能。
**socket_keepalive_options**值是字典格式,有如下三个参数:
socket.TCP_KEEPIDLE: 空闲多少秒后开始检测socket.TCP_KEEPCNT: 检测的包数量socket.TCP_KEEPINTVL: 检测包发送间隔
4. Redis变更日志
参考地址:
https://github.com/andymccurdy/redis-py/blob/master/CHANGES
该功能添加在2.10.0版本中:
- 2.10.0
- Added TCP Keep-alive support by passing use the socket_keepalive=True
option. Finer grain control can be achieved using the
socket_keepalive_options option which expects a dictionary with any of
the keys (socket.TCP_KEEPIDLE, socket.TCP_KEEPCNT, socket.TCP_KEEPINTVL)
and integers for values. Thanks Yossi Gottlieb.