一、前言
前幾天線上 ZooKeeper 出了一次不大不小的問題,由於缺少監控報警,導致事發第二天才引起我們的注意,所幸沒有造成太大的影響。這起事情也督促我們盡快建立完備的監控體系,目前項目中使用 JavaMelody 監控應用狀態,但是缺少實時報警。所以最近團隊內部都在調研相關監控工具,初步選型 Sentry。
不過本篇跟 Sentry 其實沒啥關系,主要是在調研過程中碰到 Nexus 私服無法下載遠程 Jar 包的問題,這種情況在最早期系統重構時就有遇到,但后來又不知怎么滴就自己好了,時間關系也就沒深究原因。既然這次又碰到了,那干脆就徹底解決掉。
二、問題起因
那天下午我在本地搭好 Spring Boot Admin Server 后,打算找個應用充當 Client 看下效果。Client 端需要依賴 spring-boot-admin-starter-client 包。
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.0.4</version>
</dependency>
誰知這個依賴包死活下載不下來,打開公司的 Nexus 私服搜索這個包,發現是可以搜到的。
現場未截圖,上圖為修復后的搜索結果
三、排查過程
① 由於公司 Nexus 私服中的中央倉庫還是用的默認值http://repo1.maven.org/maven2/
。所以第一時間更換為阿里雲的http://maven.aliyun.com/nexus/content/groups/public/
,重啟之后發現還是下載不了。
② 對比了倉庫組「Public Repositories」的「Browse Index」及「Browse Storage」,發現「Browse Storage」沒有相應依賴包,但既然主界面搜索能搜到那就排除了倉庫索引的問題,於是死馬當活馬醫嘗試執行了 Rebuild Metadata、Update Index 操作后還是不行。
Public Repositories:這是個 Repository Group,它的作用是我們只需要在 setting.xml 文件中配置該 Repository Group 這一個地址就行了,它將自動從其所包含的 Repository 中下載構件。
③ 隨后倉庫列表里的 Repository Status 欄引起我的注意,發現包括中央倉庫在內的三個遠程倉庫呈如下狀態:
嘗試右鍵 Allow Proxy 發現一會狀態又變回 Auto Block 。
Nexus 有一個 Auto Block 特性。當客戶端發送請求到 Nexus 拉取 Jar 包時,如果 Nexus 當前沒有,就會到遠程倉庫上去找;但如果連不到遠程倉庫,就會造成客戶端的大規模等待,因此 Nexus 設計了 Auto Block 特性,在連接不上遠程倉庫時會將倉庫設置為 Auto Block 狀態,不再去連接遠程倉庫,而是直接告訴客戶端連接不上然后返回。當然此時 Nexus 內部還會有一個健康檢查的機制定時去連接遠程倉庫,如果能連接上就將倉庫狀態自動設置為有效,否則延長重試的時間,直到 60 分鍾重試一次。
知道上述原理后,只需要修改相應配置項即可。將選中倉庫「Configuration」欄的「Auto Blocking Enabled」配置項改為 false,重新 Allow Proxy 發現狀態正常了。
帶着一絲期待再次下載依賴包,發現還是不行。
(╯‵□′)╯︵┻━┻
④ 理智告訴我要冷靜,到這會我才想起來去看服務器上 Nexus 的日志,在 wrapper.log 文件中發現如下日志信息:
怎么會連不上阿里雲遠程倉庫,明明瀏覽器訪問能正常打開,但服務器卻 ping 不通,黑人問號臉???
沒辦法,只能回到 Nexus 管理后台重新換了一個倉庫地址,重啟之后發現依賴包終於可以下載了。
✿✿ヽ(°▽°)ノ✿
⑤ 依賴包問題是解決了,但是連不上阿里雲遠程倉庫讓我很費解,最后發現原來是在服務器的 hosts 里配了「maven.aliyun.com」的 IP 映射,該 IP 應該是早前的解析地址,現在早已失效,所以刪掉就好了。
59.110.144.164 maven.aliyun.com
四、總結
上述排查過程其實並不高效,沒有第一時間找到根本原因。回到現在,可以總結出一套相對有效的排查步驟:
- 首先關注服務器上 Nexus 的日志,一般情況下從日志就能看出到底是什么原因引起的
- 其次檢查本地 setting.xml 文件里的配置是否正常
- 然后檢查遠程倉庫的 Repository Status 是否正常,必要時將「Auto Blocking Enabled」配置項改為 false,中央倉庫地址最好改為國內倉庫地址
- 再檢查 Nexus 倉庫組「Public Repositories」的 Ordered Group Repositories 是否配置正確,一般除了 Snapshots 的遠程倉庫在右側之外,其余均在左側
- 如果搜索都搜不到,那就要檢查倉庫組索引是否正常,必要時右鍵執行 Rebuild Metadata 及 Update Index
五、其他
貼一份 setting.xml 文件的常規配置以供參考:
...省略其余部分...
<mirrors>
<mirror>
<id>nexus</id>
<url>http://127.0.0.1:8080/nexus/content/groups/public/</url>
<mirrorOf>*</mirrorOf>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus</id>
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>nexus</activeProfile>
</activeProfiles>
http://127.0.0.1:8080/nexus/content/groups/public/ 替換為自身私服地址
該配置聲明了一個 id 為 nexus 的鏡像,鏡像地址為私服
,其中 mirrorOf 的值為星號
,表示該鏡像代理所有遠程倉庫,任何對於遠程倉庫的下載請求都會被轉至私服。
另外還定義了一個 id 為 nexus 的 profile,這個 profile 包含了相關的倉庫及插件倉庫配置,同時配置中又使用 activeProfile 元素將 nexus 這個 profile 激活。需要說明的是倉庫跟插件倉庫配置它們的 id 都為 central,也就是說覆蓋了中央倉庫的配置,它們的 url 已無關緊要,因為所有請求都會通過鏡像訪問私服地址。