共用方式為


教學課程:在 Azure 容器應用程式中連線到適用於 Spring 的受控設定伺服器

適用於 Spring 的 Config Server 提供集中式位置,讓設定資料可供多個應用程式使用。 在本文中,您將了解如何將裝載在 Azure 容器應用程式中的應用程式連線到適用於 Spring 的 JAVA Config Server 執行個體。

適用於 Spring 的 Config Server JAVA 元件會使用 GitHub 存放庫作為組態設定的來源。 組態值可透過元件與容器應用程式之間的繫結提供給容器應用程式。 當組態伺服器中的值變更時,它們會自動流向您的應用程式,而不需要您重新編譯或重新部署應用程式。

在本教學課程中,您將了解:

  • 建立適用於 Spring 的 Config Server JAVA 元件
  • 將適用於 Spring 的 Config Server 繫結至您的容器應用程式
  • 觀察將 Config Server 連線到應用程式之前和之後的組態值
  • 使用對稱金鑰加密和解密組態值

重要

本教學課程所使用的服務,可能會影響您的 Azure 帳單。 如果您決定逐步執行操作,請務必刪除本文中介紹的資源,以免產生非預期的帳單。

必要條件

  • 具有有效訂用帳戶的 Azure 帳戶。 如果您還沒有帳戶,您可以 免費建立一個。
  • Azure CLI

考量

在 Azure 容器應用程式中執行適用於 Spring 的 Config Server 時,請注意下列詳細資料:

項目 說明
Scope 適用於 Spring 的 Config Server 會在與連線的容器應用程式相同的環境中執行。
調整大小 為了維護單一事實來源,適用於 Spring 的 Config Server 不會進行調整。 縮放屬性 minReplicasmaxReplicas 都會設定為 1
資源 適用於 Spring 的 Config Server 的容器資源配置是固定的,CPU 核心的數目是 0.5,而記憶體大小為 1Gi。
定價 適用於 Spring 的 Config Server 在計費上會低於使用量型定價。 受控 Java 元件所取用的資源會以使用/閒置費率計費。 您可以刪除不再使用的元件來停止計費。
繫結 容器應用程式會透過繫結連線到適用於 Spring 的 Config Server。 繫結會將設定插入到容器應用程式的環境變數中。 建立系結之後,容器應用程式可以從環境變數讀取組態值。

設定

在開始使用適用於 Spring 的 Config Server 之前,您必須先建立所需資源。

執行下列命令來建立您的資源群組和容器應用程式環境。

  1. 建立變數以支援您的應用程式設定。 這些值是針對本課程的目的而向您提供的。

    export LOCATION=eastus
    export RESOURCE_GROUP=my-services-resource-group
    export ENVIRONMENT=my-environment
    export JAVA_COMPONENT_NAME=configserver
    export APP_NAME=my-config-client
    export IMAGE="mcr.microsoft.com/javacomponents/samples/sample-service-config-client:latest"
    export URI="https://github.com/Azure-Samples/azure-spring-cloud-config-java-aca.git"
    
    變數 描述
    LOCATION 您在其中建立容器應用程式和 Java 元件的 Azure 區域位置。
    ENVIRONMENT 適用於您示範應用程式的 Azure 容器應用程式環境名稱。
    RESOURCE_GROUP 示範應用程式的 Azure 資源群組名稱。
    JAVA_COMPONENT_NAME 針對容器應用程式所建立 Java 元件的名稱。 在本案例中,您會建立適用於 Spring 的 Config Server JAVA 元件。
    IMAGE 容器應用程式中所使用的容器映像。
    URI 如果 URI 是私人的,您可以將 URI 取代為 Git 存放庫 URL,請新增相關的驗證組態,例如 spring.cloud.config.server.git.usernamespring.cloud.config.server.git.password
  2. 使用 Azure CLI 登入 Azure。

    az login
    
  3. 建立資源群組。

    az group create --name $RESOURCE_GROUP --location $LOCATION
    
  4. 建立您的容器應用程式環境。

    az containerapp env create \
        --name $ENVIRONMENT \
        --resource-group $RESOURCE_GROUP \
        --location $LOCATION
    

此環境可用來裝載適用於 Spring 的 Config Server JAVA 元件和容器應用程式。

建立適用於 Spring 的 Config Server JAVA 元件

