MongoDB云数据库机器宕机引发的复制集心跳异常问题
Posted 阿里云云栖号
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MongoDB云数据库机器宕机引发的复制集心跳异常问题相关的知识,希望对你有一定的参考价值。
问题背景
”是由3个节点组成的复制集,node3原来是 Primary 节点,因为硬件故障宕机,云数据库高可用模块检测到后,立即进行了主备切换,保证服务正常,node3重启之后重新加入复制集,变为 Hidden 节点,最终的状态如下表所示:
Primary | Secondary | Hidden |
---|---|---|
node1:port1 | node2:port2 | node3:port3 |
一、宕机引发的问题
node3重新加入后,服务正常,但复制集内部的通信却还有问题。
从node3的 rs.status()看整个复制集,一切正常,说明 node3到 node1、node2发送心跳请求都正常(每个节点周期性向其他节点发送心跳,通过心跳应答来更新其他节点的状态信息)。
当从 node1、node2的 rs.status()看,node3却处于宕机状态,错误如下:
{ "_id" : 3, "name" : "node3:port3", "health" : 0, "state" : 8, "stateStr" : "(not reachable/healthy)", "uptime" : 0, "optime" : Timestamp(0, 0), "optimeDate" : ISODate("1970-01-01T00:00:00Z"), "lastHeartbeat" : ISODate("2016-07-21T12:30:17.807Z"), "lastHeartbeatRecv" : ISODate("2016-07-21T12:30:17.544Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "Couldn't get a connection within the time limit", "configVersion" : -1 }
也就是说 node1向 node3发送心跳信息是一直失败的,失败的原因是Couldn't get a connection within the time limit node1上执行 netstat,发现 node1已经建立了到 node3的连接 (注意这条连接 tcp keepalive timer 是关闭的):
tcp 0 0 node1:58347 node3:port3 ESTABLISHED off (0.00/0/0)
然而从 node3上执行 netstat,这个连接并不存在。
也就是说,这个连接是 node3宕机之前建立的连接,因为 tcp keepalive 没有打开,加上 node3异常退出,所以这条连接只是一边断开了,node1一端还一直保留着这条连接。
此时只要 node1往 node3通过这个连接发送心跳数据,就会发现对端已经关闭,但实际上没有发送任何数据,在从连接池获取连接的时候就已经出错了(Couldn't get a connection within the time limit),所以心跳并没有发出,事后确定是 MongoDB 的 bug导致,参考。
解决问题
二、解决问题
解决这个问题,最直接的方法就是把 node1、node2的 mongod 进程重启,一切就会恢复正常,但作为云服务应该尽量避免这么做,以减少对用户的影响。猜测只要上述连接只要能在 node1上关闭,node1重新建立连接就能恢复正常,于是尝试来干掉这条 tcp连接。
首先尝试了,但并不能满足需求,tcpkill 的工作方式类似于 tcpdump,要在满足条件的连接上抓到数据包才会触发 kill 连接的动作,而上述的连接上已经没有任何的数据发送了。
tcpkill 依赖 libpcap、这2个库,抓包的功能由 libpcap 实现,而kill连接(实际上是往连接上发送 reset 包)由 libnet 实现。libnet 自带的 sample 里包含了一个简单的工具,能往指定连接发包。
# ./libnet/sample/tcp2libnet 1.1 packet shaping: TCP[raw] usage: /tmp/libnet/sample/.libs/lt-tcp2 -s source_ip.source_port -d destination_ip.destination_port [-p payload]
利用这个小工具,向上述连接随便发送了一些数据,连接立即被关闭了,node1向 node3新建立了一条连接来发送心跳,一切恢复正常。
三、为什么关闭tcp keepalive
设计上是应用层会做 keepalive,但实现上的缺陷并没有达到预期的效果,遇到类似问题的用户请升级到MongoDB-3.2最新版本。
点击“阅读原文”可查看原文。
想和这群聪明人共事吗?加入阿里云云栖社区翻译志愿者:yqeditor@list.alibaba-inc.com
投稿或入驻云栖社区,请联系:yqeditor@list.alibaba-inc.com
2016,为了实现更多技术梦想,云栖社区与你携手并行。
长按二维码,一网打尽所有深度技术文章
戳原文,更有料!
以上是关于MongoDB云数据库机器宕机引发的复制集心跳异常问题的主要内容,如果未能解决你的问题,请参考以下文章