Java發送郵件必帶超時時間配置


前言

只有光頭才能變強。

文本已收錄至我的GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3y

在線上遇到了一個發送郵件的問題,記錄一下。

一、先說背景

某一天,小王跟我反饋:“麻煩檢查一下線上郵件的發送情況,我這查出來發送失敗啦”

我去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:郵件發送時間限制,單位毫秒。有關發送郵件時內容上傳的時間長短。默認同樣是無限制。

最后

樂於輸出干貨的Java技術公眾號:Java3y。公眾號內有200多篇原創技術文章、海量視頻資源、精美腦圖,關注即可獲取!

轉發到朋友圈是對我最大的支持!

覺得我的文章寫得不錯,點


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM