SpringBootにkeepaliveのtimeout設定をする
AWS の環境で ELB(ALB)のアイドルタイムアウトの設定を変更する際、意識しておかなければいけなのがバックエンド側の KeepAlive やタイムアウト設定です。
For backend connections, we recommend that you enable the HTTP keep-alive option for your EC2 instances. You can enable HTTP keep-alive in the web server settings for your EC2 instances. If you enable HTTP keep-alive, the load balancer can reuse backend connections until the keep-alive timeout expires.
バックエンド接続では EC2 インスタンスで HTTP キープアライブオプションを有効にすることが推奨されます。EC2 インスタンスのウェブサーバー設定で HTTP キープアライブを有効にできます。HTTP キープアライブを有効にすると、ロードバランサーはキープアライブのタイムアウト期間が終了するまで、バックエンド接続を再利用できます。
Connection idle timeout
バックエンド側が Apache や Nginx のケースはこれまでに何度も経験してきましたが、SpringBoot(Tomcat)の場合はどうすればいいでしょうか。
今回はその辺を探っていきたいと思います。
デフォルトのKeepAliveTimeout
まず、何も特別な設定をしない場合の「KeepAlive Timeout」の値が何になっているのか確認します。
actuator を設定して env や configprops を確認しても、こちらが意図的に指定した内容しか確認できなかったので、起動後にプログラムから確認します。
下記の公式ドキュメントを参考に、「keepAliveTimeout」と「connectionTimeout」の設定値を確認します。
server.tomcat.keep-alive-timeout
server.tomcat.connection-timeout
っと何気なく書きましたが、サクッと Kotlin でサンプルを作ってみましょう。
これで確認する限り、デフォルトは 60 秒(60000ms)のようです。
override fun customize(factory: TomcatServletWebServerFactory) {
factory.addConnectorCustomizers(TomcatConnectorCustomizer { connector ->
val protocol = connector.getProtocolHandler() as AbstractHttp11Protocol<*>
// protocol.keepAliveTimeout
// protocol.connectionTimeout
})
}
keepAliveTimeoutの設定
じつは Spring Boot 2.3 以降では、keepAliveTimeout を直接指定できる server.tomcat.keep-alive-timeout というプロパティが用意されています。
あわせて server.tomcat.connection-timeout も指定できます。120 秒(120000 ミリ秒)にするなら、application.yaml はこんな感じです。
server:
tomcat:
keep-alive-timeout: 120000
connection-timeout: 120000
これで keepAliveTimeout も connectionTimeout も 120 秒になります。
なお、古い記事でよく見かける server.connection-timeout(プレフィックスなし)は Spring Boot 2.0 で非推奨になり、現在は上記の server.tomcat.connection-timeout に置き換わっています。
連続リクエスト数の上限にも注意(max-keep-alive-requests)
Tomcat は、1 つの keep-alive 接続で処理する HTTP リクエスト数にも上限があり、既定では 100 リクエストで接続を閉じます。
接続を長く使い回したい場合は、server.tomcat.max-keep-alive-requests を大きくするか、-1(無制限)にしておくと安定します。
server:
tomcat:
max-keep-alive-requests: -1
ALB のアイドルタイムアウトとの関係
AWS の定石として、バックエンド(Tomcat)側の keep-alive タイムアウトは、ALB のアイドルタイムアウトより長めに設定します。
逆にバックエンド側が先に接続を閉じてしまうと、ALB が再利用しようとした接続がすでに切れていて、502(Bad Gateway)が発生することがあるためです。
