背景
maven deploy的過程中Archiva(Apache的開源Maven私服項(xiàng)目)一直響應(yīng)沒有權(quán)限,于是想起來Archiva系統(tǒng)有個(gè)比較怪的點(diǎn)——默認(rèn)是需要定期修改密碼的。
一旦之前設(shè)置的密碼過期,就必須通過“忘記密碼”流程修改,而這個(gè)流程需要發(fā)送郵件,不過可能這個(gè)郵件發(fā)送有什么問題,一直收不到。
于是乎就必須走重新創(chuàng)建用戶的流程,即刪除Archiva的用戶信息目錄后重啟。我的用戶目錄在/usr/local/data/databases/users。
查閱資料后,發(fā)現(xiàn)可以在Archiva的WebUI中User Runtime Configuration-Properties第三頁-security.policy.password.expiration.enabled選項(xiàng)設(shè)置為false關(guān)閉密碼過期策略。
慘痛的掉坑過程
原以為關(guān)閉過期策略就萬事大吉,沒想到后續(xù)的這一系列操作直接把CI/CD流程整癱瘓了:
- 刪除用戶目錄并重啟,在WebUI關(guān)閉了密碼過期策略
- 部署博客服務(wù)后服務(wù)啟動(dòng)失敗,僅瞟了一眼日志就誤以為內(nèi)存不夠用了
ps.這里特別說明一下,服務(wù)器內(nèi)存比較?。ǜF),在擴(kuò)容內(nèi)存之前是經(jīng)常不夠用的,于是慣性思維,認(rèn)為確實(shí)內(nèi)存不夠用了。而后來定位到真正的原因是服務(wù)器maven package過程中jar未更新。 - 把Archiva所使用的Tomcat關(guān)閉,釋放內(nèi)存資源
- 服務(wù)仍然啟動(dòng)失敗,發(fā)現(xiàn)原來是jar有問題,于是嘗試修復(fù)jar中的問題(當(dāng)然,實(shí)際上是jar未更新)
- 需要部署jar,因此又啟動(dòng)Archiva,這時(shí)Archiva啟動(dòng)不了,報(bào)錯(cuò)
至此,整個(gè)狀態(tài)是:博客服務(wù)由于依賴問題無法啟動(dòng);Archiva服務(wù)無法啟動(dòng);Jenkins正常但由于Archiva癱瘓無法打包發(fā)布。
Archiva報(bào)錯(cuò)內(nèi)容
核心錯(cuò)誤日志:
... # 服務(wù)無法啟動(dòng)
... # 一些bean無法創(chuàng)建
...Error creating bean with name 'ldapConnectionFactory#archiva'... # 一些ldap相關(guān)的bean無法創(chuàng)建
... # 一些其他的原因
Caused by: javax.naming.InvalidNameException: Invalid name: lee # 異常root,這個(gè)name是Archiva登錄用戶名
at javax.naming.ldap.Rfc2253Parser.doParse(Rfc2253Parser.java:111)
at javax.naming.ldap.Rfc2253Parser.parseDn(Rfc2253Parser.java:70)
at javax.naming.ldap.LdapName.parse(LdapName.java:785)
at javax.naming.ldap.LdapName.<init>(LdapName.java:123)
at org.apache.archiva.redback.common.ldap.connection.LdapConnectionConfiguration.setBindDn(LdapConnectionConfiguration.java:198)
at org.apache.archiva.web.runtime.ldap.ArchivaLdapConnectionFactory.initialize(ArchivaLdapConnectionFactory.java:68)
... 117 more
簡而言之,一些LDAP相關(guān)的內(nèi)容創(chuàng)建失敗,最核心的原因是某個(gè)地方的用戶名驗(yàn)證出錯(cuò)了,而這個(gè)用戶名是當(dāng)時(shí)關(guān)閉密碼過期策略時(shí)登錄的Archiva用戶名。
排查過程
0. 搜索引擎
由于Archiva參考資料較少,同時(shí)這個(gè)異常拋出來相關(guān)信息非常少,跟Archiva相關(guān)的僅兩行,絞盡腦汁用了各種關(guān)鍵詞組合也找不出幾個(gè)相關(guān)的內(nèi)容。萬能的Google也失靈了。
1. 查看Rfc2253Parser.doParse方法
追蹤代碼,發(fā)現(xiàn)拋異常的原因是用戶名中不包含等號(hào)??墒菫槭裁匆忍?hào)?
2. 查看LdapName.<init>方法
LdapName的構(gòu)造方法中有入?yún)ame,直接透傳至Rfc2253Parser.doParse方法中。
3. 查看ArchivaLdapConnectionFactory.initialize方法
沒辦法,信息太少,只能硬著頭皮上——把Archiva源碼拉下來找。
追蹤到該方法中有調(diào)用ldapConnectionConfiguration.setBindDn方法,在這里傳入了name。
看上下文,這是一個(gè)讀取配置文件的工具類,由于配置文件變動(dòng)導(dǎo)致了服務(wù)啟動(dòng)異常。
通過資料了解到LDAP是一個(gè)目錄訪問協(xié)議,可以簡單理解為通過一系列KV Pair實(shí)現(xiàn)樹形的目錄層次結(jié)構(gòu),在這之中baseDn可以理解為根目錄,bindDn也就是報(bào)錯(cuò)的setter目標(biāo)可以理解為根目錄下綁定的一個(gè)子目錄。這能夠解釋為何傳入的bindDn格式上必須包含等號(hào)(KV Pair)。
到這里就很奇怪了,在掉坑過程中我并沒有修改過配置文件,即使通過WebUI修改的配置也是布爾型數(shù)據(jù),為何把登錄用戶名寫入了這個(gè)根本不相關(guān)的配置項(xiàng)里?況且現(xiàn)在Archiva啟動(dòng)不了,要把密碼過期策略重新打開恢復(fù)修改前的狀態(tài)也不行了。
排查源碼過程中發(fā)現(xiàn)Archiva中LDAP相關(guān)的配置文件分為兩處,即{appBase}/conf/archiva.xml和~/.m2/archiva.xml,然而在這其中都“沒有”找到相關(guān)的配置。尤其是因?yàn)锳rchiva的部署和配置方式都不是常規(guī)路子,配置文件散落各處,導(dǎo)致排查難度提高。
4. 再次搜索
了解到核心原因后再次使用各種關(guān)鍵詞組合進(jìn)行搜索,終于在某個(gè)角落里發(fā)現(xiàn)了一句話(Google首屏最后兩條,關(guān)鍵詞ArchivaLdapConnectionFactory archiva configuration):

