机器宕机引发的复制集心跳异常问题

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS AI 助手,专业版
简介:

问题背景

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导致,参考SERVER-24058.

解决问题

解决这个问题,最直接的方法就是把 node1、node2的 mongod 进程重启,一切就会恢复正常,但作为云服务应该尽量避免这么做,以减少对用户的影响。猜测只要上述连接只要能在 node1上关闭,node1重新建立连接就能恢复正常,于是尝试来干掉这条 tcp连接。

首先尝试了tcpkill,但并不能满足需求,tcpkill 的工作方式类似于 tcpdump,要在满足条件的连接上抓到数据包才会触发 kill 连接的动作,而上述的连接上已经没有任何的数据发送了。

tcpkill 依赖 libpcap、libnet这2个库,抓包的功能由 libpcap 实现,而kill连接(实际上是往连接上发送 reset 包)由 libnet 实现。libnet 自带的 sample 里包含了一个简单的工具,能往指定连接发包。

 # ./libnet/sample/tcp2
libnet 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,但实现上的缺陷并没有达到预期的效果,参考SERVER-24711,遇到类似问题的用户请升级到MongoDB-3.2最新版本。

相关文章
|
前端开发 JavaScript 安全
从前端性能优化角度谈JavaScript代码压缩与混淆
本文从前端性能优化的角度出发,探讨了JavaScript代码压缩与混淆的重要性及实现方式,通过分析不同压缩混淆工具的特点和效果,为开发者提供了实用的指导和建议。
|
Java 应用服务中间件 测试技术
深入探索Spring Boot Web应用源码及实战应用
【5月更文挑战第11天】本文将详细解析Spring Boot Web应用的源码架构,并通过一个实际案例,展示如何构建一个基于Spring Boot的Web应用。本文旨在帮助读者更好地理解Spring Boot的内部工作机制,以及如何利用这些机制优化自己的Web应用开发。
383 3
|
JavaScript API 开发者
GraphQL API开发入门:比RESTful更高效的数据查询方式
**GraphQL API开发入门摘要** GraphQL是一种更高效的数据查询方式,解决RESTful API的过度或不足获取数据问题。它允许客户端按需获取数据,减少网络传输,支持一次请求获取多资源。强类型和自描述特性方便了开发。文章通过一个简单的Node.js示例,展示如何使用`apollo-server-express`搭建GraphQL服务器,包括定义Schema、实现Resolver和创建服务器。通过测试,显示了GraphQL如何提供精确数据和优化查询效率。对于复杂数据需求,GraphQL是现代API设计的有效选择。
349 0
|
JavaScript 前端开发
JavaScript 中 this 的使用方法详解
JavaScript 中 this 的使用方法详解
273 1
|
Web App开发 前端开发 Windows
CSS基础常用属性之字体属性(如果想知道CSS的字体属性知识点,那么只看这一篇就足够了!)
CSS基础常用属性之字体属性(如果想知道CSS的字体属性知识点,那么只看这一篇就足够了!)
|
消息中间件 监控 关系型数据库
实时计算 Flink版产品使用问题之运行后,怎么进行监控和报警
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
NoSQL Java MongoDB
Java一分钟之-Spring Data MongoDB:MongoDB集成
【6月更文挑战第11天】Spring Data MongoDB简化Java应用与MongoDB集成,提供模板和Repository模型。本文介绍其基本用法、常见问题及解决策略。包括时间字段的UTC转换、异常处理和索引创建。通过添加相关依赖、配置MongoDB连接、定义Repository接口及使用示例,帮助开发者高效集成MongoDB到Spring Boot应用。注意避免时间差、异常处理不充分和忽视索引的问题。
477 0
|
域名解析 Cloud Native 应用服务中间件
重磅官宣:Nacos2.0发布,性能提升10倍
​Nacos2.0 作为一个跨代版本,彻底解决了 Nacos1.X 的性能问题,将性能提升了 10 倍。
12287 93
|
存储 关系型数据库 MySQL
MySQL数据库——存储过程-游标(介绍-声明游标、打开游标、获取游标记录、关闭游标,案例)
MySQL数据库——存储过程-游标(介绍-声明游标、打开游标、获取游标记录、关闭游标,案例)
1142 0
|
Windows
本地电脑搭建Web服务器并用cpolar发布至公网访问
本地电脑搭建Web服务器并用cpolar发布至公网访问
581 0
本地电脑搭建Web服务器并用cpolar发布至公网访问