クライアントからサーバーへの再送信をやめる


はじめに

本件はわたくしは当事者ではなく、聞いただけなので曖昧な表現が多いかもしれません。

サーバーからの応答が時間がかかった

クライアント(Java)からLB経由でサーバーに接続していて、サーバーからの応答がn分間かかるという事象がありました。n分間かかってしまうのはリクエストのデータ量が多く、ある意味仕様なのです(それがイケていないというツッコミは無しで)。
時間がかかるのは、分かっていたことなのですが、n分間経過すると同じリクエストがサーバーに届くという事象が発生しました。

同じリクエストが再送されたせいで、サーバ側でエラーになってしまったのですが、上図②を誰が行ったのか分かりませんでした。クライアント側では特に例外は出ていなかったようです。

誰が再送したのか

犯人はクライアントのJavaでした。
使用していたLBではn分間応答が無かったら、クライアント側にfinを返すようになっていました。Javaでは勝手に再送するようになっていました。これは
RFC2616に記載されているように、POSTで接続できなかった場合もう一度送るべき、と書いてあるのでJavaもそれに倣っていると思います。
なお、今回はCommons-HttpClient(3.x)を使用していましたが、内部ではJavaのHTTPClientのクラスを使用しているようです。

JDKネットワークプロパティ

ここに書いてありました。

sun.net.http.retryPost (デフォルト: true)
成功しなかったHTTP POST要求がサーバーに自動的に再送信されるかどうかを決定します。この場合、「成功しなかった」とは、サーバーが有効なHTTP要求または発生したIOExceptionを送信しなかったことを意味します。

上記プロパティをfalseにすると再送されなくなりました。
ただ、結局はn分間応答が無いとエラーになってしまうので根本解決にはなっていませんが。