現在您已擁有容器應用程式環境,您可以建立容器應用程式,並將其繫結至適用於 Spring 的 Config Server JAVA 元件。 當您繫結容器應用程式時,組態值會自動從 Config Server 元件同步至您的應用程式。

  1. 建立適用於 Spring 的 Config Server JAVA 元件。

    az containerapp env java-component config-server-for-spring create \
        --environment $ENVIRONMENT \
        --resource-group $RESOURCE_GROUP \
        --name $JAVA_COMPONENT_NAME \
        --min-replicas 1 \
        --max-replicas 1 \
        --configuration spring.cloud.config.server.git.uri=$URI
    
  2. 更新適用於 Spring 的 Config Server JAVA 元件。

    az containerapp env java-component config-server-for-spring update \
        --environment $ENVIRONMENT \
        --resource-group $RESOURCE_GROUP \
        --name $JAVA_COMPONENT_NAME \
        --min-replicas 2 \
        --max-replicas 2 \
        --configuration spring.cloud.config.server.git.uri=$URI spring.cloud.config.server.git.refresh-rate=60
    

    在這裡,您會告訴元件在哪裡尋找可透過 uri 屬性保存組態資訊的存放庫。 屬性 refresh-rate 會告知 Container Apps 檢查 Git 存放庫中是否有變更的頻率。

將容器應用程式繫結至適用於 Spring 的 Config Server JAVA 元件

  1. 建立取用組態資料的容器應用程式。

    az containerapp create \
        --name $APP_NAME \
        --resource-group $RESOURCE_GROUP \
        --environment $ENVIRONMENT \
        --image $IMAGE \
        --min-replicas 1 \
        --max-replicas 1 \
        --ingress external \
        --target-port 8080 \
        --query properties.configuration.ingress.fqdn
    

    此命令會傳回取用組態資料之容器應用程式的 URL。 將 URL 複製到文字編輯器,以便能用於後續步驟。

    如果您在瀏覽器中瀏覽您的應用程式,則傳回的 connectTimeout 值是 0 的預設值。

  2. 繫結至適用於 Spring 的 Config Server。

    現在已建立容器應用程式和 Config Server,您可以將它們與 update 命令繫結至容器應用程式。

    az containerapp update \
        --name $APP_NAME \
        --resource-group $RESOURCE_GROUP \
        --bind $JAVA_COMPONENT_NAME
    

    --bind $JAVA_COMPONENT_NAME 參數會建立容器應用程式與組態元件之間的連結。

容器應用程式和元件系結在一起之後,組態變更會自動同步處理至容器應用程式。

當您再次瀏覽應用程式的 URL 時,connectTimeout 的值現在是 10000。 此值來自原本設定為元件來源之變數中的 $URI Git 存放庫集。 具體而言,此值是從存放庫 application.yml 檔案中的 connectionTimeout 屬性繪製。

繫結要求會將組態設定插入應用程式作為環境變數。 從 Config Server 擷取組態設定時,應用程式程式碼現在可以使用這些值。

在此情況下,應用程式可以使用下列環境變數:

SPRING_CLOUD_CONFIG_URI=http://[JAVA_COMPONENT_INTERNAL_FQDN]:80
SPRING_CLOUD_CONFIG_COMPONENT_URI=http://[JAVA_COMPONENT_INTERNAL_FQDN]:80
SPRING_CONFIG_IMPORT=optional:configserver:$SPRING_CLOUD_CONFIG_URI

如果您要自訂自己的 SPRING_CONFIG_IMPORT,您可以參考環境變數 SPRING_CLOUD_CONFIG_COMPONENT_URI ,例如,您可以覆寫命令行自變數,例如 Java -Dspring.config.import=optional:configserver:${SPRING_CLOUD_CONFIG_COMPONENT_URI}?fail-fast=true

您也可以從應用程式中移除繫結。

(選用) 從適用於 Spring 的 Config Server JAVA 元件解除繫結您的容器應用程式

若要從容器應用程式中移除繫結,請使用 --unbind 選項。

az containerapp update \
    --name $APP_NAME \
    --unbind $JAVA_COMPONENT_NAME \
    --resource-group $RESOURCE_GROUP

當您再次瀏覽應用程式的 URL 時,connectTimeout 的值會變更回 0

清除資源

本教學課程中建立的資源會影響您的 Azure 帳單。 如果您不會長期使用這些服務,請執行下列命令來刪除本教學課程中建立的所有內容。

az group delete --resource-group $RESOURCE_GROUP

設定選項

az containerapp update命令會--configuration使用 參數來控制如何設定 Spring 的 Config Server。 只要多個參數是以空格分隔,就可以一次使用多個參數。 如需詳細資訊,請參閱 Spring Cloud Config Server

下表描述可用的不同 Git 後端組態值:

