ネットワークで接続されている相手と通信する場合、仮にプログラムに不具合がなかったとしても、外的要因による何らかの障害が発生することは避けられません。
そのため、障害対策の方針も、障害を無くすというよりは、障害の原因をなるべく早く判明する、という方向に注力することが重要になります。
ネットワーク絡みの障害の原因は非常に多岐に渡るため、全てを並べるのは到底不可能です。よくありそうなものの抜粋と思ってください。
発生する例外 | java.net.UnknownHostException |
メッセージ例 | [ホスト名] |
HTTP Status | - |
発生要因 |
URLのホスト名が間違っている。 DNSサーバがダウンしている。 |
発生する例外 | java.net.SocketTimeoutException |
メッセージ例 | connect timed out |
HTTP Status | - |
発生要因 |
URLのIPアドレスが正しくない。 ホストがダウンしている。 ネットワークケーブルが抜けている。 Wi-Fiが接続されていない。 圏外。 |
発生する例外 | java.net.ConnectException |
メッセージ例 | Connection refused |
HTTP Status | - |
発生要因 |
URLのポート番号が正しくない。 Webサーバがダウンしている。 |
発生する例外 | java.io.FileNotFoundException |
メッセージ例 | [URL] |
HTTP Status | 404 |
発生要因 |
間違ったホストに接続している。 URLのディレクトリ名やファイル名が正しくない。 サーバに必要なディレクトリやファイルが存在しない。 |
発生する例外 | java.net.SocketTimeoutException |
メッセージ例 | Read timed out |
HTTP Status | - |
発生要因 |
サーバの負荷が高い。 |
発生する例外 | java.io.IOException |
メッセージ例 | Server returned HTTP response code: 403 for URL: [URL] |
HTTP Status | 403 |
発生要因 |
URLが正しいリソースを示していない。 認証したユーザが正しくない。 |
発生する例外 | java.io.IOException |
メッセージ例 | Server returned HTTP response code: 500 for URL: [URL] |
HTTP Status | 500 |
発生要因 |
サーバプログラムの不具合。 |
上記障害の中で、よく問題になるのが(自戒の念も込めて)「(5)応答なし(レスポンスタイムアウト)」です。
タイムアウトは、あくまでもクライアント側で検知するものなので、ホスト側の処理は続行している可能性があります。
タイムアウトだからといって、安易にリトライなどを行うと、サーバ側でのセッション管理に影響して、障害となる可能性があります。
また、更新処理の場合、二重更新となってしまう可能性もあります。
正常に結果を読み込めたケース以外は、全てエラーとするのであれば、例外が発生したケースは全てエラーとしてしまえば、それで終わりです。
しかし、「コネクトタイムアウト」の場合、一時的な場合もあるのでリトライにより解決する可能性もあります。何秒かおきに数回リトライしてみるのは、悪くない考えです。
そこで問題となるのが、障害発生原因の切り分けが難しいという事実です。
「コネクトタイムアウト」と「レスポンスタイムアウト」は、GETメソッドの場合、発生する箇所も発生する例外も同じなので、切り分けるすべがありません。
HTTP固有の問題で処理を切り分ける場合も同様です。
認証が必要なケースでは、ユーザに入力を促す必要がありますが、認証が必要なケースもサーバ内部エラーも、発生する箇所も発生する例外も同じなので、切り分けるすべがありません。
違いは例外のメッセージだけですが、メッセージはVMの実装により変わる可能性があるので、メッセージで切り分けを行うのは、かなりリスキーです。
そのあたりを切り分ける必要が生じた場合、やっとHttpURLConnectionの出番です。
もう一つ、どうしてもHttpURLConnectionを使わなければならないケースが、リダイレクトの対応です。
URLConnectionは、サーバがリダイレクトを返した場合、自動的にリダイレクトを行い、その結果のみを返します。プログラム側からは、リダイレクトが発生したかどうかを検知できないので、時により問題となります。
HttpURLConnectionを使うことにより、必要に応じてリダイレクトを抑止することが出来ます。
1.今更ながらの、HttpURLConnection Get編
2.今更ながらの、HttpURLConnection Post編
3.今更ながらの、HttpURLConnection 障害処理編