1. 程式人生 > >如何打造一個高可用多租戶的企業級Maven私有倉庫服務

如何打造一個高可用多租戶的企業級Maven私有倉庫服務

href 雲效 repl group abi 方式 簽名 ava watermark

摘要: 為什麽要打造多租戶的企業級Maven私有倉庫服務? 在Java的世界中,我們通常使用Maven的依賴體系來管理構件(artifact,又稱為二方庫或三方庫)的依賴。Maven倉庫用於存儲這些構件。一般的遠程倉庫(比如Maven Central)只提供下載功能。

為什麽要打造多租戶的企業級Maven私有倉庫服務?
在Java的世界中,我們通常使用Maven的依賴體系來管理構件(artifact,又稱為二方庫或三方庫)的依賴。Maven倉庫用於存儲這些構件。一般的遠程倉庫(比如Maven Central)只提供下載功能。而用戶想要管理自己的私有二方庫,就只能搭建Maven私服。常用的Maven私服軟件有Nexus和Artifactory等。Maven私服是很多企業都需要的功能。

如今雲服務越來越深入人心,用戶不僅紛紛把自身的服務發布到雲端,甚至也會使用雲服務來管理自己的整個研發流程。而如果有一個企業級的Maven私有倉庫服務,用戶只需要簡單的開通服務,就可開箱即用,無需自己搭建,免去了維護的煩惱。

現有Maven私庫軟件的問題
打造這樣的服務首先可能會考慮借助已有的一些Maven私庫解決方案進行改造。Nexus和Artifactory的開源版雖然支持多租戶,但由於其缺乏高可用特性,無法進行水平拓展,單節點的穩定性達不到要求。Nexus和Artifactory的商業版本具有高可用特性,但單集群支持的用戶數始終有上限。

如下是Nexus的商業版本的高可用架構:

圖片來源https://help.sonatype.com/repomanager3/high-availability---introduction

雖然其商業版本支持高可用,但仍具有以下問題:

商業版本按照用戶數和使用時間收費,花費較大;
每個節點是有狀態的,通過inter-node replication的方式進行狀態同步,擴縮容有限制;
單個節點支持的倉庫數量是有性能限制的,超過限制後需要對集群對sharding處理,進一步增加系統的復雜度。
Artifactory的商業版也具有類似的問題。

高可用的Maven私庫服務的理想架構
既然現有的軟件無法滿足要求,那麽只有通過自研的方式來自己實現一套高可用的私有倉庫管理系統了。一個理想中的私有倉庫管理系統應該是這樣子的。

每個節點都實現了標準的Maven倉庫服務規範,他們彼此之間是無狀態的,通過負載均衡向外暴露服務,這樣進行擴縮容會更加的平滑,便於支撐起海量的服務;

使用對象存儲服務作為構建的存儲倉庫,比如阿裏雲的OSS。這樣所有節點都可以共用存儲,無需擔心容量及瀏覽問題,有效的解決IO瓶頸;
私有倉庫的元數據都存放在於應用無關的數據庫中,而索引信息則存儲在Elastic Search中,數據庫和Elastic Search都進行了集群化高可用配置。
實現標準的Maven倉庫服務規範
拋開倉庫管理、用戶及權限管理、系統管理等功能來說,一個最小可用的Maven倉庫服務僅需要滿足支持Maven客戶端進行上傳和下載的功能。也就是說私有倉庫服務暴露的http URL需要滿足一定的布局,具體可參見Repository Layout - Final一文。首先需要理解兩個概念。

Maven依賴
Maven依賴是我們在構建項目時使用到的構件(artifact),也就是常說的二方庫和三方庫。比如我們項目想使用fastjson組件時,需要在項目中的pom.xml文件中加入如下依賴:
技術分享圖片
如上所示,在Maven世界中確定一個構件需要三個參數:groupId,artifactId,version。這三個參數構成了Maven世界中的坐標。