這位受害人的描述跟我的經(jīng)歷一模一樣,連報(bào)錯(cuò)都是一樣的。
幾經(jīng)輾轉(zhuǎn),最終通過這個(gè)標(biāo)題在Apache Issues中看到了最終的解決方案。
問題解決
在參考資料中受害人自述的幫助下我解決了這個(gè)問題:刪除~/.m2/archiva.xml文件中的LDAP相關(guān)配置后重啟Archiva解決。

而這個(gè)自述及相關(guān)評(píng)論也完全表述了我的心聲。
- 不知情的情況下Archiva修改了LDAP中bindDn的配置(有說是瀏覽器自動(dòng)填充用戶名密碼導(dǎo)致的,我倒認(rèn)為是bug,也沒細(xì)看)
- 啟動(dòng)時(shí)未做配置文件預(yù)先驗(yàn)證
- 異常拋出信息過少,不看源碼不知道是配置有問題
- 配置文件分散且相關(guān)說明少,不看源碼根本不知道配置文件在哪
- 配置文件中間空行過多,容易誤導(dǎo)排查方向
- 兩年前2.2.0版本的bug,2.2.3版本還沒有修復(fù)(有提到修復(fù)版本在不使用LDAP的情況下配置出錯(cuò)也可正常啟動(dòng),但非預(yù)期的配置修改這個(gè)bug還在)
總的來說,非預(yù)期且無相關(guān)性的配置改動(dòng)、重要的debug信息被吞會(huì)導(dǎo)致排查過程及其困難,這一點(diǎn)在我們自己的日常開發(fā)中也非常值得注意。
陷入排查困境時(shí)查看源碼可能會(huì)有額外收獲,更有利于提取問題本質(zhì)(更好Google)。
參考資料
[MRM-1907] Archiva won't start due to a misconfigured Redback Runtime Configuration - ASF JIRA
本文搬自我的博客,歡迎參觀!