日常Bug排查-消息不消费

前言

日常Bug排查系列都是一些简单Bug排查,笔者将在这里介绍一些排查Bug的简单技巧,同时顺便积累素材_

Bug现场

某天下午,在笔者研究某个问题正high的时候。开发突然找到笔者,线上某个系统突然消费不了queue了。Queue不消费也算是日常问题了。淡定的先把流量切到另一个机房,让问题先恢复再说。

消息累积

然后就是看不消费的queue到哪去了,打开mq(消息中间件)控制台,全部累积到mq上了。



同时开发对笔者反映,只有这个queueu积累了,其它queue还是能正常消费的。

出问题时间点

这时笔者还得到了一个关键信息,此问题是DBA对其关联的数据库进行操作后才发生的。当时由于操作灌入的数据库过大,导致数据库主从切换,漂了VIP。从时间点判断,这个应该是问题的诱因。

jstack

既然卡住了,那么老办法,jstack一下,看看我们的mq消费线程在干嘛:

ActiveMQ Session Task-1234
at java.net.SocketInputStream.socketRead0
......
at com.mysql.jdbc.MysqlIO.readFully
......
at org.apache.activemq.ActiveMQMessageConsumer.dispatch
......

很明显的,都卡在MysqlIO.readFully也就是数据库读取上,再也不往下走了。

没配超时

这就肯定是没配超时了,排查了下他们的配置,确实没配。之前系统梳理过好多次,但没想到还是有这种漏网之鱼。这个问题分析本身是很简单的。不过在这里笔者想多聊一下,为什么数据主从切换会形成这样的现象。

mha切换



如图所示,mha切换逻辑是将vip从DB旧主上摘掉,然后将vip挂到DB新主上面。为了观察这种行为,笔者写了个python程序进行测试。观察得知,在vip被摘掉的那一刻,双方的通信已经不正常了。但是tcp连接状态依旧是ESTABLISHED。

为什么tcp状态依旧ESTABLISHED

因为ip摘掉并不会让已经存在的socket立马感知,那么socket什么时候能够感知到我们这个连接已经gg了呢。在当前这个场景下,应用没设置socket超时,会有这几种可能:

  1. 如果这时候App正在发请求给此五元组

  1. 如果DB正在写回请求给此五元组

由上面两种情况,我们可以知道哪方作出发送动作,哪方就能够通过reset或者尝试次数过多来感知到这个连接已经gg了。

很明显的,由于我们的应用正卡在socket read,表明我们的App应用并没有发送数据,而是在等待MySQL的返回,那么在不设置超时的情况下,App怎么感知到连接实际上已经不好了呢。

tcp保活定时器

由于应用不做发送动作,那这时就轮到我们的tcp保活定时器tcp_keepalive出马了。linux下默认的内核参数为:

/proc/sys/net/ipv4/tcp_keepalive_time 7200 两小时
/proc/sys/net/ipv4/tcp_keepalive_probes 9 探测9次
/proc/sys/net/ipv4/tcp_keepalive_intvl 75s 每次探测间隔75s

tcp保活定时器默认在7200s也就是两小时后开启,探测9次,每次间隔75s,如果有明确失败或者9次都没返回则判定连接gg。



在我们的这个场景中,应用会在两个小时后开始保活,在第一次探测的时候对端发送reset从而应用感知到连接gg。这时候,应用才返回。也就是说,不设置超时时间,遇到这种情况,应用的线程要卡2小时!

如果是DB进程宕or重启

如果不是mha切换,而是DB进程重启或者宕的话,由于Linux内核没宕还存在着。内核会自动将DB进程所属的socket进行close也就是发FIN报文回去。那么应用就可以立马从socket read系统调用中返回了。

物理机宕机

物理机宕机而不漂VIP,应用在不设置超时的时候。如果是发送数据阶段,则tcp_reties2次重试后从socket read系统调用返回。如果不发送数据,和上面的描述基本一样,2个小时后开启保活定时器。唯一不同的是,这次是需要探活9次,所以需要会多花11分钟左右的时间感知。

线下演练为什么不出问题

VIP漂移这种操作,我们在线下演练过,当时应用很快就切换完了。为什么到了线上就会卡住呢?这是因为,线下没有加上IO hang住导致SQL处理时间过长这一条件。SQL很快就返回了,所以我们线下的线程只有很小的概率卡在socket read上面。况且有几十个线程在消费,卡一两个无关大局。

而在我们这次上面,由于SQL处理时间超长,所以基本所有的线程都在VIP漂移的那一刻执行socket read即等待数据库返回阶段,就导致所有线程全部hang住等。这时候只能等待tcp_keepalive或者重启了。

总结

要保证高可用,任何远程调用都需要设置超时。否则就会导致应用长时间无法响应这样的现象。

