1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Application Load Balancer 配下の SpringBoot アプリケーションを暖機運転する

Posted at

環境

  • java: 17
  • spring: 6.0.11
  • spring-boot: 3.1.2
  • spring-boot-actuator: 3.1.2

きっかけ

ALB (Application Load Balancer) + ECS で Java アプリケーションを公開しているとき、スケールアウトのタイミングで応答時間が一時的に劣化する問題の対応として暖機運転を実装しました。

方針

ヘルスチェックには spring-boot-actuator のヘルスチェックエンドポイントを使っている前提とします。

  • 暖機リクエストの実行タイミング
    暖機リクエストの送信は、当然ながらアプリケーションがリクエストを受け付けられる準備が整ってから始めたいので、 Spring の ApplicationReadyEvent@EventListener でハンドリングするようにします。

  • ヘルスチェックのカスタマイズ
    spring-boot-actuator では、独自の HealthIndicator 実装を追加することでヘルスチェックの内容を拡張できます。
    すべての暖機リクエストを送信し終わってから初めて "UP" ステータスを返す HealthIndicator を実装することにします。

実装

Configuration として実装した例は、以下。

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication
@Slf4j
class WarmUpConfig implements HealthIndicator {
  private final int port;
  private volatile boolean done = false;

  WarmUpConfig(@Value("${server.port:8080}") int port) {
    this.port = port;
  }

  @Override
  public Health health() {
    if (!done) {
      return Health.down().build();
    }
    return Health.up().build();
  }

  @EventListener(ApplicationReadyEvent.class)
  public void onReady() {
    try {
      doWarmUp();
    } catch (Exception e) {
      log.warn("暖機リクエスト送信中に問題が起きたけど、サーバは元気です!!", e);
    } finally {
      this.done = true;
    }
  }

  private void doWarmUp() {
    final HttpClient httpClient =
        HttpClient.create()
            .followRedirect(false)
            .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2000)
            .responseTimeout(Duration.ofSeconds(10));
    final WebClient client =
        WebClient.builder()
            .clientConnector(new ReactorClientHttpConnector(httpClient))
            .baseUrl("http://localhost:" + port + "/path/to/endpoint")
            .build();

    // ローカルあてに暖機リクエストを送る
  }
}

動作確認

  • 暖機運転中
    $ curl -v localhost:8080/actuator/health | jq .
    *   Trying 127.0.0.1:8080...
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
      0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* 
    Connected to localhost (127.0.0.1) port 8080 (#0)
    > GET /actuator/health HTTP/1.1
    > Host: localhost:8080
    > User-Agent: curl/7.79.1
    > Accept: */*
    > 
    * Mark bundle as not supporting multiuse
    < HTTP/1.1 503 
    < Content-Type: application/vnd.spring-boot.actuator.v3+json
    < Transfer-Encoding: chunked
    < Date: Tue, 26 Sep 2023 03:32:42 GMT
    < Connection: close
    < 
    { [23 bytes data]
    100    17    0    17    0     0   1958      0 --:--:-- --:--:-- --:--:--  5666
    * Closing connection 0
    {
      "status": "DOWN"
    }
    
  • 暖機運転完了後
    $ curl -v localhost:8080/actuator/health | jq .
    *   Trying 127.0.0.1:8080...
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
      0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* 
    Connected to localhost (127.0.0.1) port 8080 (#0)
    > GET /actuator/health HTTP/1.1
    > Host: localhost:8080
    > User-Agent: curl/7.79.1
    > Accept: */*
    > 
    * Mark bundle as not supporting multiuse
    < HTTP/1.1 200 
    < Content-Type: application/vnd.spring-boot.actuator.v3+json
    < Transfer-Encoding: chunked
    < Date: Tue, 26 Sep 2023 03:32:47 GMT
    < 
    { [20 bytes data]
    100    15    0    15    0     0   1469      0 --:--:-- --:--:-- --:--:--  3750
    * Connection #0 to host localhost left intact
    {
      "status": "UP"
    }
    

まとめ

ApplicationReadyEvent と spring-boot-actuator を使って暖機運転を実装する例を紹介しました。

Spring 6.x からは GraalVM 対応が入ったので、今だったらネイティブイメージにしてデプロイすれば初速から全速力ということも可能なのかもしれません。
ただ、開発の優先順位もあり、そう簡単に GraalVM 対応できないんですよね。
しばらくは暖機運転のお世話になりそうです。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?