主構件和次要構件
其實除了這三個參數外,還有另外兩個參數。第一個是packaging。該參數定義了Maven項目的打包方式,可能的值有pom, jar, maven-plugin, ejb, war, ear, rar, par等,默認值為jar,所以在上述的依賴中並不需要填寫packaging值。第二個是classifier。classifier用來擴充構件內容。它可以是任意字符串,經典的兩個值為javadoc和sources。比如你訪問http://maven.aliyun.com/nexus/service/local/repositories/central/content/com/alibaba/fastjson/1.2.47/,返回的內容中除了fastjson-1.2.47.jar還有fastjson-1.2.47-sources.jar和fastjson-1.2.47-javadoc.jar文件。fastjson-1.2.47.jar被稱為主構件(Primary Artifacts),而定義了classifier的構件被稱為次要構件(Secondary Artifacts)。

如果想獲取次要構件可以這樣寫。
技術分享圖片
其實Maven倉庫主要就是用來存儲管理這些構件。Maven和Gradle之類的客戶端訪問Maven倉庫時,進行上傳和下載構件時要求倉庫URL滿足一定的布局。

倉庫URL布局
當上傳或下載依賴時,Maven倉庫的URL布局為:

/$groupId[0]/../$groupId[n]/$artifactId/$version/$artifactId-$version.$extension
如果classifier不為空的話(也就是說該構件為次要構件),則URL布局為:

$groupId[0]/../$groupId[n]/$artifactId/$version/$artifactId-$version-classifier.$extension
在這裏會把groupId依據“.”分割為目錄。比如com.alibaba會變為com/alibaba。fastjson構件的jar的倉庫地址為:

/com/alibaba/fastjson/1.2.47/fastjson-1.2.47.jar
而fastjson的次要構件javadoc的倉庫地址為:

/com/alibaba/fastjson/1.2.47/fastjson-1.2.47-javadoc.jar
每個主構件都應該有一個POM文件與之對應:

/$groupId[0]/../${groupId[n]/$artifactId/$version/$artifactId-$version.pom
次要構件則無需單獨的POM文件,它會引用主構件的POM文件。

Maven會為每個構件(包括pom文件)生成md5和sha1校驗文件,放置在同級目錄下。比如fastjson-1.2.47.jar的校驗文件為fastjson-1.2.47.jar.sh1和fastjson-1.2.47.jar.md5。

只要實現了這樣的URL布局就可以滿足一個最小化的maven倉庫需要具備的功能。

後端對象存儲服務化改造
根據日常的統計來看,Maven倉庫服務的下載數量遠遠大於上傳數量。為了提供更好、更快的服務,我們可以對下載進行一系列的優化。優化以前下載構件的流程是這樣的。

?

從上圖中可以看出,當下載構件時,倉庫服務需要先從對象存儲服務下載資源,然後再轉發給客戶端。整個過程不僅耗時,而且會對倉庫服務節點的性能造成影響。經過仔細分析以後,我們發現其實倉庫服務無需從對象存儲服務下載構件,只需要收到客戶端的請求後,給客戶端返回一個302狀態碼,並生成一個預先簽名的對象存儲服務下載鏈接。這樣客戶端就可以直接通過對象存儲服務下載所需的構件。

?

新的實現方式無需倉庫服務和對象存儲服務進行數據流的交互,IO壓力都交給了更專業的對象存儲服務,下載速度可以提高數倍。

除此之外,還可以進行進一步的優化,即在對象存儲服務之前加上一層CDN服務,這樣可以保證不同的地區的客戶端的下載體驗都是一致的。

最後
目前這套架構已經替換了maven.aliyun.com,現在maven.aliyun.com運行的如絲般平滑。如果你需要使用可以自行上傳下載的maven私有倉庫服務,可以訪問我們的雲效版。

原文鏈接

本文為雲棲社區原創內容,未經允許不得轉載。

如何打造一個高可用多租戶的企業級Maven私有倉庫服務