事故描述
1、上午9.55發(fā)布了一個Apollo動態(tài)配置參數(shù);
2、片刻后,服務(wù)器接口開始出現(xiàn)大量的超時告警,似乎是某資源被耗盡不足分配;
3、正值業(yè)務(wù)請求高峰的上午十點(diǎn)(平臺上午10點(diǎn)會有一些活動會拉一波用戶流量);
4、考慮是否是機(jī)器資源不足導(dǎo)致無法承載用戶并發(fā)量,其實(shí)不是,還是跟Apollo發(fā)布配置有關(guān);
5、進(jìn)行服務(wù)器資源觀測,發(fā)現(xiàn)14臺機(jī)器只有1臺機(jī)器線程數(shù)急劇飆升,并且出現(xiàn)了死鎖線程(平臺分析工具或jstack),超時告警也都集中出現(xiàn)在這一臺機(jī)器上;
6、趕緊進(jìn)行對應(yīng)機(jī)器重啟,先解除故障;
7、隨后進(jìn)行dubbo支持的離線jstack-log分析;
從dubbo源碼可以看到AbortPolicyWithReport繼承自AbortPolicy,AbortPolicy的默認(rèn)行為是如果任務(wù)超過線程池的最大處理能力則直接拒絕任務(wù)并拋出異常。而AbortPolicyWithReport除了拋出異常外,還打印了一條非常詳細(xì)的日志,該日志包含了線程池的詳細(xì)配置,并且在用戶的家目錄下面導(dǎo)出了一個Dubbo_JStack.log文件。
原因分析
jasypt-spring-boot-starter是干嘛的?
Jasypt(Java Simplified Encryption)是一個用于Java應(yīng)用程序的簡單加密庫,它提供了各種加密算法和解密工具。
jasypt-spring-boot-starter
是一個Spring Boot Starter,用于在Spring Boot應(yīng)用程序中方便地集成Jasypt,以實(shí)現(xiàn)配置文件的加密和解密。在 Apollo 中添加配置項(xiàng),將數(shù)據(jù)庫密碼進(jìn)行加密保存。確保配置項(xiàng)的值以ENC()
開頭,表示它是一個加密過的值。例如,假設(shè)你的數(shù)據(jù)庫密碼是password
,加密后的值為ENC(加密后的密碼)
為什么會出現(xiàn)死鎖現(xiàn)象?
CachingDelegateEncryptablePropertySource中getProperty方法中存在加鎖操作(多把鎖),且加鎖的順序不是一致的!
圖1:
圖2:
上圖2中的source就是圖1中的delegate
如上圖,最終會在for循環(huán)中重新訪問到:
com.ulisesbocchio.jasyptspringboot.caching.CachingDelegateEncryptablePropertySource#getProperty
簡化后的加鎖分析圖如上圖,因?yàn)榧渔i的目標(biāo)是this:即CachingDelegateEncryptablePropertySource的實(shí)例對象,而這種實(shí)例對象又存在多個,就是代表有多把鎖的存在。那么就會存在如上圖所示的場景,如果apollo觸發(fā)了更新,而此刻又有大量的線程在訪問property資源,那么在極端情況下就會觸發(fā)這個死鎖現(xiàn)象!這也是14臺機(jī)器只有一臺出現(xiàn)死鎖問題的原因。后面找了github,也確實(shí)是存在這個問題。
官方解釋及如何解決
Issues · ulisesbocchio/jasypt-spring-boot · GitHub
文章來源:http://www.zghlxwxcb.cn/news/detail-861470.html
加鎖目標(biāo)改用屬性名稱的字符串常量值,這樣多線程并發(fā)訪問某個name時,加鎖的目標(biāo)是固定的,鎖也是同一把,不存在多把鎖,這樣就避免了死鎖;文章來源地址http://www.zghlxwxcb.cn/news/detail-861470.html
解決:升級版本到3.0.4以上!
到了這里,關(guān)于jasypt組件死鎖bug案例分享的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!