日常Bug排查-消息不消费的更多相关文章

  1. 日常Bug排查-系统失去响应-Redis使用不当

    日常Bug排查-系统失去响应-Redis使用不当 前言 日常Bug排查系列都是一些简单Bug排查,笔者将在这里介绍一些排查Bug的简单技巧,同时顺便积累素材_. Bug现场 开发反应线上系统出现失去响 ...

  2. 日常Bug排查-抛异常不回滚

    日常Bug排查-抛异常不回滚 前言 日常Bug排查系列都是一些简单Bug排查,笔者将在这里介绍一些排查Bug的简单技巧,同时顺便积累素材_. Bug现场 最近有人反映java应用操作数据库的时候,抛异 ...

  3. 日常Bug排查-Nginx重复请求?

    日常Bug排查-Nginx重复请求? 前言 日常Bug排查系列都是一些简单Bug排查,笔者将在这里介绍一些排查Bug的简单技巧,其中不乏一些看起来很低级但很容易犯的问题. 问题现场 有一天运维突然找到 ...

  4. Spring Cloud Stream如何处理消息重复消费?

    最近收到好几个类似的问题:使用Spring Cloud Stream操作RabbitMQ或Kafka的时候,出现消息重复消费的问题.通过沟通与排查下来主要还是用户对消费组的认识不够.其实,在之前的博文 ...

  5. ActiveMQ消息的消费原理

    消费端消费消息: 在 初识ActiveMQ 中我提到过,两种方法可以接收消息,一种是使用同步阻塞的ActiveMQMessageConsumer#receive方法.另一种是使用消息监听器Messag ...

  6. 记一次线上bug排查-quartz线程调度相关

    记一次线上bug排查,与各位共同探讨. 概述:使用quartz做的定时任务,正式生产环境有个任务延迟了1小时之久才触发.在这一小时里各种排查找不出问题,直到延迟时间结束了,该任务才珊珊触发.原因主要就 ...

  7. 分布式消息服务DMS如何实现死信消息的消费

    本文部分内容节选自华为云帮助中心的分布式消息服务(DMS)服务的产品介绍 死信消息是什么 死信消息是指无法被正常消费的消息.分布式消息服务DMS支持对消息进行异常处理.当消息进行多次重复消费仍然失败后 ...

  8. NSQ源码剖析——主要结构方法和消息生产消费过程

    目录 1 概述 2 主要结构体及方法 2.1 NSQD 2.2 tcpServer 2.3 protocolV2 2.4 clientV2 2.5 Topic 2.6 channel 3 启动过程 4 ...

  9. springboot项目整合rabbitMq涉及消息的发送确认,消息的消费确认机制,延时队列的实现

    1.引入maven依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactI ...

随机推荐

  1. hdu3665 水最短路

    题意 :        从起点0开始,到达最近的那个是海边的城镇的距离.. 思路:       水的最短路,随你怎么写,dij,floyd,spfa..都行,只要你喜欢..我写的spfa好久不写了,复 ...

  2. Redhat中网络启动错误解决办法( Failed to start LSB: Bring up/down networking RTNETLINK answers: File exists)

    关于Redhat系列中网络启动失败的解决办法 报错: Failed to start LSB: Bring up/down networking.             RTNETLINK answ ...

  3. 路由协议之OSPF

    目录 OSPF协议 OSPF的七种状态 OSPF的11种LSA Stub和Nssa OSPF中的防环机制 OSPF中的路由汇总和路由过滤 OSPF中的虚拟链路 虚拟链路有两种存在的意义 OSPF中的认 ...

  4. 11.PHP与MySQL

    PHP与MySQL 首先是PHPStorm设置创建SQL的教程,找到了一个写的不错的,在这里:http://blog.csdn.net/knight_quan/article/details/5198 ...

  5. 学习Canvas绘图与动画基础 canvas入门(一)

    一.创建canvas 1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta char ...

  6. NumPy之:使用genfromtxt导入数据

    目录 简介 genfromtxt介绍 多维数组 autostrip comments 跳过行和选择列 简介 在做科学计算的时候,我们需要从外部加载数据,今天给大家介绍一下NumPy中非常有用的一个方法 ...

  7. Python数模笔记-Sklearn(1) 介绍

    1.SKlearn 是什么 Sklearn(全称 SciKit-Learn),是基于 Python 语言的机器学习工具包. Sklearn 主要用Python编写,建立在 Numpy.Scipy.Pa ...

  8. Day006 可变参数

    可变参数(不定项参数) 在jdk1.5开始,java支持传递同类型的可变参数给一个方法. 在方法声明中,在指定参数类型后加一个省略号(...). 一个方法只能指定一个可变参数,它必须是方法的最后一个参 ...

  9. ColyseusJS 轻量级多人游戏服务器开发框架 - 中文手册(下)

    快速上手多人游戏服务器开发.后续会基于 Google Agones,更新相关 K8S 运维.大规模快速扩展专用游戏服务器的文章.拥抱️原生 Cloud-Native! 系列 ColyseusJS 轻量 ...

  10. Django(3)pycharm创建项目

    创建项目 我们创建django项目有两种方式,命令行方式和使用pycharm工具创建,本文就介绍常用的pycharm工具创建   首先点击django,输入项目的名称,选择创建好的虚拟环境,最后点击c ...