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

Java3y發表於2019-09-06

前言

只有光頭才能變強。

文字已收錄至我的GitHub倉庫,歡迎Star:github.com/ZhongFuChen…

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

一、先說背景

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

我去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詳細用法以及教程:www.cnblogs.com/kongzhongqi…

於是我就去執行了一下jstack命令,在資訊中搜了一下"Email",真被我搜出來了:

發郵件卡住了

那就好辦了,只要搜一下:“Java 傳送郵箱 執行緒 阻塞”此類的關鍵字,應該就有解決方案了。

解決方案

最後,發現是因為在傳送郵件的時候沒有配置超時時間,導致某些執行緒在傳送郵件的時候阻塞掉了(具體原因不明)

  • mail.smtp.connectiontimeout:連線時間限制,單位毫秒。是關於與郵件伺服器建立連線的時間長短的。預設是無限制。
  • mail.smtp.timeout:郵件接收時間限制,單位毫秒。這個是有關郵件接收時間長短。預設是無限制。
  • mail.smtp.writetimeout:郵件傳送時間限制,單位毫秒。有關傳送郵件時內容上傳的時間長短。預設同樣是無限制。

最後

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

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

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

相關文章