Java發(fā)送郵件時(shí),必須要的一個(gè)配置!
前言
只有光頭才能變強(qiáng)。
文本已收錄至我的GitHub倉(cāng)庫(kù),歡迎Star:https://github.com/ZhongFuCheng3y/3y
在線(xiàn)上遇到了一個(gè)發(fā)送郵件的問(wèn)題,記錄一下。
一、先說(shuō)背景
某一天,小王跟我反饋:“麻煩檢查一下線(xiàn)上郵件的發(fā)送情況,我這查出來(lái)發(fā)送失敗啦”
我去DB查了一下近期的郵件發(fā)送情況,表示:“看著都挺正常的,線(xiàn)上沒(méi)有異常的情況。可能郵件在redis里邊堆積了,還沒(méi)消費(fèi)”
select?*?from?email?order?by?id?desc?limit?100
先來(lái)說(shuō)一下我這邊發(fā)郵件的大致實(shí)現(xiàn)方式:
處理郵件消息的方式這樣做有什么好處?把Redis當(dāng)做一個(gè)消息隊(duì)列,把請(qǐng)求全部扔到Redis上,這能削峰。機(jī)器A/B/C的線(xiàn)程會(huì)在一定的間隔內(nèi)向Redis拉取消息,然后調(diào)用郵件接口進(jìn)行發(fā)送。
而我這邊會(huì)在頁(yè)面上提供一個(gè)功能給業(yè)務(wù)方查詢(xún)各類(lèi)消息是否發(fā)送成功,由于發(fā)送郵件是一個(gè)異步的操作,而前同事在編寫(xiě)的時(shí)候又追求實(shí)時(shí)性。
目前的邏輯是:如果push到Redis是成功的,并且Redis里邊沒(méi)有堆積著消息(說(shuō)明機(jī)器A/B/C能及時(shí)處理掉這封郵件),那就認(rèn)為這封郵件發(fā)送成功。
PS:(如果系統(tǒng)不存在問(wèn)題,其實(shí)這個(gè)實(shí)現(xiàn)也是OK的。因?yàn)猷]件的發(fā)送量一般不會(huì)太大(Redis不會(huì)堆積消息),并且發(fā)送郵件的成功率也是挺高的。
回到問(wèn)題上,由于有上面的一個(gè)背景,所以我就猜測(cè):是不是小王在查結(jié)果時(shí),這封郵件還堆積在Redis上,所以就直接返回失敗了。果不其然,我去查了一下Redis,還有200封郵件沒(méi)消息。
于是我就問(wèn)小王:“你這發(fā)了多少封郵件???”小王表示:“20分鐘500封,1qps都不到”。我想了一下:“那我們這有四臺(tái)機(jī)器,按道理是不會(huì)堆積那么多的”。
于是跑去線(xiàn)上服務(wù)器看一下消費(fèi)的日志,發(fā)現(xiàn)只有一臺(tái)機(jī)器在消費(fèi)Redis的數(shù)據(jù)。又去看了一下錯(cuò)誤的日志是不是有大量的錯(cuò)誤信息,但并沒(méi)找到錯(cuò)誤的日志…
于是去查了一下機(jī)器的監(jiān)控信息,也沒(méi)發(fā)現(xiàn)異樣。那問(wèn)題就來(lái)了:為啥就只有一臺(tái)機(jī)器在消費(fèi)Redis的消息呢?其他三臺(tái)機(jī)器的日志和監(jiān)控信息都沒(méi)異常。
二、解決
從日志和機(jī)器的信息都判斷不出有什么問(wèn)題,這時(shí)我又想起在Java中的一個(gè)命令:jstack
jstack命令主要用來(lái)查看Java線(xiàn)程的調(diào)用堆棧的,可以用來(lái)分析線(xiàn)程問(wèn)題(如死鎖)。
jstack詳細(xì)用法以及教程:
https://www.cnblogs.com/kongzhongqijing/articles/3630264.html
于是我就去執(zhí)行了一下jstack命令,在信息中搜了一下"Email",真被我搜出來(lái)了:
發(fā)郵件卡住了那就好辦了,只要搜一下:“Java 發(fā)送郵箱 線(xiàn)程 阻塞”此類(lèi)的關(guān)鍵字,應(yīng)該就有解決方案了。
解決方案最后,發(fā)現(xiàn)是因?yàn)樵诎l(fā)送郵件的時(shí)候沒(méi)有配置超時(shí)時(shí)間,導(dǎo)致某些線(xiàn)程在發(fā)送郵件的時(shí)候阻塞掉了(具體原因不明)
mail.smtp.connectiontimeout:連接時(shí)間限制,單位毫秒。是關(guān)于與郵件服務(wù)器建立連接的時(shí)間長(zhǎng)短的。默認(rèn)是無(wú)限制。
mail.smtp.timeout:郵件接收時(shí)間限制,單位毫秒。這個(gè)是有關(guān)郵件接收時(shí)間長(zhǎng)短。默認(rèn)是無(wú)限制。
mail.smtp.writetimeout:郵件發(fā)送時(shí)間限制,單位毫秒。有關(guān)發(fā)送郵件時(shí)內(nèi)容上傳的時(shí)間長(zhǎng)短。默認(rèn)同樣是無(wú)限制。
公眾號(hào)文章導(dǎo)航:公眾號(hào)所有的文章導(dǎo)航
長(zhǎng)按掃碼可關(guān)注獲取?
歡迎關(guān)注
點(diǎn)個(gè)再看
