美文网首页
kafka客户端间歇性丢失redis连接问题调查

kafka客户端间歇性丢失redis连接问题调查

作者: 哈密朵 | 来源:发表于2019-07-06 22:27 被阅读0次

【发现问题】
2019年3月20日某个项目组报告称A机房的应用日志,每隔一段时间报出一次丢失Sentinel连接的异常。

[00:38:55.256] {Thread-11}Lost connection to Sentinel at xx.xx.xx.40:26379. Sleeping 5000ms and retrying.
[00:38:55.256] {Thread-12}Lost connection to Sentinel at xx.xx.xx.39:26379. Sleeping 5000ms and retrying.
[00:38:55.256] {Thread-10}Lost connection to Sentinel at xx.xx.xx.41:26379. Sleeping 5000ms and retrying.
。。。。。。
[02:50:32.344] {Thread-11}Lost connection to Sentinel at xx.xx.xx.40:26379. Sleeping 5000ms and retrying.
[02:50:32.344] {Thread-10}Lost connection to Sentinel at xx.xx.xx.41:26379. Sleeping 5000ms and retrying.
[02:50:32.345] {Thread-12}Lost connection to Sentinel at xx.xx.xx.39:26379. Sleeping 5000ms and retrying.
。。。。。。
[05:02:09.432] {Thread-12}Lost connection to Sentinel at xx.xx.xx.39:26379. Sleeping 5000ms and retrying.
[05:02:09.432] {Thread-11}Lost connection to Sentinel at xx.xx.xx.40:26379. Sleeping 5000ms and retrying.
[05:02:09.432] {Thread-10}Lost connection to Sentinel at xx.xx.xx.41:26379. Sleeping 5000ms and retrying.
。。。。。。

【分析问题】
Sentinel是redis的监察节点,三个IP地址正是A机房redis的一套Sentinel地址。该项目组刚接入kafka并启用了自研的托管offset到redis的功能,所以会出现跟redis的连接。
查询该异常可知客户端跟Sentinel的连接属于长连接,结合两次异常之间的间隔都是2小时11分27秒,联想到linux的默认keepalive为7500即2小时,猜测长连接已被意外断开,在每2小时的keepalive时检查到连接不可达所以抛出异常。
登录A机房Sentinel所在机器,查询26379端口的连接情况如下,共有980个客户端连接,且都处于ESTABLISHED状态,而且客户端几乎都落在xx.xx.xx.149,xx.xx.xx.150,xx.xx.xx.153上。

netstat -anp | grep 26379
tcp        0      0 xx.xx.xx.39:26379          xx.xx.xx.153:47914         ESTABLISHED 9752/./src/redis-se
tcp        0      0 xx.xx.xx.39:26379          xx.xx.xx.150:55064         ESTABLISHED 9752/./src/redis-se
tcp        0      0 xx.xx.xx.39:26379          xx.xx.xx.153:59528         ESTABLISHED 9752/./src/redis-se
tcp        0      0 xx.xx.xx.39:26379          xx.xx.xx.150:48246         ESTABLISHED 9752/./src/redis-se
tcp        0      0 xx.xx.xx.39:26379          xx.xx.xx.150:43686         ESTABLISHED 9752/./src/redis-se
tcp        0      0 xx.xx.xx.39:26379          xx.xx.xx.150:55588         ESTABLISHED 9752/./src/redis-se
tcp        0      0 xx.xx.xx.39:26379          xx.xx.xx.153:58350         ESTABLISHED 9752/./src/redis-se
tcp        0      0 xx.xx.xx.39:26379          xx.xx.xx.150:59076         ESTABLISHED 9752/./src/redis-se 
。。。。。。

登录客户端所在机器xx.xx.xx.149,查询26379端口的连接情况如下,只有3个Sentinel的一套连接。

netstat -anp | grep 26379
tcp        0      0 xx.xx.xx.149:53610     xx.xx.xx.39:26379      ESTABLISHED 28548/java          
tcp        0      0 xx.xx.xx.149:42184     xx.xx.xx.40:26379      ESTABLISHED 28548/java          
tcp        0      0 xx.xx.xx.149:53520     xx.xx.xx.41:26379      ESTABLISHED 28548/java  

经运维查询证实客户端机器xx.xx.xx.149的keepalive为7500, probes为9, intvl为75,即在 7500 + 75 * 9 = 2小时11分15秒时能探知连接不可达并多次尝试后决定连接失效然后清理,这和日志表达出来的连接失效的间隔时间几乎一致。

