- Spring Cloud Configとは
- 何がいいの?
- サンプル書いた
- 実装方法
- クライアントから見たときのファイル名とアプリの関連性は?
- 設定変更の反映
- でも全部のConfigクライアントに/refreshなんてしたくない
- 参考にしたサイト
Spring Cloud Configとは
複数アプリケーション(同一サービス)間で共通の設定を提供するプロダクト。
クライアント-サーバ型のアーキテクチャ。
- Configサーバ(githubやファイルシステム上のgitリポジトリから設定を取得してクライアントに配布する)
- Configクライアント(サーバに要求して設定を取得する)
何がいいの?
- 複数アプリケーション(同一サービス)間の設定の不一致を避けられる。
- 再起動なしで設定を再配布できる。
サンプル書いた
実装方法
Configサーバ
pom.xmlで必要なjarを指定する。
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency>
@EnableConfigServerをつける。
@SpringBootApplication @EnableConfigServer public class ConfigServerApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerApplication.class, args); } }
クライアントに配布する設定ファイルの配置場所をapplication.propertiesで指定する。portは8888が一般的っぽい。
server.port = 8888 spring.cloud.config.server.git.uri = https://github.com/kimullaa/spring-cloud-config-repo.git
githubでもローカルのファイルシステム上にあるgitリポジトリでもok。publicでもprivateなリポジトリでもok。sshでもok。特に制約なし。
リポジトリはアプリごとに1つ用意するのがシンプルでよい。
ファイル名は{app名}-{profile}にする。
https://github.com/kimullaa/spring-cloud-config-repo
Configサーバといっても、以下のようなエンドポイントを持ったAPサーバ。
(labelはdefaultがmasterで省略可能)
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
そのため、curlで設定を確認できる。
$ curl -X GET http://localhost:8888/app/production { "name":"app", "profiles":[ "production" ], "label":null, "version":"1469d0351becdfcc a1bffa98f4a07ee685af8255", "propertySources":[ { "name":"https://github.com/kimulla men/spring-cloud-config-repo.git/app-production.properties", "source":{ "greeting":"production" } } ] } $ curl -X GET http://localhost:8888/app-development.properties greeting: development
Configクライアント
pom.xmlで必要なjarを指定する。
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency>
bootstrap.propertiesにconfigサーバのURIを指定する。
spring.cloud.config.uri = http://localhost:8888 spring.application.name = app spring.profiles.active = production
bootstrap.propertiesはBootstrapContext※を生成するときに利用するファイル。
Configサーバから取得した設定内容を読み込んだクラスが生成される。
※BootstrapContextはApplicationContextの子親コンテキスト。詳細はリファレンスを参照する。
設定を取得できてるか確認するためのControllerを実装する。
@Valueでpropertiesファイルの値を取得できる。(:not-foundは見つからなかったときのデフォルト値)
@RestController public class GreetingRestController { @RequestMapping("/greeting") public String greeting(@Value("${greeting:not-found}") String greeting) { return greeting; } }
クライアントから見たときのファイル名とアプリの関連性は?
{app名}-{profile}-{label}.properties
app名 | spring.application.name |
profile | spring.active.profiles |
label | gitのbranch名(デフォルトmaster) |
設定変更の反映
いくらgitのファイルを更新しても、アプリ側が設定ファイルを再度読み込むまでは値が反映されない。設定ファイルを再度読み込むためには、/refreshエンドポイントにPOSTすればよい。
細かい理由
- @ConfigurationPropertiesアノテーションが付与されているクラスは@RefreshScopeになる
- @RefreshScopeのBeanは/refreshエンドポイントにPOSTするとBeanが再生成される
- ConfigClientAutoConfigurationクラス内でConfigServicePropertySourceLocatorという設定ファイル読み込み用のクラスが@RefreshScopeになっているため/refreshエンドポイントにPOSTすれば更新されるっぽい
$ curl -X POST localhost:8080/refresh ["greeting"]
でも全部のConfigクライアントに/refreshなんてしたくない
Spring Cloud Busというプロダクトを使えば、Configクライアントから他のConfigクライアントへ更新通知を伝搬できるようになる。また今度調べる。調べた。
kimulla.hatenablog.com