为什么要做邮件通知?
- 一懒人,我是一个懒人,懒到即便有日志平台看日志我也嫌麻烦,更别说要登录服务器看日志更麻烦。如果错误日志自动发我就好了。
- 急脾气,我脾气不好,当系统出现问题反馈到我这儿时,我总想着急的问清一些具体情况,发生时间,具体现象,之前有没有类似问题,截图说明。但是通常得到的答案是:不清楚。 我就很生气。一般这种问题是经过多人流转才到我这儿,如果我能第一时间知道就好了。
- 要面子,作为一个有多年工作经验的程序员,如果负责的项目经常出问题,总是给别人带来麻烦,不能分担领导的压力,我面子上是挂不住的。如果问题发生后还没人发现,我自己先发现偷偷修复就好了。
基于以上原因,结合项目实际情况,我选择了用免费的邮件通知。
哪些地方用邮件通知?
-
restful未知异常, 最开始我在 @RestControllerAdvice 里加了邮件通知功能,在这里面可以监控到 所有restful接口的异常。
-
逻辑预判异常,一些预判型异常,这种异常一般是之前发生过一次这种情况,影响比较大(比如涉及钱),但是代码逻辑又不好处理,就加了个通知,进行人工干预。
-
定时任务异常, @RestControllerAdvice 只能监控restful接口的异常,如果定时任务里发生异常 是监控不到的。 定时任务的异常也需要处理
-
调试日志, 和三方对接时为了方便调试,需要打印详细日志,如果再去翻日志就太麻烦了,直接发邮件。
怎么写的代码?
-
工具类,快速搭建框架自带的,hutool工具类的,一搜一大堆,不是难点。 注意的一点是要用异步发邮件,不要影响主线程。
-
@RestControllerAdvice 全局异常监控里加上 邮件通知代码, 所有的restful接口 有异常就能监控到。一般Spring项目里都有,你可以全局搜@RestControllerAdvice
-
定时任务里加上邮件通知,一般Quartz 框架整合时 都会有段代码执行反射,可以找找你的框架里是在哪儿整合的。
比如下面这样Object target = SpringContextUtils.getBean(scheduleJob.getBeanName()); Method method = target.getClass().getDeclaredMethod("run", String.class); method.invoke(target, scheduleJob.getParams());
在这个地方加上发邮件代码即可,所有的定时任务里如果有异常就会自动执行
try { //执行任务 logger.info("任务准备执行,任务ID:{}", scheduleJob.getId()); Object target = SpringContextUtils.getBean(scheduleJob.getBeanName()); Method method = target.getClass().getDeclaredMethod("run", String.class); method.invoke(target, scheduleJob.getParams()); logger.info("任务执行完毕,任务ID:{} 总共耗时:{} 毫秒", scheduleJob.getId(), times); } catch (Exception e) { logger.error("任务执行失败,任务ID:{}", scheduleJob.getId(), e); SysMailTemplateService sysMailTemplateService = SpringContextUtils.getBean(SysMailTemplateService.class); try { sysMailTemplateService.sendMailNormal(EnvConfig.mailAddress, "定时任务发生未知异常,请及时处理", log.toString()); } catch (Exception ex) { ex.printStackTrace(); } }finally { //获取spring bean ScheduleJobLogService scheduleJobLogService = SpringContextUtils.getBean(ScheduleJobLogService.class); scheduleJobLogService.insert(log); }
-
根据上面的写法,就要求我们的业务代码里 不要随便写try catch, 能控制住的异常当然可以逻辑控制, 不可预判的异常大可放开向上抛出用邮件拦截住通知你。 如果业务代码都保守性的try catch 只打印了个日志,邮件通知监控不到,等用户反馈问题后就是大问题。
曾遇到的问题
- 本地能发送邮件,但在阿里云服务器上发送不了邮件,阿里云将25端口禁用了,需要改用SSL 465
p.setProperty("mail.smtp.ssl:enable", "true");
p.setProperty("mail.smtp.socketFactory.port", "465");
p.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
-
163邮箱每天能发的邮件数量有限制,如果发的太多会报错,我之前一直用的公司的 163.com 给我发邮件, 有次在测试环境调试一个新的对接,由于错误数据比较多暴漏了这个问题,发现这个问题后改成 一部分应用用公司的163,一部分应用用我自己的QQ邮箱
-
发送邮件时需要注意,password并不是 邮箱的登录密码,而是一个授权码
https://email.163.com/
https://mail.qq.com/
-
QQ邮箱的授权码 有时会莫名其妙失效,导致发送不了邮件,我遇到时是 23年底,几天内失效了两次,之后就没问题了,怀疑是那段时间 腾讯服务器崩掉有关。 24年4月还出现一次,不太稳定
-
可以用QQ邮箱接收邮件,电脑端用foxmail客户端,手机端用QQ邮箱 APP,两边是同步的
利与弊
-
通过添加邮件通知功能确实能帮助掌握系统的运行情况,出现异常能第一时间知道,从被动得等待领导把问题抛出来变成主动发现问题,能让系统更好的运行。
-
我负责的系统有时出现问题后,我第一时间解决掉并反馈给用户后,通常都会得到一个赞,满足了小小的虚荣心。
-
随着负责的工作越来越多,我的邮件也越来越多,导致我没有太多时间集中干某个工作,大部分时间是零碎的。 针对这个问题,我在尝试关掉一些意义不大的邮件通知,寻找一个平衡点,不让自己太累又能监控好系统。
-
有时邮件通知会集中爆发,多个问题会一起出现,我只能一个个处理,通常一个问题并不是能立马处理完
适用场景
我们公司是一些自营性的项目,基本是一个人长期负责几个项目。项目不大,比较适合这种方式,免费简单高效