【初步结论】
所以可以断定长连接被意外断开后,客户端已通过keepalive清理掉失效长连接,并重建新的一轮长连接。但服务端无感知,保持失效长连接处于ESTABLISHED状态。

接下来要查找长连接被意外断开的原因,登录另一个机房B的Sentinel所在机器查询26379端口的连接情况,总共只有130个客户端连接,说明A机房的redis长连接断开是个例。这里的reids处于xx.xx.19网段,客户端处于xx.xx.32网段,所以我们猜测redis长连接被断开同样是因为A机房子网间的网关防火墙造成。
经运维查询证实,xx.xx.19网段和xx.xx.32网段之间的防火墙,设置有限定超时时间1小时,任何连接在1小时内没有任意的数据报文通过,即会被防火墙断开。客户端该业务使用频次较低,很可能几个小时没有请求,而客户端的keepalive使用的是默认值2小时,超过了防火墙设置的1小时。
所以每1小时防火墙发现没有报文通过就断开连接,客户端和服务端此时都无感知。每2小时客户端的keepalive发送心跳包时,探知到连接不可用所以就抛出异常。

【思考】
1)为什么能够确定客户端发现连接不可用抛出异常后,重建了新的一轮连接?
通过源码得知,catch异常打印丢失连接的日志后,方法并没有退出,而是在while循环里重头再来,新建Jedis发起长连接订阅“switch-master”事件。
从现象上来看,客户端间隔性的打印丢失连接的日志后,登录客户端所在机器xx.xx.xx.149,查询26379端口,依然能看到一整套Sentinel的连接,也能轻易的判断出这一点。


图片.png

2)为什么服务端redis没有清理无效的长连接?

# A reasonable value for this option is 60 seconds.
tcp-keepalive 0

因为redis默认没有开启keepalive,所以防火墙断开连接后,客户端通过keepalive检测清理失效连接并进行重建,服务端没有做出任何措施所以会造成连接堆积。

【解决问题】
有三种思路可以解决这个问题:
1)调整防火墙策略,上调或者放过部分端口的超时设置。但这会增加运维对全机房的维护负担。
2)调整客户端的keepalive间隔,但这需要每一台机器都要配一次,如果新机器有遗漏,问题还会重现。
3)调整服务端,打开keepalive并设置一个合理值,这样可以不用在意客户端的keepalive配置。因为对防火墙来说,业务数据包,客户端发起的来回的keepalive包,服务端发起的来回的keepalive包,都是有效的。

最终选择的是3)设置redis的tcp-keepalive=600(10分钟)。

相关文章

  • kafka客户端间歇性丢失redis连接问题调查

    【发现问题】2019年3月20日某个项目组报告称A机房的应用日志,每隔一段时间报出一次丢失Sentinel连接的异...

  • hyperf遇到的坑redis连接报错

    redis连接方式 redis 代理连接池 实际是继承了redis客户端代理封装成连接池 多个连接的redis

  • kafka 2.2.0 那些事

    问题 1 本地客户端连接虚拟机cenos中的kafka服务,出现拒绝连接 https://blog.csdn.ne...

  • Kafka相关问题

    Kafka远程连接问题 本地Kafka客户端启动正常,可以正常生产消费信息。但是把jar包放在同事电脑上,则出现报...

  • Linux上安装Redis(Ubuntu16.04+Redis3

    参考地址 关闭redis-cli shutdown启动redis-server客户端连接redis-cli测试连接...

  • Redis基本使用

    客户端连接 无密码 : redis-cli 有密码 : redis-cli -a 密码 php连接redis $r...

  • Redis 连接

    Redis 连接 Redis 连接命令主要是用于连接 redis 服务。 实例 以下实例演示了客户端如何通过密码验...

  • Redis 连接

    Redis 连接命令主要是用于连接 redis 服务。实例以下实例演示了客户端如何通过密码验证连接到 redis ...

  • Kafka学习——生产者和消费者客户端

    kafka客户端 Kafka除了提供内置Java客户端外,还提供了二进制连接协议,即向Kafka网络端口发送适当的...

  • redis启动与配置篇篇

    环境:docker+redis 权限控制 Redis-cli连接 windows客户端免费连接工具:https:/...

网友评论

      本文标题:kafka客户端间歇性丢失redis连接问题调查

      本文链接:https://www.haomeiwen.com/subject/xbnmhctx.html