网站首页 > java教程 正文
在线上遇到了一个发送邮件的问题,记录一下。
一、先说背景
某一天,小王跟我反馈:“麻烦检查一下线上邮件的发送情况,我这查出来发送失败啦”
我去DB查了一下近期的邮件发送情况,表示:“看着都挺正常的,线上没有异常的情况。可能邮件在redis里边堆积了,还没消费”
select * from email order by id desc limit 100
先来说一下我这边发邮件的大致实现方式:
这样做有什么好处?把Redis当做一个消息队列,把请求全部扔到Redis上,这能削峰。机器A/B/C的线程会在一定的间隔内向Redis拉取消息,然后调用邮件接口进行发送。
而我这边会在页面上提供一个功能给业务方查询各类消息是否发送成功,由于发送邮件是一个异步的操作,而前同事在编写的时候又追求实时性。
- 目前的逻辑是:如果push到Redis是成功的,并且Redis里边没有堆积着消息(说明机器A/B/C能及时处理掉这封邮件),那就认为这封邮件发送成功。
PS:(如果系统不存在问题,其实这个实现也是OK的。因为邮件的发送量一般不会太大(Redis不会堆积消息),并且发送邮件的成功率也是挺高的。
回到问题上,由于有上面的一个背景,所以我就猜测:是不是小王在查结果时,这封邮件还堆积在Redis上,所以就直接返回失败了。果不其然,我去查了一下Redis,还有200封邮件没消息。
于是我就问小王:“你这发了多少封邮件啊?”小王表示:“20分钟500封,1qps都不到”。我想了一下:“那我们这有四台机器,按道理是不会堆积那么多的”。
于是跑去线上服务器看一下消费的日志,发现只有一台机器在消费Redis的数据。又去看了一下错误的日志是不是有大量的错误信息,但并没找到错误的日志…
于是去查了一下机器的监控信息,也没发现异样。那问题就来了:为啥就只有一台机器在消费Redis的消息呢?其他三台机器的日志和监控信息都没异常。
二、解决
从日志和机器的信息都判断不出有什么问题,这时我又想起在Java中的一个命令:jstack
jstack命令主要用来查看Java线程的调用堆栈的,可以用来分析线程问题(如死锁)。
jstack详细用法以及教程:
https://www.cnblogs.com/kongzhongqijing/articles/3630264.html
于是我就去执行了一下jstack命令,在信息中搜了一下"Email",真被我搜出来了:
那就好办了,只要搜一下:“Java 发送邮箱 线程 阻塞”此类的关键字,应该就有解决方案了。
最后,发现是因为在发送邮件的时候没有配置超时时间,导致某些线程在发送邮件的时候阻塞掉了(具体原因不明)
- mail.smtp.connectiontimeout:连接时间限制,单位毫秒。是关于与邮件服务器建立连接的时间长短的。默认是无限制。
- mail.smtp.timeout:邮件接收时间限制,单位毫秒。这个是有关邮件接收时间长短。默认是无限制。
- mail.smtp.writetimeout:邮件发送时间限制,单位毫秒。有关发送邮件时内容上传的时间长短。默认同样是无限制。
文章来源:https://dwz.cn/FRvvdAVh作者:Java3y
猜你喜欢
- 2024-10-08 避免重复造轮子,Java 程序员必备
- 2024-10-08 Java二十周年特别策划--谈谈我与Java的那些年、这些事
- 2024-10-08 Prometheus+Grafana+钉钉部署一个单机的MySQL监控告警系统
- 2024-10-08 Java程序员必须了解的20个lib库(郑州java程序员工资一般多少)
- 2024-10-08 使用java写爬虫时可能会用到.httpclient中Headers及Cookies
- 2024-10-08 Java二十周年特别策划——谈谈我与Java的那些年、这些事
- 2024-10-08 白当了这么多年程序员,今天才发现伪造邮件的小秘密
- 2024-10-08 SpringBoot+RabbitMQ ,保证消息100%投递成功并被消费(附源码)
- 2024-10-08 如何将自己的jar包发布到maven中央仓库,让别人也能使用?
- 2024-10-08 郑州Java学习进阶课程之消息队列(java中消息队列什么意思)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)