spring-cloud-configを触ってみた

# 概要

- Spring Projectsの中で「spring-cloud-config」が気になったので触ってみた！

# 使ってみての所感

先に所感を

- アプリケーションを再起動するだけでconfigの読み替えができるのはいいかも
- /refreshエンドポイントを使って稼働中にもconfigを再読み込みはできるけど、classがreloadされるのでレスポンスが悪化する…
    - 何かうまいやり方ないかな😇

# 構成

```
config client --read--> config server --read--> git, class path, ...
```

要素 | 役割
--- | ---
config client | アプリケーション
congig server | configをAPIで提供
git, class path | config serverで扱う設定値の格納場所

# 構築

## Config Server

今回はclass path上に設定ファイルを配置する方針で構築してみます。

依存には`spring-cloud-config-server`を追加します。

```groovy:build.gradle
dependencies {
    implementation 'org.springframework.cloud:spring-cloud-config-server'
}
```

アプリケーションが側の実装は、`@EnableConfigServer`を付与するだけです！

```Application.java
@SpringBootApplication
@EnableConfigServer
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
}
```

application.yml（application.properties）には設定ファイルの場所を記載します。

```yaml:application.yml
server:
  # config serverは8888が一般的なようです
  port: 8888

spring:
  cloud:
    config:
      server:
        native:
          search-locations: "classpath:/config/"
  # ファイル参照の場合は「native」を指定
  profiles:
    active: native
```

今回は`classpath:/config/`を指定しているので、`src/main/resources/config`配下にファイルをおきます

```yaml:sample-dev.yml
sample:
  key1: value1
  key2: value2
```

ファイル名は「<Clientのアプリケーション名>-<環境>」とするのが無難かなと思います

起動して動作確認してみます

```bash
$ curl localhost:8888/sample/dev | jq
{
  "name": "sample",
  "profiles": [
    "dev"
  ],
  "label": null,
  "version": null,
  "state": null,
  "propertySources": [
    {
      "name": "class path resource [config/sample-dev.yml",
      "source": {
        "sample.key1": "value1",
        "sample.key2": "value2"
      }
    }
  ]
}
```

`/<Clientのアプリケーション名>/<環境>`のパスで配置した設定ファイルの内容がAPIのレスポンスとして取得できるようになっています！  
これをClient側で読み込めばOKですね！

## Config Client

依存に`spring-cloud-starter-config`を追加します。

```groovy:build.gradle
dependencies {
  implementation 'org.springframework.cloud:spring-cloud-starter-config'
}
```

application.ymlにはconfig serverを読み込むための設定をします

```yaml:application.yml
management:
  endpoints:
    web:
      exposure:
        # config serverから読み込んだconfigの確認のためにenvを利用
        # configの再読み込みのためにrefreshも有効化
        include: "env,refresh"
      base-path: "/"
  server:
    port: 9990

spring:
  config:
    import: "optional:configserver:http://localhost:8888"

  profiles:
    active: dev
  application:
    name: sample
```

起動して読み込まれたプロパティを確認してみます

```bash
$ curl localhost:9990/env | jq
{
  "activeProfiles": [
    "dev"
  ],
  "propertySources": [
    ...
    {
      "name": "configserver:class path resource [config/sample-dev.yml",
      "properties": {
        "sample.key1": {
          "value": "value1",
          "origin": "Config Server class path resource [config/sample-dev.yml:2:9"
        },
        "sample.key2": {
          "value": "value2",
          "origin": "Config Server class path resource [config/sample-dev.yml:3:9"
        }
      }
    },
    ...
  ]
}
```

# configのreload

Config Clientで`/refresh`エンドポイントにGetリクエストをするとConfig Serverの設定値を読み込み直してくれます。

このとき、classのreloadが行われるため（言葉は正確じゃないかも…）一時的にレスポンスが遅延してそうでした…  
（リクエストがこない状態にしてからじゃないと/refresh叩けないな😇）