使用 Maven 或 Gradle 等軟體建構工具 (build tool) 常常會需要使用 Maven 套件倉儲 (artifacts repository) 來作為套件存放的地方 。 過去山姆鍋習慣使用 Nexus Repository Manager 來作為這樣的套件倉儲服務器 , Artifactory 雖然沒用過 , 看起來也很不錯 。 本來不加思索打算按照習慣用 Nexus 安裝個套件倉儲 , 或者使用 Artifactory 看看也很新鮮 , 但突發奇想 : 可不可以使用 Amazon S3 來作為 Maven repository? 有什麼問題跟限制 ?

說是突發奇想也不全然是事實 , 畢竟 「 影化身科技 」 的發展策略之一就是盡量採用雲端服務而不自行管理服務器 。 基於這個方向便開始 Google 相關的文章 , 看看有沒有可能完成這個挑戰 。

使用 S3 作為套件倉儲的好處

Amazon S3 作為儲存服務 , 提供下列好處 :

  • 可靠性高 : 資料在同一個區域 , 多個資料中心存放 。
  • 可用性高 : 不會因為單一服務器或資料中心故障導致無法使用 。
  • 整合 IAM: 可以限制可以存取的機器或用戶 。

支援 S3 作為套件倉儲的方法

本來以為會很麻煩 , 想不到 Google 一下就發現已經有人提出 解決方法 。 所提的方法適用以 Maven 作為建構工具 , 目前還沒有發現使用 Gradle 的做法 。

首先在您個人的 Maven 設定檔 ( 通常位於 ~/.m2/settings.xml) 加入兩個 "\" 片段 :

<?xml version="1.0" encoding="UTF-8"?>  
 <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"  
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
      xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">  
   <servers>  
     <server>  
       <id>maven-s3-release-repo</id>  
       <username>ACCESS_KEY_ID</username>  
       <passphrase>SECRET_ACCESS_KEY</passphrase>  
     </server>  
     <server>  
       <id>maven-s3-snapshot-repo</id>  
       <username>ACCESS_KEY_ID</username>  
       <passphrase>SECRET_ACCESS_KEY</passphrase>  
     </server>  
   </servers>  
 </settings>  

其中 ,ACCESS_KEY_ID/SECRET_ACCESS_KEY 就是從 Amazon 控制台產生的 security credentials( 安全憑證 )。

針對要發佈到 Amazon S3 的專案 , 修改其 pom.xml。 主要有兩個部分 , 第一部分是在 元素中加入 org.springframework.build.aws.maven 這個擴充功能 , 讓 Maven 知道符合發佈到 S3。

<build>  
     <extensions>  
       <extension>  
         <groupId>org.springframework.build.aws</groupId>  
         <artifactId>org.springframework.build.aws.maven</artifactId>  
         <version>3.0.0.RELEASE</version>  
       </extension>  
     </extensions>
</build>

再來就是加入幾個套件倉儲位置的宣告 :

<repositories>  
     <repository>  
       <id>maven-s3-release-repo</id>  
       <name>S3 Release Repository</name>  
       <url>s3://S3_BUCKET_NAME/release</url>  
       <releases>  
         <enabled>true</enabled>  
       </releases>  
       <snapshots>  
         <enabled>false</enabled>  
       </snapshots>  
     </repository>  
     <repository>  
       <id>maven-s3-snapshot-repo</id>  
       <name>S3 Snapshot Repository</name>  
       <url>s3://S3_BUCKET_NAME/snapshot</url>  
       <releases>  
         <enabled>false</enabled>  
       </releases>  
       <snapshots>  
         <enabled>true</enabled>  
       </snapshots>  
     </repository>  
   </repositories>  
   <pluginRepositories>  
     <pluginRepository>  
       <id>maven-s3-release-repo</id>  
       <name>S3 Release Repository</name>  
       <url>s3://S3_BUCKET_NAME/release</url>  
       <releases>  
         <enabled>true</enabled>  
       </releases>  
       <snapshots>  
         <enabled>false</enabled>  
       </snapshots>  
     </pluginRepository>  
     <pluginRepository>  
       <id>maven-s3-snapshot-repo</id>  
       <name>S3 Snapshot Repository</name>  
       <url>s3://S3_BUCKET_NAME/snapshot</url>  
       <releases>  
         <enabled>false</enabled>  
       </releases>  
       <snapshots>  
         <enabled>true</enabled>  
       </snapshots>  
     </pluginRepository>  
   </pluginRepositories>  

   <distributionManagement>  
     <repository>  
       <id>maven-s3-release-repo</id>  
       <name>S3 Release Repository</name>  
       <url>s3://S3_BUCKET_NAME/release</url>  
     </repository>  
     <snapshotRepository>  
       <id>maven-s3-snapshot-repo</id>  
       <name>S3 Snapshot Repository</name>  
       <url>s3://S3_BUCKET_NAME/snapshot</url>  
     </snapshotRepository>  
   </distributionManagement>

S3_BUCKET_NAME 自然要跟您建立的 S3 bucket 名稱相對應 。

最後 原文作者 也提供了實際範例 , 放在 GitHub 上供人參考 : https://github.com/mberwanger/s3-maven-example。 Kudos to Mr. Berwanger.

小結

利用 Amazon S3 作為 Maven 套件倉儲便可以運用 S3 所俱備的高可用 、 高擴充的儲存能力 , 再加上 CloudFront CDN 服務 , 不管在哪個地方都可以方便開發與部署 。 如果讓建構服務器 (build server) 跟 S3 位於同一個 Availability zone 還可以免除頻寬的費用 。