アプリ構成のサポート
この記事では、Spring Cloud Azure App Configuration ライブラリについて説明します。 このライブラリは、Azure App Configuration サービスから構成と機能グラフを読み込みます。 ライブラリは、環境変数、コマンドライン構成、ローカル構成ファイルなどの Spring 環境がすでに生成した抽象化と一致する PropertySource
抽象化を生成します。
Spring は VMware によって開発されたオープンソースのアプリケーション フレームワークであり、Java アプリケーションを作成するための簡素化されたモジュール方式のアプローチを提供します。 Spring Cloud Azure は、Spring と Azure サービスのシームレスな統合を実現するオープンソース プロジェクトです。
前提条件
- Azure サブスクリプション - 無料アカウントを作成します。
- Java Development Kit (JDK) バージョン 8 以降。
- Apache Maven
- Azure CLI
App Configuration ストアを設定する
次のコマンドを使用して、Azure App Configuration ストアを作成します。
az appconfig create \
--resource-group <your-resource-group> \
--name <name-of-your-new-store> \
--sku Standard
このコマンドにより、新しい空の構成ストアが作成されます。 次のインポートコマンドを使用すると、構成をアップロードできます。
az appconfig kv import \
--name <name-of-your-new-store> \
--source file \
--path <location-of-your-properties-file> \
--format properties \
--prefix /application/
構成を読み込む前に確認します。 形式を YAML に変更することで、YAML ファイルをアップロードできます。 [プレフィックス] フィールドは、クライアント ライブラリによって読み込まれるデフォルトのプレフィックスであるため、重要です。
ライブラリの使用状況
アプリケーションでこの機能を使用するには、Spring Boot アプリケーションとしてビルドします。 依存関係を追加する最も便利な方法として、Spring Boot スターター com.azure.spring:spring-cloud-azure-starter-appconfiguration-config
の使用が挙げられます。 次の pom.xml ファイルの例では、Azure App Configuration を使用します。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>{spring-boot-version}</version>
<relativePath />
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-dependencies</artifactId>
<version>5.18.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-appconfiguration-config</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Note
Spring Boot 2.xを使用している場合は、 spring-cloud-azure-dependencies
バージョンを 4.19.0
に設定してください。
このBOMに使用されるバージョンの詳細については、「Spring Cloud Azureのどのバージョンを使うべきか」を参照してください。
次の例は、App Configuration を使用した基本的な Spring Boot アプリケーションを示しています。
@SpringBootApplication
@RestController
public class Application {
@RequestMapping("/")
public String home() {
return "Hello World!";
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
この例では、bootstrap.properties ファイルには次の行が含まれています。
spring.cloud.azure.appconfiguration.stores[0].connection-string=${CONFIG_STORE_CONNECTION_STRING}
CONFIG_STORE_CONNECTION_STRING
は、Azure App Configuration ストアへの接続文字列を含む環境変数です。 次のコマンドを使用すると、接続文字列にアクセスできます。
az appconfig credential list --name <name-of-your-store>
デフォルトでは、構成が設定されていない場合、Spring Profile が設定されていない限り、/application/
で開始される構成は、(No Label)
のデフォルト ラベルで読み込まれません。この場合、デフォルト ラベルは、Spring Profile です。 ストアが空であるため、構成は読み込まれませんが、Azure App Configuration Property Source は引き続き生成されます。
/application/https://<name-of-your-store>.azconfig.io/
という名前のプロパティ ソース作成され、これにはストアのプロパティが含まれます。 要求で使用されるラベルは、名前の末尾に追加されます。 ラベルが設定されていない場合、文字 \0
は空のスペースとして存在します。
構成の読み込み
ライブラリは、1 つまたは複数の App Configuration ストアの読み込みをサポートします。 キーが複数のストア間で重複している状況で、すべてのストアを読み込むと、最も優先度の高いストア構成が読み込まれます。 最後の 1 つが最優先となります。 このプロセスを次の例で説明します。
spring.cloud.azure.appconfiguration.stores[0].connection-string=[first-store-connection-string]
spring.cloud.azure.appconfiguration.stores[1].connection-string=[second-store-connection-string]
この例では、1 番目と 2 番目のストアの両方の構成が同じ場合、2 番目のストアの構成の優先度が最も高く、最後のストアが優先されます。
Note
その他 Spring 構成と同様に Azure App Configuration を使用できます。 詳細については、Spring Boot のドキュメントの「コア機能」または「クイック スタート: Azure App Configuration を使用して Java Spring アプリを作成する」を参照してください。
構成を選択する
構成は、キーとラベルによって読み込まれます。 デフォルトでは、キー /application/
で始まる構成が読み込まれます。 デフォルト ラベルは、${spring.profiles.active}
です。 ${spring.profiles.active}
が設定されていない場合は、null
ラベルが付いた構成が読み込まれます。 null
ラベルは、Azure Portal で (No Label)
のように表示されます。
次の例に示すように、異なるキーとラベル フィルターを選択して読み込まれた構成を構成できます。
spring.cloud.azure.appconfiguration.stores[0].selects[0].key-filter=[my-key]
spring.cloud.azure.appconfiguration.stores[0].selects[0].label-filter=[my-label]
key-filter
プロパティは、次のフィルターをサポートします。
キー フィルター | 結果 |
---|---|
* |
すべてのキーと一致します。 |
abc |
abc という名前のキーと一致します。 |
abc* |
abc で始まるキー名に一致します。 |
abc,xyz |
キー名 abc または xyz を一致させます。 カンマ区切りの値は 5 つまでに制限されます。 |
label-filter
プロパティは、次のフィルターをサポートします。
Label | 説明 |
---|---|
* |
\0 を含むすべてのラベルと一致します。 |
\0 |
Azure Portal で null のように表示される (No Label) ラベルと一致します。 |
1.0.0 |
厳密に 1.0.0 であるラベルに一致します。 |
1.0.* |
1.0.* で始まるラベルに一致させます。 |
,1.0.0 |
null と 1.0.0 ラベルと一致します。 カンマ区切りの値は 5 つまでに制限されます。 |
ラベル フィルターで YAML を使用していて、null
で開始する必要がある場合、ラベル フィルターを一重引用符で囲む必要があります。
spring:
cloud:
azure:
appconfiguration:
stores:
- selects:
- label-filter: ',1.0.0'
Note
フィルターで *
と ,
を組み合わせることはできません。 その場合は、追加の選択値を使用する必要があります。
Spring プロファイル
デフォルトでは、spring.profiles.active
は、すべての選択済み構成に対して、デフォルト label-filter
として設定されます。 label-filter
を使用するとこの機能をオーバーライドできます。 次の例に示すように、label-filter
を使用すると、${spring.profiles.active}
で Spring Profiles を使用できます。
spring.cloud.azure.appconfiguration.stores[0].selects[0].label-filter=,${spring.profiles.active}
spring.cloud.azure.appconfiguration.stores[0].selects[1].label-filter=${spring.profiles.active}_local
最初の label-filter
で、null
ラベル付きのすべての構成を読み込んだら、Spring Profiles と一致するすべての構成を読み込みます。 終的な構成であるため、Spring Profiles は、null
構成よりも優先されます。
2 つ目の label-filter
で、_local
文字列が Spring Profilesの最後に追加されますが、最後の Spring Profiles のみが追加されます。
無効なストア
構成 spring.cloud.azure.appconfiguration.enabled
を使用すると、すべての構成ストアの読み込みを無効化できます。 spring.cloud.azure.appconfiguration.stores[0].enabled
構成を使用すると、個々のストアを無効化できます。
ストアを無効にするだけでなく、読み込みに失敗した場合にストアを無効にするように構成することもできます。 この構成の場合は、spring.cloud.azure.appconfiguration.stores[0].fail-fast
を使用します。 fail-fast
に設定することで false
を無効化する際は、RuntimeException
は、アプリケーションの構成が読み込まれないまま、アプリケーション ストアが無効になります。 起動時に構成ストがが無効になっている場合は、更新時に変更が確認されません。 また、構成が更新された場合、そこから値の読み込みは試行されません。
更新確認中、または構成の再読み込み中に RuntimeException
が発生した場合、更新の試行は、終了し、refresh-interval
が渡された後に再試行されます。
認証
このライブラリでは、Azure Identity Library でサポートされているすべての形式の ID がサポートされています。 接続文字列とマネージド ID の構成を使用して認証を行うことができます。
接続文字列
接続文字列を使用した認証は、設定する最も簡単な形式です。 次のコマンドを使用すると、ストアの接続文字列にアクセスできます。
az appconfig credential list --name <name-of-your-store>
その後、spring.cloud.azure.appconfiguration.stores[0].connection-string
プロパティを接続文字列に設定できます。 ローカル構成ファイルの接続文字列を、環境変数にマップされるプレースホルダー値に設定することが強く推奨されます。 この方法では、ソース制御に接続文字列を追加しないようにすることができます。
Spring Cloud Azure の構成
Spring Cloud Azure 構成を使用すると、ライブラリを構成できます。 次のプロパティを使用するとライブラリを構成できます。
spring.cloud.azure.appconfiguration.stores[0].endpoint= <URI-of-your-configuration-store>
エンドポイントのみが設定されている場合、クライアント ライブラリは、DefaultAzureCredential を使用して認証を行います。 DefaultAzureCredential
は次の方法を使用して認証を行います。
- 環境資格情報
- マネージド ID 資格情報
- Azure Developer CLI 資格情報
- IntelliJ の資格情報
- Azure CLI の資格情報
- Azure PowerShell 資格情報
システム割り当て ID などの ID を読み取り構成に割り当てる必要があります。 次のコマンドを使用して、この割り当てを作成します。
az role assignment create \
--role "App Configuration Data Reader" \
--assignee <your-client-ID> \
--scope /subscriptions/<your-subscription>/resourceGroups/<your-stores-resource-group>/providers/Microsoft.AppConfiguration/configurationStores/<name-of-your-configuration-store>
Note
エンドポイントごとに定義できる認証方法は、接続文字列、ユーザー割り当て ID、トークン資格情報の 1 つだけです。 組み合わせる必要がある場合は、ConfigurationClientCustomizer
を使用して、別の方法を使用するストアを変更します。
geo レプリケーション
このライブラリでは、Azure App Configuration の [geo レプリケーション] 機能をサポートします この機能を使用すると、データを他の場所にレプリケートできます。 この機能は、高可用性と障害復旧に役立ちます。
作成する各レプリカには、専用エンドポイントがあります。 アプリケーションが複数の地理位置に存在する場合、それぞれの場所にデプロイされた各アプリケーションを更新して、その場所にできるだけ近いレプリカに接続するようにすれば、アプリケーションと App Configuration との間のネットワーク待ち時間を最小限に抑えることができます。 それぞれのレプリカに与えられる要求クォータは独立しているため、この設定は、複数リージョンに分散されたサービスとして拡大するアプリケーションのスケーラビリティにも寄与します。
ライブラリで次のいずれかの条件が観察された場合、フェールオーバーが発生する可能性があります。
- エンドポイントからサービス利用不可状態 (HTTP 500 以上) の応答を受信した。
- ネットワーク接続の問題が発生した。
- 要求がスロットルされた (HTTP 状態コード 429)。
geo レプリケーションを使用した構成ストアの作成
構成ストアのレプリカを作成するには、Azure CLI または Azure Portal を使用できます。 次の例では、Azure CLI を使用して、米国東部 2 リージョンにレプリカを作成します。
az appconfig replica create --location --name --store-name [--resource-group]
構成ストア レプリカの使用
レプリカを作成したら、それをアプリケーションで使用できます。 配信元ストアと同様に、Microsoft Entra ID または接続文字列を使用してレプリカに接続できます。
Microsoft Entra ID を使用してレプリカに接続するには、次の例に示すように、構成ストア インスタンスの endpoints
を一覧する必要があります。
spring.cloud.azure.appconfiguration.stores[0].endpoints[0]=[your primary store endpoint]
spring.cloud.azure.appconfiguration.stores[0].endpoints[1]=[your replica store endpoint]
レプリカがある限り多くのエンドポイントを一覧表示できます。 ライブラリは、表示されている順序でエンドポイントに接続します。 ライブラリがレプリカに接続できない場合は、リスト内の次のレプリカが試行されます。 一定期間が経過すると、ライブラリは優先エンドポイントへの再接続を試みます。
キーの値
Azure App Configuration では、複数の種類のキー値がサポートされており、その一部には特別な機能が組み込まれています。 Azure アプリ Configuration には、JSON コンテンツ タイプ、Spring プレースホルダー、および Key Vault 参照のサポートが組み込まれています。
プレースホルダー
ライブラリでは、${}
スタイルの環境プレースホールダーを使用した構成がサポートされています。 プレースホルダーを使用して Azure App Configuration キーを参照する場合は、参照からプレフィックスを削除します。 たとえば、/application/config.message
は ${config.message}
として参照されます。
Note
削除されるプレフィックスは値 spring.cloud.azure.appconfiguration.stores[0].selects[0].key-filter
と一致します。
JSON
コンテンツ タイプ application/json
を持つ構成は、JSON オブジェクトとして処理されます。 この機能を使用すると、1 つの構成を、@ConfigurationProperties
内の複雑なオブジェクトにマッピングできます。 たとえば、次の値を持つ JSON キー /application/config.colors
を考察していきます。
{
"Red": {
"value": [255, 0, 0]
},
"Blue": {
"value": [0, 255, 0]
},
"Green": {
"value": [0, 0, 255]
}
}
このキーは、次のコードにマップされます。
@ConfigurationProperties(prefix = "config")
public class MyConfigurations {
private Map<String, Color> colors;
}
Key Vault の参照
Azure App Configuration とそのライブラリは、Key Vault に格納されているシークレットの参照をサポートします。 App Configurationでは、Key Vault に格納されているシークレットにマップされる値を持つキーを作成できます。 シークレットは Key Vault に安全に格納されますが、読み込まれた後は他の構成と同じ方法でアクセスできます。
App Configuration に格納されているその他のキーの場合と同様、お使いのアプリケーションは、クライアント プロバイダーを使用して Key Vault 参照を取得します。 クライアントはキーを Key Vault 参照として認識するため、一意のコンテンツ タイプを持ち、クライアントは Key Vault に接続して値を取得します。
Note
Key Vault ではシークレットを一度に 1 つしか取得できないため、App Configuration に格納されている各 Key Vault 参照は、Key Vault に対してプルされます。
Key Vault 参照の作成
Azure Portal の Key Vault 参照を作成するには、[構成エクスプローラー]> > [作成]> > [Key Vault 参照] の順に選択します。 その後、アクセス権を持つ任意の Key Vault から参照するシークレットを選択します。 [入力] タブから任意の Key Vault 参照を作成することもできます。Azure Portal で、有効な URI を入力します。
次のコマンドを使用して、Azure CLI 経由で Key Vault 参照を作成することもできます。
az appconfig kv set-keyvault \
--name <name-of-your-store> \
--key <key-name> \
--secret-identifier <URI-to-your-secret>
Azure CLI 経由で任意のシークレット識別子を作成できます。 シークレット識別子には、バージョン セクションがオプションの形式 {vault}/{collection}/{name}/{version?}
が必要です。
Key Vault 参照の使用
Spring Cloud Azure 構成を使用すると、ライブラリを構成できます。 App Configuration に接続して Azure Key Vault に接続する場合と同じ資格情報を使用できます。
Key Vault 以外のシークレットを解決する
App Configuration ライブラリには、Key Vault が関連付けられていないシークレットをローカルで解決するメソッドが用意されています。 この解決策は、KeyVaultSecretProvider
を介して完了します。 KeyVaultSecretProvider
が Key Vault 参照を提供しない場合は、TokenCredential
が呼び出されます。 Key Vault 参照の URI が指定され、返された値がシークレットの値になります。
警告
KeyVaultSecretProvider
を使用すると、システムが割り当てたマネージド ID の使用がオーバーライドされます。 両方を使用する場合は、KeyVaultCredentialProvider
を使用して、解決する URI の null
を返します。
public class MySecretProvider implements KeyVaultSecretProvider {
@Override
public String getSecret(String uri) {
...
}
}
機能の管理
機能管理は、Spring Boot アプリケーションがコンテンツに動的にアクセスする方法を提供します。 機能管理には、次のようなさまざまな機能があります。
- コンテンツを有効または無効にできる機能フラグ
- コンテンツが表示されたときにターゲットを設定するための機能フィルター
- カスタマイズされた機能フィルター
- エンドポイントを動的に有効にする機能ゲート
機能フラグを有効にするには、次の構成を使用します。
spring.cloud.azure.appconfiguration.stores[0].feature-flags.enabled= true
有効な機能フラグは、プレフィックス feature-management
を使用して Spring 構成システムに読み込まれます。 機能フラグは、ローカル構成ファイルに登録することもできます。 詳細については、「機能フラグ宣言」セクションを参照してください。
機能管理を使用する最も簡単な方法として、spring-cloud-azure-feature-management
と spring-cloud-azure-feature-management-web
ライブラリの使用が挙げられます。 2 つのライブラリの違いは、spring-cloud-azure-feature-management-web
は、spring-web
と spring-webmvc
の依存関係を使用して、 機能ゲートなどの機能をさらに追加します。
キー/ラベル フィルターを使用して機能フラグを有効にすることができます。 デフォルトでは、null
と表示されている (No Label)
ラベルが割り当てられます。 次の例に示すように、ラベル フィルターを設定することで、読み込まれる機能フラグを構成できます。
spring.cloud.azure.appconfiguration.stores[0].feature-flags.selects[0].key-filter=A*
spring.cloud.azure.appconfiguration.stores[0].feature-flags.selects[0].label-filter= dev
機能管理の基本
機能フラグ
機能フラグは、名マネと機能をオンにするために使用する機能フィルターの一覧の 2 つで構成されています。 機能フラグは、オン/オフのブール状態を持つか、機能フィルターの一覧を持つことができます。 機能フラグは、true
が返されるまで、機能フィルターを評価します。 機能フィルターが true
を返さない場合は、機能フィルターは false
を返します。
機能フィルター
機能フィルターは、機能を有効にする必要があるシナリオを定義します。 機能フィルターは同期的に評価されます。
機能管理ライブラリには、AlwaysOnFilter、PercentageFilter、TimeWindowFilter および TargetingFilter の 4 つの事前定義されたフィルターがあります。
カスタム機能フィルターを作成できます。 たとえば、機能フィルターを使用して、Microsoft Edge ブラウザーを使用しているお客様にカスタム エクスペリエンスを提供できます。 たとえば、この機能フィルターの機能をカスタマイズして、Microsoft Edge ブラウザーの対象ユーザーの特定のヘッダーを表示できます。
機能フラグの宣言
機能管理ライブラリは、機能フラグのソースとして application.yml または bootstrap.yml がある Azure App Configuration をサポートします。 application.yml ファイルで機能フラグを設定するために使用される形式の例を次に示します。
feature-management:
feature-t: false
feature-u:
enabled-for:
- name: Random
feature-v:
enabled-for:
- name: TimeWindowFilter
parameters:
Start: "Wed, 01 May 2019 13:59:59 GMT"
End: "Mon, 01 July 2019 00:00:00 GMT"
feature-w:
evaluate: false
enabled-for:
- name: AlwaysOnFilter
この例には、次の機能フラグがあります。
feature-t
がfalse
に設定されます。 この設定は、常に機能フラグの値を返します。feature-u
は、機能フィルターと共に使用されます。 これらのフィルターは、enabled-for
プロパティで定義されます。 この場合、feature-u
には、Random
と呼ばれる機能フィルターが 1 つあり、これには、構成は不要なため、名前プロパティのみが必要です。feature-v
は、TimeWindowFilter
という名前の機能フィルターを指定します。 この機能フィルターは、構成として使用するパラメーターに渡されます。 この例では、TimeWindowFilter
がその機能が有効な開始時刻と終了時刻を渡します。feature-w
は、AlwaysOnFilter
に対して使用され、常にtrue
を評価します。evaluate
フィールドは、機能フィルターの評価を停止するために使用され、結果として機能フィルターは常にfalse
を返します。
機能フラグの評価
spring-cloud-azure-feature-management
ライブラリは、FeatureManager
を提供して機能フラグを有効にするかどうかを判断します。 FeatureManager
は、フラグの状態をチェックする非同期の方法を提供します。
spring-cloud-azure-feature-management-web
と一緒に提供される FeatureManager
は、FeatureManagerSnapshot
を含みます。これは、@RequestScope
で以前評価した機能フラグの状態をキャッシュして、すべての要求が同じ値を返すことを保証します。 さらに、Web ライブラリは、@FeatureGate
を提供します。これは、異なるエンドポイントをブロックするか、Web 要求を異なるエンドポイントにリダイレクトします。
機能フラグのチェック
FeatureManager
は、@Bean
または、@Autowired
型オブジェクトに挿入できる @Component
です。 FeatureManager
には、機能フラグの名前を渡すと、その状態を返す isEnabled
メソッドがあります。
@Autowired
FeatureManager featureManager;
if (featureManager.isEnabled("feature-t")) {
// Do Something
}
Note
FeatureManger
には、isEnabled
と呼ばれる isEnabledAsync
の非同期バージョンがあります。
機能管理を構成していない場合、または機能フラグが存在しない場合は、isEnabled
は常に false
を返します。 既存の機能フラグが不明な機能フィルターで構成されている場合、FilterNotFoundException
がスローされます。 false
を fail-fast
に構成することで、false
を返すようにこの動作を変更できます。 次の表では、fail-fast
について説明します。
名前 | 説明 | 必要 | Default |
---|---|---|---|
spring.cloud.azure.feature.management.fail-fast |
例外が発生すると、RuntimeException がスローされます。 このプロパティが false に設定されている場合は、isEnabled は代わりに、false を返します。 |
いいえ | true |
FeatureManagerSnapshot
と FeatureManager
の唯一の違いは、@RequestScope
の結果となるキャッシュです。
機能ゲート
機能管理 Web ライブラリを使用すると、エンドポイントを実行するために特定の機能を有効にするよう求められます。 次の例に示すように、@FeatureGate
注釈を使用すると、この要件を設定できます。
@GetMapping("/featureT")
@FeatureGate(feature = "feature-t")
@ResponseBody
public String featureT() {
...
}
[feature-t] が有効な場合、featureT
エンドポイントのみにアクセスできます。
無効なアクション処理
指定した機能が無効になっているためにエンドポイントがブロックされると、DisabledFeaturesHandler
が呼び出されます。 既定では、HTTP 404 が返されます。 この動作は、次の例に示すように DisabledFeaturesHandler
を実装することでこの動作をオーバーライドできます。
@Component
public class MyDisabledFeaturesHandler implements DisabledFeaturesHandler {
@Override
public HttpServletResponse handleDisabledFeatures(HttpServletRequest request, HttpServletResponse response) {
...
return response;
}
}
ルーティング
特定のルートでは、機能によって制御されるアプリケーション機能が公開される場合があります。 機能が無効になっている場合は、次の例に示すように、これらのルートを別のエンドポイントにリダイレクトできます。
@GetMapping("/featureT")
@FeatureGate(feature = "feature-t" fallback= "/oldEndpoint")
@ResponseBody
public String featureT() {
...
}
@GetMapping("/oldEndpoint")
@ResponseBody
public String oldEndpoint() {
...
}
組み込み機能フィルター
spring-cloud-azure-feature-management
パッケージに付属する新しい機能フィルターがいくつかあります。 これらの機能フィルターは自動的に追加されませんが、@Configuration
で設定できます。
AlwaysOnFilter
このフィルターは常に true
を返します。 使用例については、「機能フラグ宣言」セクションを参照してください。
PercentageFilter
ユーザーが要求を行うたびにPercentageFilter
の評価は、異なる結果として返されます。 この不整合は、FeatureManagementSnapshot
を使用して、回避できます。これは、ユーザー別機能フラグの結果をキャッシュします。 この機能により、ユーザーが要求を再送信する必要がある場合でも、一貫したエクスペリエンスが確保されます。
feature-management:
feature-v:
enabled-for:
- name: PercentageFilter
parameters:
Value: 50
TimeWindowFilter
このフィルターは、時間枠に基づいて機能を有効にする機能を提供します。 End
を指定した場合のみ、その時点まで機能がオンと見なされます。 指定した場合のみ Start
、その時点以降のすべてのポイントで機能がオンと見なされます。 両方を指定した場合、この機能は 2 回の間に有効と見なされます。
feature-management:
feature-v:
enabled-for:
- name: TimeWindowFilter
parameters:
Start: "Wed, 01 May 2019 13:59:59 GMT",
End: "Mon, 01 July 2019 00:00:00 GMT"
TargetingFilter
このフィルターは、対象ユーザーに対して機能を有効にする機能を提供します。 ターゲットの詳細な説明については、「ターゲット」セクションを参照してください。 フィルター パラメーターには、ユーザー、グループ、および機能にアクセスできるユーザー ベースのデフォルトの割合を説明する対象ユーザー オブジェクトが含まれます。 対象ユーザーに記載されているグループオブジェクトごとに、その機能にアクセスできるグループのメンバーの割合を定義する割合が必要です。 ユーザーは、次の場合にこの機能を有効にします。
- ユーザーは、ユーザーのセクションで直接指定されます。
- ユーザーは、グループのロールアウトに含まれる割合に含まれています。
- ユーザーは、デフォルトのロールアウト率に分類されます。
feature-management:
target:
enabled-for:
- name: targetingFilter
parameters:
users:
- Jeff
- Alicia
groups:
- name: Ring0
rollout-percentage: 100
- name: Ring1
rolloutPercentage: 100
default-rollout-percentage: 50
カスタム機能フィルター
カスタム機能フィルターを作成すると、定義した条件に基づいて機能を有効にすることができます。 カスタム機能フィルターを作成するには、FeatureFilter
インターフェイスを実装する必要があります。 FeatureFilter
には メソッド evaluate
が 1 つあります。 機能フィルターを使用して機能を有効にできることを指定すると、evaluate
メソッドが呼び出されます。 evaluate
が true
を返した場合、その機能を有効にする必要があります。 false
が返された場合は、true
が返されるまで機能フィルターを評価し続けます。 すべてのフィルターが false
を返したら、機能をオフにします。
機能フィルターは、Spring Beans として定義され、@Component
として定義されるか、@Configuration
で定義します。
@Component("Random")
public class Random implements FeatureFilter {
@Override
public boolean evaluate(FeatureFilterEvaluationContext context) {
double chance = Double.valueOf((String) context.getParameters().get("chance"));
return Math.random() > chance / 100;
}
}
パラメーター化機能フィルター
一部の機能フィルターでは、機能を有効にする必要があるかどうかを判断するためにパラメーターが必要です。 たとえば、ブラウザー機能フィルターでは、特定のブラウザー セットの機能を有効にすることができます。 Microsoft Edge ブラウザーと Chrome ブラウザーで機能を有効にできますが、Firefox では有効にできません。 この状況を設定するには、パラメーターを想定するように機能フィルターを設計します。 これらのパラメーターは、機能構成とコードで指定され、FeatureFilterEvaluationContext
の evaluate
パラメーターを介してアクセスできます。 FeatureFilterEvaluationContext
には、parameters
という HashMap<String, Object>
プロパティがあります。
ターゲティング
対象設定は、開発者が新しい機能をユーザー ベースに段階的にロールアウトできるようにする機能管理戦略です。 この戦略は、対象ユーザーと呼ばれる一連のユーザーをターゲットにする概念に基づいて構築されています。 対象ユーザーは、特定のユーザー、グループ、およびユーザー ベース全体の指定された割合で構成されます。 対象ユーザーに含まれるグループは、メンバーの合計数に対する割合にさらに分けることができます。
次の手順は、新しい「ベータ」機能の段階的なロールアウトの例を示しています。
- 個人ユーザーのジェフとアリシアには、ベータ版へのアクセスが付与されています。
- 別のユーザーであるマークは、オプトイン要求をして、含まれました。
- 「Ring1」ユーザーと呼ばれるグループの 20% がベータ版に含まれています。
- ベータ版に含まれる「Ring1」ユーザーの数は、最大 100% 増加します。
- ユーザー ベースの 5% がベータに含まれています。
- ロールアウト率は最大 100% まで増加し、機能は完全にロールアウトされます。
機能をロールアウトする戦略は、含まれている TargetingFilter
機能フィルターを介して、ライブラリでビルドされます。
アプリケーションでのターゲット設定
ターゲット機能フィルターを使用する Web アプリケーションの例は、プロジェクト例に記載されています。
アプリケーションで TargetingFilter
の使用を開始するには、その他機能フィルターのように @Bean
として追加する必要があります。 TargetingFilter
は、アプリケーション @Bean
に追加される別の TargetingContextAccessor
に依存します。 次の例に示すように、TargetingContextAccessor
は、現在のユーザー ID とグループの定義に使用される現在の TargetingContext
の定義を許可します。
public class MyTargetingContextAccessor implements TargetingContextAccessor {
@Override
public void getContextAsync(TargetingContext context) {
context.setUserId("Jeff");
ArrayList<String> groups = new ArrayList<String>();
groups.add("Ring0");
context.setGroups(groups);
}
}
ターゲットの評価オプション
オプションは、指定の TargetingFilter
でターゲット設定評価がどのように実行されるかをカスタマイズするために使用します。 TargetingEvaluationOptions
作成中に、オプションのパラメータ TargetingFilter
を設定できます。
@Bean
public TargetingFilter targetingFilter(MyTargetingContextAccessor contextAccessor) {
return new TargetingFilter(contextAccessor, new TargetingEvaluationOptions().setIgnoreCase(true));
}
構成の更新
構成の構成更新を有効にすると、アプリケーションを再起動しなくても、App Configuration ストアまたは複数のストアから最新の値をプルできます。
更新を有効にするには、監視トリガーと共に監視を有効にする必要があります。 監視トリガーは、更新をトリガーするために値の変更を確認するオプションのラベルが付けられたキーです。 更新が必要になったときに変更される限り、監視トリガーの値には任意の値を指定できます。
Note
監視トリガーの ETag を変更する操作は、コンテンツ タイプの変更などの更新を引き起こします。
spring:
cloud:
azure:
appconfiguration:
stores:
- monitoring:
enabled: true
triggers:
- key: [my-watched-key]
label: [my-watched-label]
構成の更新をトリガーするには、構成ストアのキーの値を変更します。 次に、いずれかのウォッチ キーを新しい値に更新します。 この変更により、ログの作成がトリガーされます。 たとえば、/application/config.message
トリガーの値を変更すると、次のログ メッセージが表示されます。
INFO 17496 --- [TaskScheduler-1] o.s.c.e.event.RefreshEventListener : Refresh keys changed: [config.message]
アプリケーションはログを生成した後、更新スコープ内のすべての @Bean
を更新します。
Note
デフォルトでは、@ConfigurationProperties
注釈付きBeans は、このスコープに含まれます。
プルベースの更新
App Configuration Spring ライブラリは、監視トリガーに加えられた変更の更新間隔で定期的にチェックする機能をサポートしています。 デフォルトの更新間隔は、30 秒です。 更新間隔が経過すると、すべてのトリガーが変更のために指定されたストアでチェックされます。 キーを変更すると、更新がトリガーされます。 ライブラリは Spring 更新システムと統合されるため、更新を行うと、すべてのストアのすべての構成が再読み込みされます。 更新間隔は、1 秒より長い任意の間隔に設定できます。 更新間隔でサポートされる単位は、s
、m
、h
、d
で、それぞれ、秒、分、時間、日です。 次の例では、間隔を 5 分に設定しています。
spring.cloud.azure.appconfiguration.stores[0].monitoring.refresh-interval= 5m
自動
spring-cloud-azure-appconfiguration-config-web
ライブラリを使用する際、サーブレット要求 (具体的には、ServletRequestHandledEvent
) が発生するたびに、アプリケーションは、更新を自動チェックします。 このイベントが送信される最も一般的な方法は、@RestController
のエンドポイントへの要求です。
手動
コンソール アプリケーションとして、spring-cloud-azure-appconfiguration-config
のみを使用するアプリケーションでは、AppConfigurationRefresh
の refreshConfiguration
メソッドを呼び出すことで更新を手動でトリガーできます。 AppConfigurationRefresh
は、任意の @Bean
に居んジェクトできる @Component
です。
また、ライブラリが Spring の構成システムを使用するため、更新をトリガーすると、Azure App Configuration ストアからの構成だけではなくすべての構成が更新されます。
プッシュベースの更新
Azure App Configuration ストアから、プッシュ通知を受信するように spring-cloud-azure-appconfiguration-config-web
ライブラリを設定すると、構成値が更新されます。 この構成は、Azure Event Grid Web Hook を使用して設定できます。これは、指定されたキーに変更の通知を送信するように構成できます。 Spring Actuator ライブラリを依存関係として追加することで、App Configuration の更新エンドポイントを公開できます。 エンドポイントには、appconfiguration-refresh
と appconfiguration-refresh-bus
があります。 これらのエンドポイントは、カウンターパート refresh
と refresh-bus
のように機能します。ここでは、アプリ構成エンドポイントは、受信時に強制的に構成するのではなく、更新間隔を期限切れにします。 refresh
と refresh-bus
は引き続き使用できますが、設定で応答が必要なため、Web Hook を使用して Azure Event Grid に直接接続できません。
appconfiguration-refresh
プロパティは、更新間隔の有効期限を切ることで、次の更新チェック前に、残りの更新間隔は待機されません。 appconfiguration-refresh-bus
プロパティは、Azure Service Bus などの接続されたメッセージ サービスに通知を送信し、アプリケーションのすべてのインスタンスに通知して更新します。 どちらの場合も、更新間隔で完全に期限切れになるわけではありませんが、少量のジッターによって、オフになります。 このジッターにより、アプリケーションのすべてのインスタンスが同時更新されないようになります。
management.endpoints.web.exposure.include= appconfiguration-refresh, appconfiguration-refresh-bus
更新エンドポイントを公開するだけでなく、セキュリティに必要なクエリ パラメーターが追加されました。 デフォルトではトークン名または値は設定されませんが、次の例に示すように、エンドポイントを使用するにはトークン名または値のいずれかを設定する必要があります。
spring.cloud.azure.appconfiguration.stores[0].monitoring.push-notification.primary-token.name=[primary-token-name]
spring.cloud.azure.appconfiguration.stores[0].monitoring.push-notification.primary-token.secret=[primary-token-secret]
spring.cloud.azure.appconfiguration.stores[0].monitoring.push-notification.secondary-token.name=[secondary-token-name]
spring.cloud.azure.appconfiguration.stores[0].monitoring.push-notification.secondary-token.secret=[secondary-token-secret]
Web Hook の設定
Web Hook を設定するには、Azure App Configuration ストアを開き、[ナビゲーション] メニューで、[イベント] を開きます。 その後、[イベント サブスクリプション] を選択します。 イベントの名前を設定し、Web Hook となるエンドポイントの種類を選択します。 Web Hook を選択すると、[エンドポイント] オプションが表示されます。 [エンドポイントの選択] を選択します。 エンドポイントは https://www.myaplication.com/actuator/appconfiguration-refresh?myTokenName=mySecret
のようになります。
[選択を確認] は、特定の URI にセットアップ通知を送信し、そこから応用が送信されることを想定します。 応答が返されない場合、セットアップは失敗します。 Azure App Configuration ストアがアプリケーションに構成されている場合、エンドポイントに設定された azure-spring-cloud-appconfiguration-web
ライブラリは、正しい応答を返します。 この確認は、他の方法で送信できます。 Web Hook 配信の詳細については、「Web Hookイベント配信」を参照してください。
Note
この検証は、エンドポイントの作成または変更時にのみ行われます。
それ以外の場合は、キーの作成と変更のたびに更新がトリガーされるため、フィルターを設定することが強く推奨されます。
クライアントの強制更新
すべての構成を更新間隔に基づき、強制的に更新するようにライブラリを構成できます。 次の表は、refresh-interval
プロパティについての説明です。
名前 | 説明 | 必要 | Default |
---|---|---|---|
spring.cloud.azure.appconfiguration.refresh-interval |
更新中の標準時間。 Duration か。 |
いいえ | null |
spring.cloud.azure.appconfiguration.refresh-interval
で更新すると、構成済みウォッチ キーはチェックされません。 Azure App Configuration は、更新タイミングを判断できないため、このプロパティを使用して、Key Vault シークレットを最新の状態に保ちます。
Azure Key Vault は、シークレットとして、認定資格証の公開キーとプライベート キーの組み合わせを保管するため、アプリケーションは、App Configuration で Key Vault 参照として、認定資格証を取得します。 認定資格証は定期的にローテーションする必要があるため、クライアント アプリケーションもクライアント更新間隔に基づいて頻繁に更新する必要があります。
機能フラグの更新
機能フラグと監視の両方が有効になっている場合、機能フラグの更新間隔のデフォルト値は 30 秒に設定されます。 更新間隔が経過すると、指定ストア内のすべての機能フラグの変更が確認されます。 キーを変更すると、更新がトリガーされます。 ライブラリは Spring 更新システムと統合されるため、更新を行うと、すべてのストアのすべての構成が再読み込みされます。 更新間隔は、1 秒より長い任意の間隔に設定できます。 更新間隔でサポートされる単位は、s
、m
、h
、d
で、それぞれ、秒、分、時間、日です。 次の例では、間隔を 5 分に設定しています。
spring.cloud.azure.appconfiguration.stores[0].monitoring.feature-flag-refresh-interval= 5m
正常性インジケーター
クライアント ライブラリには、Azure App Configuration ストアまたは複数のストアへの接続が正常かどうかを確認する正常性インジケーターがあります。 ストアごとに有効にすると、次のいずれかの状態値が表示されます。
- UP - 最後の接続が正常に行われました。
- DOWN- 最後の接続の結果、200 以外のエラー コードが発生しました。 この状態は、資格情報の期限切れからサービスの問題までの問題が原因である可能性があります。 クライアント ライブラリは、次回の更新間隔でストアへの接続を自動的に再試行します。
- NOT LOADED - 構成ストアはローカル構成ファイルに一覧表示されますが、起動時に構成ストアがファイルから読み込まれていませんでした。 構成ストアが構成ファイルで無効になっているか、
fail-fast
ストアの構成がfalse
に設定されている間、起動時に 1 つの構成または複数の構成を読み込めませんでした。
management.health.azure-app-configuration.enabled=true
に設定すると、正常性インジケーターを有効化できます。
クライアントのカスタマイズ
App Configuration ライブラリは、Azure App Configuration と Azure Key Vault を接続するために、Azure SDK for Java を使用します。 クライアントを変更するために、ConfigurationClientCustomizer
と SecretClientCustomizer
の 2 つのインターフェイスが提供されます。 各インターフェイスには、customize
メソッドがあります。次のインターフェイス定義で示されているように、これは、各ビルダーとクライアントが構成する URI の String
値を受け取ります。?
public interface ConfigurationClientCustomizer {
public void setup(ConfigurationClientBuilder builder, String endpoint);
}
public interface SecretClientCustomizer {
public void setup(SecretClientBuilder builder, String endpoint);
}
これらのインターフェイスを使用すると、HTTP クライアントとその構成をカスタマイズできます。 次の例では、既定値 HttpClient
を、App Configuration と Key Vault に送信されるすべてのトラフィックにプロキシを使用する別のものに置き換えます。
Note
ConfigurationClientBuilder
に渡す際は、SecretClientBuilder
と customize
が既に使用用に設定されています。 資格情報や再試行ポリシーなど、クライアントに対する変更は、既に設定されている変更よりも優先されます。
Spring Cloud Azure 構成を使用しても、この構成を実行できます。
public class CustomClient implements ConfigurationClientCustomizer, SecretClientCustomizer {
@Override
public void customize(ConfigurationClientBuilder builder, String endpoint) {
builder.httpClient(buildHttpClient());
}
@Override
public void customize(SecretClientBuilder builder, String endpoint) {
builder.httpClient(buildHttpClient());
}
private HttpClient buildHttpClient() {
String hostname = System.getProperty("https.proxyHosts");
String portString = System.getProperty("https.proxyPort");
int port = Integer.valueOf(portString);
ProxyOptions proxyOptions = new ProxyOptions(ProxyOptions.Type.HTTP,
new InetSocketAddress(hostname, port));
return new NettyAsyncHttpClientBuilder()
.proxy(proxyOptions)
.build();
}
}