线上消息堆积与感想

共 2449字,需浏览 5分钟

 ·

2021-04-28 02:29



环境介绍



1.应用服务器部署在阿里云

2.消息中间件使用阿里云RocketMQ



前两天线上发生了MQ消息堆积的情况,在我的知识认知里,消息堆积的原因是消费者消费能力差,无法及时消费消息,才会导致消息堆积.

那么有哪些因素会导致消费者消费能力差呢? 我目前的理解有三种情况


因素




1:Dubbo的RPC调用时间太久


2:查询数据库或者插入数据太久


3:业务中还有其他耗时操作,比如发送邮件



记得以前看博客的时候,似乎看到过说发送邮件耗时久导致消息堆积的情况, 而现在就发生在自己身上,真是冥冥之中自有安排.


发生消息堆积,查看阿里云上的线程堆栈信息,如下



从线程堆栈上来看,线程在发送邮件,准确说在连接. 根据代码分析以及一段时间的观察线程,断定就是发送邮件的逻辑导致的.临时注释掉这段代码,重新发布,问题解决.


其实发送邮件并不会耗时太久, 而根据阿里云ARMS上的错误显示,消息消费失败总耗时2min. 为什么发送邮件(准确说是连接)会这么久. 因为那段发送邮件的代码在本地测试,只耗时1s左右.


<dependency>    <groupId>javax.mail</groupId>    <artifactId>mail</artifactId>    <version>1.4</version></dependency>


import javax.mail.Authenticator;import javax.mail.BodyPart;import javax.mail.Message;import javax.mail.Message.RecipientType;import javax.mail.MessagingException;import javax.mail.Multipart;import javax.mail.PasswordAuthentication;import javax.mail.Session;import javax.mail.Transport;import javax.mail.internet.InternetAddress;import javax.mail.internet.MimeBodyPart;import javax.mail.internet.MimeMessage;import javax.mail.internet.MimeMultipart;
import java.util.Date;import java.util.HashMap;import java.util.Map;import java.util.Properties;
public static void main(String[] args) { long start = System.currentTimeMillis(); try { // 配置仅为了文章说明,并不是真实配置 Mail mail = new Mail("xyz@qq.com", "password"); mail.addToAddress(Mail.ReceiveType.TO, "opq@qq.com"); mail.setMailInfo(Mail.Mode.TEXT_MAIL, "这是测试数据", "这是测试数据"); mail.send(); } catch (Throwable e) { System.out.println(e.getMessage()); } long end = System.currentTimeMillis();
System.out.println(end - start);}



我把上面的代码在线上机器测试,发现耗时的确在2min. 为了描述, 我这里以我自己的阿里云服务器做演示.




测试了两次,耗时都在1min.   

接下来通过strace命令查看系统调用, 看下具体耗时在哪个系统调用上.



关于如何使用strace命令查看系统调用,在我之前的文章中也有过一些介绍






邮件发送默认使用25号端口,搜索下关键字25

grep -iE 'connect.*25' strace*



在连接邮件服务器25号端口的时候,超时了.


为什么本地耗时1s, 而在阿里云上的机器就耗时这么久呢? 原因只要一个





阿里云默认禁用了25号端口,所以导致连接超时.



在本次事件中,还发现一个情况




消息已经消费成功,可是MQ Broker依然投递消息. 简单咨询了阿里云客服,也没给我个具体原因.





请回答


●常见消费者消费慢的因素有哪些?

●消费慢的时候,要查看下线程堆栈,观察线程都在干啥

●你会使用strace命令查看系统调用吗?







如上图,目前给我的感觉,作为一个Java码农或者工程师,系统上应该要对以上四个都要熟悉.

你不仅要会使用Java层面的Map,Thread,AQS等等, 当它调用到native方法时候,你还要去JVM层面追踪查看具体的实现,JVM层面可是C或者C++语言. 还有它最终调用到的系统调用是哪个. 而绝大多数人都停留在Java层面,当然这个层面达到精通也很难. 了解JVM的更少了, 能够继续向下了解C和Linux的那就凤毛麟角了.


你掌握的技术,一个刚毕业的学生在2个月或者半年就掌握了,但是别人掌握的知识,你未必在1-2年能掌握. 这或许就是人与人之间的区别.  你是哪种人呢?




浏览 39
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报