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

前言

只有光頭才能變強。

文本已收錄至個人GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3yhtml

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

1、先說背景

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

我去DB查了一下近期的郵件發送狀況,表示:「看着都挺正常的,線上沒有異常的狀況。可能郵件在redis裏邊堆積了,還沒消費」redis

select * from email order by id desc limit 100

先來講一下我這邊發郵件的大體實現方式:sql

處理郵件消息的方式

這樣作有什麼好處?把Redis當作一個消息隊列,把請求所有扔到Redis上,這能削峯。機器A/B/C的線程會在必定的間隔內向Redis拉取消息,而後調用郵件接口進行發送。服務器

而我這邊會在頁面上提供一個功能給業務方查詢各種消息是否發送成功,因爲發送郵件是一個異步的操做,而前同事在編寫的時候又追求實時性異步

  • 目前的邏輯是:若是push到Redis是成功的,而且Redis裏邊沒有堆積着消息(說明機器A/B/C能及時處理掉這封郵件),那就認爲這封郵件發送成功。

PS:(若是系統不存在問題,其實這個實現也是OK的。由於郵件的發送量通常不會太大(Redis不會堆積消息),而且發送郵件的成功率也是挺高的spa

回到問題上,因爲有上面的一個背景,因此我就猜想:是否是小王在查結果時,這封郵件還堆積在Redis上,因此就直接返回失敗了。果不其然,我去查了一下Redis,還有200封郵件沒消息。線程

因而我就問小王:「你這發了多少封郵件啊?」小王表示:「20分鐘500封,1qps都不到」。我想了一下:「那咱們這有四臺機器,按道理是不會堆積那麼多的」。日誌

因而跑去線上服務器看一下消費的日誌,發現只有一臺機器在消費Redis的數據。又去看了一下錯誤的日誌是否是有大量的錯誤信息,並沒找到錯誤的日誌...

因而去查了一下機器的監控信息,也沒發現異樣。那問題就來了:爲啥就只有一臺機器在消費Redis的消息呢?其餘三臺機器的日誌和監控信息都沒異常。

2、解決

從日誌和機器的信息都判斷不出有什麼問題,這時我又想起在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多篇原創技術文章、海量視頻資源、精美腦圖, 關注便可獲取!

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

以爲個人文章寫得不錯,點

相關文章
相關標籤/搜索