名稱 描述
spring.cloud.config.server.git.uri
spring.cloud.config.server.git.repos.{repoName}.uri
遠端存放庫的 URI。
spring.cloud.config.server.git.username
spring.cloud.config.server.git.repos.{repoName}.username
使用遠端存放庫進行驗證的用戶名稱。
spring.cloud.config.server.git.password
spring.cloud.config.server.git.repos.{repoName}.password
使用遠端存放庫進行驗證的密碼。
spring.cloud.config.server.git.search-paths
spring.cloud.config.server.git.repos.{repoName}.search-paths
搜尋要在本機工作複本中使用的路徑。 根據預設,只會搜尋根目錄。
spring.cloud.config.server.git.force-pull
spring.cloud.config.server.git.repos.{repoName}.force-pull
旗標,表示存放庫應該強制提取。 如果 true為 ,請捨棄任何本機變更,並從遠端存放庫取得。
spring.cloud.config.server.git.default-label
spring.cloud.config.server.git.repos.{repoName}.default-label
Git 所使用的預設標籤是 main。 如果您未設定 spring.cloud.config.server.git.default-label ,且名為 main 的分支不存在,則組態伺服器預設也會嘗試簽出名為 master 的分支。 如果您要停用後援分支行為,您可以將 設定 spring.cloud.config.server.git.tryMasterBranchfalse
spring.cloud.config.server.git.try-master-branch
spring.cloud.config.server.git.repos.{repoName}.try-master-branch
根據預設,組態伺服器會嘗試簽出名為 master 的分支。
spring.cloud.config.server.git.skip-ssl-validation
spring.cloud.config.server.git.repos.{repoName}.skip-ssl-validation
您可以將 屬性設定 git.skipSslValidationtrue,以停用組態伺服器對 Git 伺服器的 TLS/SSL 憑證驗證。
spring.cloud.config.server.git.clone-on-start
spring.cloud.config.server.git.repos.{repoName}.clone-on-start
旗標,表示應該在啟動時複製存放庫,而不是隨選複製。 通常會導致啟動速度較慢,但第一次查詢的速度較快。
spring.cloud.config.server.git.timeout
spring.cloud.config.server.git.repos.{repoName}.timeout
如果適用的話,取得 HTTP 或 SSH 連線的逾時,以秒為單位。 的預設值為 5 秒,
spring.cloud.config.server.git.refresh-rate
spring.cloud.config.server.git.repos.{repoName}.refresh-rate
設定伺服器從 Git 後端擷取更新的組態數據的頻率。
spring.cloud.config.server.git.private-key
spring.cloud.config.server.git.repos.{repoName}.private-key
有效的 SSH 私密鑰。 如果 ignore-local-ssh-settingstrue Git URI 為 SSH 格式,必須設定 。
spring.cloud.config.server.git.host-key
spring.cloud.config.server.git.repos.{repoName}.host-key
有效的 SSH 主機金鑰。 如果 host-key-algorithm 也已設定,則必須設定 。
spring.cloud.config.server.git.host-key-algorithm
spring.cloud.config.server.git.repos.{repoName}.host-key-algorithm
ssh-rsassh-ed25519ecdsa-sha2-nistp256ecdsa-sha2-nistp384ecdsa-sha2-nistp521ssh-dss其中一個。 如果 host-key 也已設定,則必須設定 。
spring.cloud.config.server.git.strict-host-key-checking
spring.cloud.config.server.git.repos.{repoName}.strict-host-key-checking
truefalse。 如果 false為,則忽略主機密鑰的錯誤。
spring.cloud.config.server.git.repos.{repoName} 遠端存放庫的 URI。
spring.cloud.config.server.git.repos.{repoName}.pattern 模式格式是具有通配符的名稱逗號分隔清單 {application}/{profile} 。 如果 {application}/{profile} 不符合任何模式,它會使用下定義的預設 URI。

下列清單描述常見的組態:

  • 記錄相關組態:

    • logging.level.*
    • logging.group.*
    • 命名空間下 logging.* 的任何其他設定都應該禁止 ,例如,應該禁止使用 logging.file 寫入記錄檔。
  • spring.cloud.config.server.overrides

    • 將屬性來源無條件傳送至所有客戶端的額外對應。
  • spring.cloud.config.override-none

    • 您可以將用戶端中所有覆寫的優先權變更為更像是預設值,讓應用程式在環境變數或系統屬性中提供自己的值,方法是在遠端存放庫中設定 spring.cloud.config.override-none=true 旗標 - 預設值為 false 。
  • spring.cloud.config.allow-override

    • 如果您啟用組態第一次啟動程式,您可以允許用戶端應用程式在來自組態伺服器的應用程式組態中放置兩個屬性,以覆寫組態伺服器的組態。
  • spring.cloud.config.server.health.*

    • 您可以設定健全狀況指標來檢查更多應用程式,以及自訂配置檔和自定義標籤。
  • spring.cloud.config.server.accept-empty

    • 您可以設定 spring.cloud.config.server.accept-emptyfalse ,讓伺服器在找不到應用程式時傳回 HTTP 404 狀態。 根據預設,此旗標會設定為 true
  • 加密和解密 (對稱):

    • encrypt.key
      • 當您使用對稱金鑰時很方便,因為它是要設定的單一屬性值。
    • spring.cloud.config.server.encrypt.enabled
      • 將此屬性設定為 false ,以停用伺服器端解密。

