1. 問題描述
項目使用的相關技術棧:Alitomcat+Pandora
日常環境下郵件發送正常,進入預發環境中郵件發送失敗。拋出異常(偶現)
java.net.SocketException: Connection reset
javax.mail.MessagingException: Can't send command to SMTP host;nested exception is:
java.net.SocketException: Connection closed by remote host
javamail SSL peer shut down incorrectly
2. 排查思路
2.1 郵箱發送源碼有BUG
大概網上查了下,該異常的導致原因。沒有發現啥問題。朝着郵件發送源碼有BUG的方向排查了好久@-@
2.2 環境相關的問題,先看看郵箱相關的JAR包
發現郵箱相關的JAR包有好多個,如下圖。再看看拋出異常的類javax.mail.Transport, 同時處在在多個JAR包中。javax.mail\javax.mail-api\mail
2.3 同名類有多個,兩個不同環境,分別從哪個JAR包加載?
對比日常環境、預發環境加載的javax.mail.Transport,發現兩個環境加載的包不一樣。
分析到這里存在以下疑問:
- 如果項目中出現多個全限定名相同的類,從哪個JAR包中加載?順序是怎么樣的?
- 目前項目是Docker化部署的,為啥日常環境、預發環境部署出現不一樣? Docker化部署有覆蓋不到的場景?
2.4 同名類從哪個JAR包中加載?順序是怎么樣的?
參照StackOverFlow上的一個問答,從/lib目錄下,加載JAR包的順序是什么。某個Tomcat版本巧合之下,加載JAR包是按字母序來的。實際官方指出開發Web應用時,不應該依賴於對JAR包的加載順序,它的排序取決於底層操作系統搜索排序,即 find "/path," -name *.jar,find命令返回的順序是隨機的,跟磁盤上文件內容有關系。
用提供的靜態 class 查找工具findclass.py,在WEB-INF/lib 目錄下,查找對應類的JAR包。日常\預發環境找到的包順序相反。
2.5 Docker化部署前提下,為什么會出現部署不一致情況?
環境是一致的,但是實際應用時,還是可能會有細節上的不同。
3. 總結
- 不要引入非必要的JAR包,明確功能,然后引入
- 可以認為加載的類時,選用該類所在的JAR是無序的(取決於find命令返回順序)。官方指出不應對JAR包加載順序有依賴。
- Docker化部署理論上是環境一致的,但實際應用時,可能還是會存在細節上有不一樣,比如find命令返回順序不同。
參考鏈接:
https://bz.apache.org/bugzilla/show_bug.cgi?id=57129