本記事はこちらのブログを参考にしています。
翻訳にはアリババクラウドのModelStudio(Qwen)を使用しております。
Spring Cloud アプリケーションにおける Nacos の動的設定リフレッシュのベストプラクティス
Zunfei Liu 作成
はじめに
Spring Cloud アプリケーションでは、Nacos を非常に低いコストで統合して、動的な設定リフレッシュを実現できます。アプリケーションコード内では、公式の Spring アノテーションである @Value
と @ConfigurationProperties
を使用して、Spring 環境コンテキスト内のプロパティ値を参照できます。これに関する詳細情報は、Best Practices for Dynamic Configuration with Spring Cloud, Nacos, and KMS という記事をご覧ください。
この方法の最大の利点は、コードレベルでの非侵襲性です。しかし、多くの制限もあります。例えば:
-
プロパティソースの競合: Nacos の設定は、Spring コンテキスト環境のプロパティソースの1つとして機能します。プロパティを取得する際、JVM パラメータや環境変数を通じて注入されたプロパティが、Nacos よりも優先される場合があります。
-
同一キーの問題: 複数の Nacos 設定を
spring.config.import
を介してインポートした場合、同じキーが存在すると、そのうちの1つしか有効になりません。複数のプロパティソース間でキーの重複がないことを確認するか、優先順位によるプロパティの上書き問題に対処する必要があります。 -
オブジェクト型フィールドへの自動インジェクションの欠如: Nacos の設定はオブジェクト型のフィールドには自動的にインジェクトされません。
-
受動的な設定変更: 設定の変更は受動的にしか受け取れず、設定変更時に二次処理を行うサポートや、他のビジネスアクションをトリガーする手段はありません。また、プロパティ変更前後の詳細な情報を把握することもできません。
-
@RefreshScope の必要性:
@Value
アノテーションによって参照される設定に対して動的リフレッシュをサポートするには、SpringBean に@RefreshScope
を追加する必要があります。設定更新時には、まず Bean が破棄され、その後新しいものが再作成されます。適切に使用しないと、これが生産環境で問題を引き起こす可能性があります。
これらの問題を解決し、アプリケーションが Nacos 設定センターにアクセスしやすくするために、Spring Cloud Alibaba は Nacos 設定センター用の新しいアノテーションセットをリリースしました。
-
@NacosConfig: SpringBean のフィールドに適用すると、このアノテーションは指定された Nacos 設定をフィールドにインジェクトします。SpringBean クラスに適用すると、指定された Nacos 設定を Bean のプロパティにインジェクトします。FactoryBean メソッドに適用すると、指定された Nacos 設定を Bean のプロパティにインジェクトします。これは
@RefreshScope
アノテーションに依存せずに有効になります。 -
@NacosConfigListener: このアノテーションは SpringBean 内のメソッドに使用され、Nacos の設定変更後に最新の設定内容を受け取ります。結果はオブジェクト型として受け取ることも可能です。
-
@NacosConfigKeysListener: このアノテーションも SpringBean 内のメソッドに使用されます。Nacos 設定内の指定されたプロパティキー集合が変更された場合、変更前後のプロパティ値を含む
ConfigChangeEvent
をメソッドパラメータとして受け取ります。
以下では、3つのアノテーションの使い方について詳しく説明します。
@NacosConfig アノテーションの概要と使用法
@NacosConfig
アノテーションを使用すると、指定された Nacos 設定を SpringBean のフィールドにインジェクトできます。このアノテーションは、SpringBean の単一フィールド、または SpringBean 自体(BeanClass にアノテーションを追加し、FactoryBean インジェクションモードと組み合わせる場合を含む)に適用できます。インジェクト対象のタイプは、基本型、プロパティ、および List<T>
、Set<T>
、Map<T>
などのコレクションや、任意のカスタム Java Beans をサポートします。設定形式が YAML またはプロパティの場合、特定のキー名を指定して、そのキーに対応するプロパティ値を読み込むこともできます。
アノテーションフィールドの説明java
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
@Documented
public @interface NacosConfig {
String group();
String dataId();
String key() default "";
String defaultValue() default "";
}
- group: 導入する設定が属するグループ。
- dataId: 導入する設定の DataId。
- key: 設定形式が YAML またはプロパティの場合、特定のキー名を指定して、そのキーに対応するプロパティ値を読み込むことができます。
- defaultValue: 設定が存在しない場合、または指定されたキーのプロパティが空の場合にロードされるデフォルト値。
Nacos にアクセスするためのグローバルパラメータは、application.properties
内の spring.cloud.nacos.config.server-addr
および spring.cloud.nacos.config.namespace
で設定されます。spring.config.import
でインポートされた設定は、Spring の @Value
が参照するプロパティソースに適用されますが、アノテーションでインポートされた設定とは独立しています。ただし、同じ NacosClient オブジェクトを共有し、同じ Nacos インスタンスおよびネームスペース内の設定にアクセスします。
使用例
1. 完全な設定内容を String 型フィールドにロードjava
@NacosConfig(dataId = "SampleApp.application.properties", group = "default")
String configContent;
dataId=SampleApp.application.properties
, group=default
の完全な設定内容を configContent
フィールドにインジェクトします。
2. 指定されたキーのプロパティを基本型フィールドにロードjava
@NacosConfig(dataId = "SampleApp.application.properties", group = "default", key = "useCache", defaultValue = "false")
boolean booleanValue;
dataId=SampleApp.application.properties
, group=default
の設定から useCache
プロパティの値を booleanValue
フィールドにインジェクトします。以下の5つの基本型とそのラッパー型をサポートします:int
, long
, float
, double
, boolean
。
3. JSON 形式の設定を基本型配列にロードjava
@NacosConfig(dataId = "scoreintArray.json", group = "default")
int[] scores;
dataId=scoreintArray.json
, group=default
の JSON 形式の設定を scores
フィールドにインジェクトします。設定形式は正しく逆シリアル化される必要があります。以下の5つの基本型とそのラッパー型の配列をサポートします:int
, long
, float
, double
, boolean
。設定ファイルは .json
で終わる必要があります。
4. 設定を Properties フィールドにロードjava
@NacosConfig(dataId = "SampleApp.application.properties", group = "default")
Properties properties = new Properties();
dataId=SampleApp.application.properties
, group=default
の設定内容を properties
フィールドにインジェクトします。内部のプロパティ値は properties.getProperty
メソッドで取得できます。リモートの Nacos 設定が変更された場合、properties
オブジェクトが置き換えられ、参照が更新されます。プロパティおよび YAML 形式をサポートします。dataId
は .properties
, .yaml
, .yml
で終わる必要があります。YAML 形式では、配列またはリスト形式のプロパティを含めることはできません。
5. カスタム JavaBean フィールドにロードjava
@NacosConfig(dataId = "myobject.json", group = "default")
MyObject json2Object;
JSON形式の設定をFactoryBeanにロードするjava
public class SampleConfiguration {
@NacosConfig(dataId = myobject1.json, group = default)
@Bean
public MyObject bean1(){
return new MyObject();
}
@NacosConfig(dataId = myobject2.json, group = default)
@Bean
public MyObject bean2(){
return new MyObject();
}
}
dataId = myobject1.json
および group = default
の設定内容を、beanName=bean1
の MyObject
型の SpringBean にロードします。同様に、dataId = myobject2.json
および group = default
の設定内容を、beanName=bean2
の MyObject
型の SpringBean にロードします。この機能は、@Bean
アノテーションと併用する必要があります。
@NacosConfigListener アノテーションの使用方法の紹介
@NacosConfig
アノテーションのターゲットはフィールドです。このアノテーションは直接的にターゲットフィールドのプロパティを変更します。しかし、設定内容に対して二次処理を行う必要がある場合、@NacosConfig
アノテーションでは対応できません。例えば、プロパティが変更された際にプログラムが特定のビジネスアクションを実行したり、コード内で変更された設定に基づいて二次処理を行う場合などです。このようなケースでは、@NacosConfigListener
アノテーションを使用してこの要件を満たすことができます。
このアノテーションはSpringBeanメソッドに適用されます。指定された設定が変更されると、その設定内容がメソッドパラメータとして指定されたメソッドにコールバックされます。@NacosConfig
アノテーションと同様に、メソッドパラメータは基本型、プロパティ、配列、コレクション、カスタムJavaBeansをサポートします。初期化時にコールバックを受け取りたい場合は、initNotify=true
を設定できます(デフォルトはfalse)。以下のコールバックメソッド名は例であり、自由にカスタマイズ可能です。
使用例
-
String型のパラメータを持つメソッドでネイティブ設定の内容を受け取るjava
@NacosConfigListener(dataId = myobjectArray.json, group = default)
private void fullContentChanged(String content) {
System.out.println("receive :" + content);
}
dataId = myobjectArray.json
かつ group = default
の設定が変更された際、その完全な内容が content
パラメータとして fullContentChanged
メソッドに渡されます。
-
基本型のパラメータを持つメソッドで指定されたキー値の内容を受け取るjava
@NacosConfigListener(dataId = SampleApp.application.properties, group = default,key=score)
private void scoreChanged(int score) {
System.out.println("receive :" + score);
}
dataId = SampleApp.application.properties
かつ group = default
の設定において、key=score
のプロパティ値が変更された場合、そのプロパティ値が score
パラメータとして scoreChanged
メソッドに渡されます。これは以下の5つの基本型をサポートします:int、long、float、double、boolean。
-
基本型の配列パラメータを持つメソッドでJSON形式の設定内容を受け取るjava
@NacosConfigListener(dataId = scoresArray.json, group = default)
private void scoresChanged(int[] scores) {
System.out.println("receive :" + scores);
}
dataId = scoresArray.json
かつ group = default
のJSON形式の設定が変更された場合、その設定内容は基本型配列オブジェクトに逆シリアル化され、scores
パラメータとして scoresChanged
メソッドに渡されます。これには以下の5つの基本型の配列がサポートされます:int、long、float、double、boolean。なお、dataId
は .json
で終わる必要があり、設定内容はJSON配列形式である必要があります。
-
Properties型のパラメータを持つメソッドでプロパティパラメータを受け取るjava
@NacosConfigListener(dataId = SampleApp.application.properties, group = default)
private void propertiesChanged(Properties properties) {
System.out.println("receive :" + properties);
}
dataId = SampleApp.application.properties
かつ group = default
のプロパティ形式の設定が変更された場合、その設定内容は Properties
オブジェクトに解析され、Properties
型のパラメータとして propertiesChanged
メソッドに渡されます。
-
カスタムJavaBeanパラメータjava
@NacosConfigListener(dataId = myobject.json, group = default)
private void myObjectChanged(MyObject object) {
System.out.println("receive :" + object);
}
@NacosConfigListener(dataId = myobjectArray.json, group = default)
private void myObjectArrayChanged(MyObject[] objectArray) {
System.out.println("receive :" + objectArray);
}
@NacosConfigListener(dataId = myobjectArray.json, group = default)
private void myObjectListChanged(List objectList) {
System.out.println("receive :" + objectList);
}
@NacosConfigListener(dataId = myobjectMap.json, group = default)
private void myObjectMapChanged(Map objectMap) {
System.out.println("receive :" + objectMap);
}
指定された設定内容が変更された場合、これらのメソッドはオブジェクト、オブジェクト配列、オブジェクトリスト、オブジェクトマップと共にコールバックされます。これにはカスタム配列やコレクションタイプもサポートされており、指定されたジェネリックに基づいて自動的に逆シリアル化されます。
@NacosConfigKeysListener アノテーションの使用方法の紹介
このアノテーションはプロパティおよびYAML形式の設定をサポートしています。指定されたキーが変更された際に、ConfigChangeEvent
パラメータを通じて変更前後の内容を受け取ることができます。interestedKeys
または interestedKeyPrefixes
を使用して監視するキーのセットやプレフィックスを指定できます。これらの条件に一致するいずれかのキーが変更された場合、コールバックがトリガーされます。
使用例java
@NacosConfigKeysListener(dataId = SampleApp.122110test.properties, group = default, interestedKeys = {
"useLocalCache",}, interestedKeyPrefixes = {"122110."})
private void onKeysChangeSingle(ConfigChangeEvent changeEvent) {
System.out.println("interestedKeyPrefixes:nacos." + changeEvent.getChangeItems());
}
このアノテーションはプロパティおよびYAML形式をサポートしており、dataId
は .properties
、.yaml
、または .yml
で終わる必要があります。
まとめ
Spring Cloud Alibabaは、上記のアノテーションに対応した新しいバージョンを全シリーズ(2.2.x、2021.x、2022.x、2023.x)で正式にリリースしました。
- 2023.x シリーズはバージョン 2023.0.3.2 にアップグレードする必要があります。
- 2022.x シリーズはバージョン 2022.0.0.2 にアップグレードする必要があります。
- 2021.x シリーズはバージョン 2021.0.6.2 にアップグレードする必要があります。
- 2.2.x シリーズはバージョン 2.2.11 にアップグレードする必要があります。
2023.x バージョンでは、spring-cloud-alibaba 設定モジュールを再構築し、spring-alibaba-nacos-config モジュールを独立して抽出しました。このモジュールはSpringCloudフレームワークに依存しません。そのため、SpringBoot 3ベースのアプリケーションは、単純に spring-alibaba-nacos-config モジュールを含むだけで、Nacosの設定を参照するために @Value
アノテーションや、本記事で紹介された3つのアノテーションを使用できるようになります。
pom.xml への spring-alibaba-nacos-config 依存関係の導入xml
com.alibaba.cloud spring # 参考文献[1] Nacos 公式ウェブサイトhttps://nacos.io
[2] Nacos Github メインリポジトリhttps://github.com/alibaba/nacos
[3] エコシステムグループリポジトリhttps://github.com/nacos-group
[4] Spring Cloud Alibabahttps://sca.aliyun.com/docs/2023/user-guide/nacos/quick-start/
Nacos 多言語エコシステムリポジトリ
[1] Nacos-GO-SDKhttps://github.com/nacos-group/nacos-sdk-go
[2] Nacos-Python-SDKhttps://github.com/nacos-group/nacos-sdk-python_disabled
[3] Nacos-Rust-SDKhttps://github.com/nacos-group/nacos-sdk-rust
[4] Nacos C# SDKhttps://github.com/nacos-group/nacos-sdk-csharp
[5] Nacos C++ SDKhttps://github.com/nacos-group/nacos-sdk-cpp
[6] Nacos PHP-SDKhttps://github.com/nacos-group/nacos-sdk-php
[7] Rust Nacos Serverhttps://github.com/nacos-group/r-nacos
関連記事
Best Practice for Using KMS to Encrypt Sensitive Configurations in MSE Nacos
Zero-Trust Security Practice of Nacos
Evolution of Nacos in the Cloud-native Architecture