Refresh

取用屬性的服務在發生之前必須知道變更。 適用於 Spring 的 Config Server 的預設通知方法牽涉到手動觸發重新整理事件,例如透過呼叫 https://<YOUR_CONFIG_CLIENT_HOST_NAME>/actuator/refresh重新整理 ,如果有許多應用程式實例,則可能無法使用。

相反地,您可以讓設定客戶端根據重新整理內部輪詢變更,自動重新整理 Config Server 的值。 使用下列步驟,從 Config Server 自動重新整理值:

  1. 註冊排程的工作以在指定的間隔中重新整理內容,如下列範例所示:

    @Configuration
    @AutoConfigureAfter({RefreshAutoConfiguration.class, RefreshEndpointAutoConfiguration.class})
    @EnableScheduling
    public class ConfigClientAutoRefreshConfiguration implements SchedulingConfigurer {
        @Value("${spring.cloud.config.refresh-interval:60}")
        private long refreshInterval;
        @Value("${spring.cloud.config.auto-refresh:false}")
        private boolean autoRefresh;
        private final RefreshEndpoint refreshEndpoint;
        public ConfigClientAutoRefreshConfiguration(RefreshEndpoint refreshEndpoint) {
            this.refreshEndpoint = refreshEndpoint;
        }
        @Override
        public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
            if (autoRefresh) {
                // set minimal refresh interval to 5 seconds
                refreshInterval = Math.max(refreshInterval, 5);
                scheduledTaskRegistrar.addFixedRateTask(refreshEndpoint::refresh,  Duration.ofSeconds(refreshInterval));
            }
        }
    }
    
  2. 在application.yml檔案中啟用autorefresh並設定適當的重新整理間隔。 在下列範例中,用戶端每隔 60 秒輪詢一次組態變更,這是您可以針對重新整理間隔設定的最小值。

    根據預設, autorefresh 會設定為 false ,並將 refresh-interval 設定為 60 秒。

    spring:
        cloud:
            config:
            auto-refresh: true
            refresh-interval: 60
    management:
        endpoints:
            web:
            exposure:
                include:
                - refresh
    
  3. 在您的程式代碼中新增 @RefreshScope 。 在下列範例中,變數 connectTimeout 會每隔 60 秒自動重新整理一次:

    @RestController
    @RefreshScope
    public class HelloController {
        @Value("${timeout:4000}")
        private String connectTimeout;
    }
    

使用對稱金鑰進行加密和解密

伺服器端解密

根據預設,會啟用伺服器端加密。 使用下列步驟在應用程式中開啟解密:

  1. 在 Git 存放庫中的 .properties 檔案中新增加密的屬性。

    檔案應該類似下列範例:

    message={cipher}f43e3df3862ab196a4b367624a7d9b581e1c543610da353fbdd2477d60fb282f
    
  2. 更新 Spring Java 元件的設定伺服器,以使用具有加密屬性並設定加密金鑰的 Git 存放庫。

    執行下列命令之前,請以您的值取代以 <> 括住的預留位置。

    az containerapp env java-component config-server-for-spring update \
        --environment <ENVIRONMENT_NAME> \
        --resource-group <RESOURCE_GROUP> \
        --name <JAVA_COMPONENT_NAME> \
        --configuration spring.cloud.config.server.git.uri=<URI> encrypt.key=randomKey
    

用戶端解密

您可以遵循下列步驟,使用屬性的用戶端解密:

  1. 在 Git 存放庫中的 .properties 檔案中新增加密的屬性。

  2. 更新 Spring Java 元件的 Config Server,以使用具有加密屬性的 Git 存放庫,並停用伺服器端解密。

    執行下列命令之前,請以您的值取代以 <> 括住的預留位置。

    az containerapp env java-component config-server-for-spring update \
        --environment <ENVIRONMENT_NAME> \
        --resource-group <RESOURCE_GROUP> \
        --name <JAVA_COMPONENT_NAME> \
        --configuration spring.cloud.config.server.git.uri=<URI> spring.cloud.config.server.encrypt.enabled=false
    
  3. 在您的用戶端應用程式中,將解密金鑰 ENCRYPT_KEY=randomKey 新增為環境變數。

    或者,如果您在 上classpath包含 spring-cloud-starter-bootstrap ,或設定spring.cloud.bootstrap.enabled=true為系統屬性,請在 中bootstrap.properties設定 encrypt.key

    執行下列命令之前,請以您的值取代以 <> 括住的預留位置。

    az containerapp update \
        --name <APP_NAME> \
        --resource-group <RESOURCE_GROUP> \
        --set-env-vars "ENCRYPT_KEY=randomKey"
    
    encrypt:
      key: somerandomkey