只有光頭才能變強。文本已收錄至個人GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3yhtml
在線上遇到了一個發送郵件的問題,記錄一下。git
某一天,小王跟我反饋:「麻煩檢查一下線上郵件的發送狀況,我這查出來發送失敗啦」github
我去DB查了一下近期的郵件發送狀況,表示:「看着都挺正常的,線上沒有異常的狀況。可能郵件在redis裏邊堆積了,還沒消費」redis
select * from email order by id desc limit 100
先來講一下我這邊發郵件的大體實現方式:sql
這樣作有什麼好處?把Redis當作一個消息隊列,把請求所有扔到Redis上,這能削峯。機器A/B/C的線程會在必定的間隔內向Redis拉取消息,而後調用郵件接口進行發送。服務器
而我這邊會在頁面上提供一個功能給業務方查詢各種消息是否發送成功,因爲發送郵件是一個異步的操做,而前同事在編寫的時候又追求實時性。異步
PS:(若是系統不存在問題,其實這個實現也是OK的。由於郵件的發送量通常不會太大(Redis不會堆積消息),而且發送郵件的成功率也是挺高的。spa
回到問題上,因爲有上面的一個背景,因此我就猜想:是否是小王在查結果時,這封郵件還堆積在Redis上,因此就直接返回失敗了。果不其然,我去查了一下Redis,還有200封郵件沒消息。線程
因而我就問小王:「你這發了多少封郵件啊?」小王表示:「20分鐘500封,1qps都不到」。我想了一下:「那咱們這有四臺機器,按道理是不會堆積那麼多的」。日誌
因而跑去線上服務器看一下消費的日誌,發現只有一臺機器在消費Redis的數據。又去看了一下錯誤的日誌是否是有大量的錯誤信息,但並沒找到錯誤的日誌...
因而去查了一下機器的監控信息,也沒發現異樣。那問題就來了:爲啥就只有一臺機器在消費Redis的消息呢?其餘三臺機器的日誌和監控信息都沒異常。
從日誌和機器的信息都判斷不出有什麼問題,這時我又想起在Java中的一個命令:jstack
jstack命令主要用來查看Java線程的調用堆棧的,能夠用來分析線程問題(如死鎖)。
jstack詳細用法以及教程:https://www.cnblogs.com/kongzhongqijing/articles/3630264.html
因而我就去執行了一下jstack
命令,在信息中搜了一下"Email",真被我搜出來了:
那就好辦了,只要搜一下:「Java 發送郵箱 線程 阻塞」此類的關鍵字,應該就有解決方案了。
最後,發現是由於在發送郵件的時候沒有配置超時時間,致使某些線程在發送郵件的時候阻塞掉了(具體緣由不明)
樂於輸出 乾貨的Java技術公衆號: Java3y。公衆號內 有200多篇原創技術文章、海量視頻資源、精美腦圖, 關注便可獲取!
以爲個人文章寫得不錯,點贊!