Azure App Configurationを試す(3)ポーリングモデルを使用した動的な構成を試す

はじめに

先日より試してみている機能の一つとして、アプリの設定や機能フラグを一元的に管理するためのサービスとしてAzure App Configurationというものがあります。

docs.microsoft.com

上のドキュメントを読んでもあまり嬉しさがわからないのですが、その嬉しさを理解するためにもSpring Bootアプリで試してみることにしました。今回はポーリングモデルを使用した動的な構成を試してみました。

これまで試した記事は以下の通り。

サンプル

例によってチュートリアルが用意されているのでそれを参考にします。

docs.microsoft.com

例によって幾つか注意点がありましたので、それらを記していきます。

ライブラリのバージョン

com.azure.spring:azure-spring-cloud-appconfiguration-config-webが必要ということなので、build.gradleに追記しておきます。追記する際、com.azure.spring:azure-spring-cloud-appconfiguration-config-webのバージョンを確認しておきます。先日com.azure.spring:azure-spring-cloud-appconfiguration-configを試したときには、2.5.0だったのですが、執筆時点(2022年5月8日)では2.6.0が出ていたので、両方のバージョンを合わせておきます。

mvnrepository.com

実装

実装というほどでもないですが、src/main/resources/boostrap.propertiesに以下の2行を追加します。

spring.cloud.azure.appconfiguration.stores[0].monitoring.enabled=true
spring.cloud.azure.appconfiguration.stores[0].monitoring.triggers[0].key=sentinel

このとき、spring.cloud.azure.appconfiguration.stores[0].monitoring.triggers[0].key=sentinelを記述していない場合はSpring Bootアプリの起動時に以下の例外をはいて起動に失敗します。

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'spring.cloud.azure.appconfiguration-com.azure.spring.cloud.config.properties.AppConfigurationProperties': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Triggers need to be set if refresh is enabled.

spring.cloud.azure.appconfiguration.stores[0].monitoring.triggers[0].keyの値に指定するのはAzure App Configurationの構成エクスプローラーで指定したキーとなります。ちなみに、この値をAzure App Configurationで設定したものとは違うもの(sentinel2とか)に指定した場合、Spring Bootアプリは以下の例外をはいて起動に失敗します。

com.azure.core.exception.ResourceNotFoundException: Setting not found.

試してみる

この状態でAzure App Configuration上の/application/config.messageの値を変更します。変更は3点リーダーをクリックしたら出てくるEditを押した画面にて実施します。

値の変更

これだけだとダメで、spring.cloud.azure.appconfiguration.stores[0].monitoring.triggers[0].keyで指定したキーの値も変更します。

変更が完了後、少し(30秒ぐらい)待ってSpring Bootアプリにアクセスします。最初のアクセス時に/application/config.messageが変更されたことが検出されます。Spring Bootアプリのログにも、変更が検出されRefresh keys changedと出力されていることがわかります。

2022-05-08 11:22:10.507  INFO 7265 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2022-05-08 11:22:10.509  INFO 7265 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 2 ms
2022-05-08 11:27:07.580  INFO 7265 --- [        task-16] c.a.s.c.config.AppConfigurationRefresh   : Configuration Refresh Event triggered by sentinel
2022-05-08 11:27:08.360  INFO 7265 --- [        task-16] b.c.PropertySourceBootstrapConfiguration : Located property source: [BootstrapPropertySource {name='bootstrapProperties-/application/https://xxxxxxxxxxxx.azconfig.io/'}]
2022-05-08 11:27:08.363  INFO 7265 --- [        task-16] o.s.boot.SpringApplication               : No active profile set, falling back to 1 default profile: "default"
2022-05-08 11:27:08.367  INFO 7265 --- [        task-16] o.s.boot.SpringApplication               : Started application in 0.784 seconds (JVM running for 312.312)
2022-05-08 11:27:08.417  INFO 7265 --- [        task-16] o.s.c.e.event.RefreshEventListener       : Refresh keys changed: [config.message]

この段階ではブラウザの表示に変更はありません。

再度Spring Bootアプリにアクセスすることで/application/config.messageの値が反映され、ブラウザの表示が変更されます。

変更が検出される時間を短く/長くする

今回、変更が検出されるためにspring.cloud.azure.appconfiguration.stores[0].monitoring.triggers[0].keyで指定したキーの値の変更後30秒ほど待ちました。これは、com.azure.spring:azure-spring-cloud-appconfiguration-config-webで設定されているspring.cloud.azure.appconfiguration.stores[0].monitoring.refresh-intervalという設定値のデフォルト値が30秒になっているためです。これを短くする/長くするにはsrc/main/resources/boostrap.propertiesにて次のように記述すればよいです。

# 10秒に変更
spring.cloud.azure.appconfiguration.stores[0].monitoring.refresh-interval=10s

上記のように設定すると、10秒で変更が検出されるようになりました。

テストの時Azure App Configurationを参照しないようにする

ポーリングモデルを使用した動的な構成のテストは以上です。ここからは、少し発展的な話題です。

JUnitなどでテストを書いた時、Azure App Configurationを設定しなくてもJUnitのテストは動くようにしたい場合があります。このような場合はsrc/test/resources/bootstrap.propertiesにて以下の記述をすればJUnitのテスト実行時にAzure App Configurationを参照することはなくなります。

spring.cloud.azure.appconfiguration.enabled=false

このときAzure App Configurationで設定する各種設定値を使ったテストをしたい場合は、以下の通り@SpringBootTestproperties属性を使って設定してあげたらテストごとに異なった設定値のテストができてよいかなと思います。

@SpringBootTest(properties = "config.message=hogehoge")
@AutoConfigureMockMvc
public class HelloControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @Test
    public void shouldReturnMessage() throws Exception {
        this.mockMvc.perform(get("/"))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(content().string(containsString("Message:hogehoge")));
    }
}

サンプルソース

ここまでのソースです。

github.com