プログラムから外部のWeb APIを呼び出すことはよくあることで、HttpURLConnectionクラスを使ったり、OkHttpなどのライブラリを使ったりするようです。ちょっと古い?HttpClientを使っているプロジェクトで、HTTPのKeep Aliveを見直す必要があったので簡単にまとめます。
Apache HttpComponents
Apache Http Clientなんて聞きましたが、今ではApache HttpComponentsというようです。バージョンが上がるときにAPIが大きく変わったことがあるらしく、どのバージョンについて説明している記事か確認するように気をつけましょう。この記事では4.5について説明します。
Apache HttpComponents – HttpComponents HttpClient Overview
Although the java.net package provides basic functionality for accessing resources via HTTP, it doesn't provide the full flexibility or functionality needed by many applications. HttpClient seeks to fill this void by providing an efficient, up-to-date, and feature-rich package implementing the client side of the most recent HTTP standards and recommendations.
HTTP Keep-Alive
HTTPはステートレスなプロトコルなので、毎回サーバに繋いで処理が終わったら切断して、というのが基本です。が、いちいち繋ぎなおすのは効率がよくないため、接続しっぱなしにする、Keep-Aliveという仕組みがあります。Real World HTTPを読んでみるのがよいでしょう。
HTTP Connectionが維持される時間は?
HTTP/1.1では、Keep-Aliveがデフォルトです。
Connection: Closeのヘッダーをつけてサーバかクライアントがリクエスト/レスポンスを投げることで、明示的に接続を切断します。そうでない場合、タイムアウトするまでは接続が維持されます。
タイムアウト?何秒でタイムアウトするか、どこにも書いてありません。何秒にするか、決まりもないようです。Apache HTTP Serverで、Keep-Aliveの設定値を短めにしてサーバの負荷を下げるなんてことを見かけたこともあるので、サーバー管理者が適切な値を設定するもののようです。
問題なのは、何秒接続が維持されるのか、クライアント側にはわからないことです。クライアントが想定している維持時間(例えば60秒)よりも、サーバ側の設定が短い(例えば30秒)場合、クライアントでは、既に閉じられているコネクションを使おうとして、通信がエラーになります。エラーリトライすればよいのかもしれませんが、すぐにリトライしてよいものなのかどうか、判断する必要があります。
Keep-Aliveの拡張情報をApache Http Clientで使う
何秒接続が維持されるかわからないのでは不便だと思っている人は多いようで、Keep-Aliveのヘッダーを独自拡張しているサーバがあります。とあるApache http serverは
Keep-Alive: timeout=5, max=100となっていましたし、Nginxでの動きを検証した記事もありました。
Nginx の keep-alive の設定と検証 - How old are you?
このエントリは nginx Advent Calendar 2014 の7日目です。 1 はじめに Webサーバを運用する時に気になる設定の1つとして keep-alive の設定があります。 今まで調べようと思ってできていなかったので、nginx Advent Calendar 2014 の勢いに乗って調べてみました。このエントリの概要は以下の通り。 クライアント Nginx 間の keep-a
では、Http Clientでどう対応すればよいかというと、チュートリアルにコードが載っています。
Connection keep alive strategy
The HTTP specification does not specify how long a persistent connection may be and should be kept alive. Some HTTP servers use a non-standard Keep-Alive header to communicate to the client the period of time in seconds ...
Keep-Aliveのtimeoutが検出できなかった場合のコードを少し手直しする必要がありますが、あとは使えそうです。ただ、
- サーバから提示されたtimeoutをそのまま使う?(少し短めの値にしなくても大丈夫?)
- timeoutの値がなかった場合、何秒にする?(チュートリアルのコードでは30秒になっているけど?)
といった部分は、検討した方がよいでしょう。
いい感じにやってくれるライブラリはそのうち?
Java11で、HTTPクライアントAPIは大幅に進化したようです。
イマドキのJava徹底入門(10) HTTP接続を劇的に改善したHTTPクライアントAPIとは?(その1)
Javaの標準APIでHTTP接続を行う場合、HttpURLConnectionクラスを使う方法が一般的だった。しかしこのクラスは実装が古く、HTTP/2プロトコルにも対応していないため、実用に耐えない。そこで、Java 11からHTTPクライアントAPIが登場した。今回は、この新しいAPIを使ってHTTP接続を行う方法を紹介する。
サードパーティーのhttp client ライブラリも、いろいろ進化することでしょう。HTTP/2に移行しないサーバもあるでしょうから、HTTP/1.1でも手間をかけずに効率的に利用できるようなライブラリが出てくることを期待しています。