はじめに
Google App Engine Java + Spring Boot という構成で warmup request を受け取る方法を調べましたが、いい情報が見つからなかったのでまとめました。Java ではなく Kotlin を使用していますが、基本的には同じだと思います。
構成
- Java 1.8
- Spring Boot 2.1.0
- Kotlin 1.3.10
GAE の制約により Java 1.8 なのがネックですが、そのうち google がバージョンアップしてくれるはずだと信じています🙏
ウォームアップリクエストを受け取る方法
公式に書いてあるチュートリアルを要約するとこんな感じです。
- /_ah/warmup に対してウォームアップリクエストが定期的に実行される
- GAE/Java はデフォルトでウォームアップリクエストが有効 ※エンドポイントが存在しないと http status 500 エラーになる
- カスタムウォームアップリクエストを追加したい場合は web.xml にサーブレットを追加する
-
ServletContextlisterner
を使用してサーブレット読み込み前にカスタムをロジックを実行できる
上記のような感じなのですが、Spring Boot の場合だと web.xml を使用しない構成が一般的だと思います。
試しに web.xml
にカスタムサーブレットを追記して ./gradlew appengineStart
したところ、Spring Boot が起動しませんでした。こいつは困った😅
web.xml にカスタムサーブレットを追記せず、ウォームアップリクエストを受け取る @RestController
を追加する という方法も試しましたが、Controller は Spring Boot が起動していないと機能しないため、ウォームアップリクエストをハンドリングできずエラーになってしまいました。
解決方法
上記を踏まえて以下の方法で解決しました。
- web.xml は使用しない
-
@WebServlet
アノテーションを付与したサーブレットクラスを作成する -
name = "_ah_warmup"
,urlPatterns = /_ah/warmup
とし、ウォームアップリクエストを受け取るようにする
ソースコードはこんな感じです。
import javax.servlet.annotation.WebServlet
import javax.servlet.http.HttpServlet
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
@WebServlet(
name = "_ah_warmup",
description = "handling warmup request.",
urlPatterns = arrayOf("/_ah/warmup"),
loadOnStartup = 1
)
class WarmupServlet : HttpServlet() {
override fun doGet(req: HttpServletRequest?, resp: HttpServletResponse?) {
// 特に何もしない
}
}
Stackdriver Logging を見たところ、/_ah/warmup
宛のリクエストを正常に受け取れるようになりました。ウォームアップリクエストを使用しないという選択肢も考えましたが、その場合だと GAE/Java の起動だけで47秒かかってしまうため、上記の方法を採用しました。他にも何かいい方法があれば教えていただけると助かります🙏
※GAE の制約により、60秒を超える処理はタイムアウトするため正常に処理できない。Spring Boot の起動で47秒かかると他の処理に使える時間が13秒しかないので、重い処理を実行するとタイムアウトする可能性が高くなる