HTTPの再接続戦略を実装してみよう！

# はじめに
　HTTPリクエストの再接続戦略どうされてますか？
　HTTPリクエストの標準で設けられている再接続設定を利用している人は多いいかと思います。
　今回はそのお話です。

# 背景
　Endpoint With ProxyでSecret Managerを利用してTSL相互認証を利用している環境で、接続しているシステムやネットワークの影響で、瞬間でコネクションを確立できない時があります。
　その場合、HTTPリクエストの標準の再接続設定を設定しているから大丈夫だと思ってませんか？
　私たちは、その時のためにHTTPリクエストの再接続設定を設定しているわけですが、再接続処理は動作せずに、Endpoint With Proxyの500系のサーバエラーをクライアントに返却してしまいます。
　MuleSoftサポートからの回答は、「コネクタの再接続設定は、JMSなどのエンドポイントベースで、接続を保持してポーリングでメッセージを通信する方式には利用可能だが、HTTPのようにメッセージベースでメッセージが送信されるタイミングで接続を確立するHTTPリクエストでは利用できない。UntilSuccessfulの再接続メカニズムが推奨される方式。」とのことでした。
　「（いろいろ言いたいことあるけど）そうかー」とみんな思うのではないでしょうか？

[公式ヘルプ：再接続戦略](https://docs.mulesoft.com/jp/mule-runtime/4.3/reconnection-strategy-about)
[公式ヘルプ：HTTP Request 設定リファレンス > 再試行メカニズム](https://docs.mulesoft.com/jp/http-connector/1.5/http-request-ref#%E5%86%8D%E8%A9%A6%E8%A1%8C%E3%83%A1%E3%82%AB%E3%83%8B%E3%82%BA%E3%83%A0)

# 解決方法
　再接続メカニズムは、Untilsuccessfulコンポーネントとサクセスコードバリデータを利用します。
　まず、サクセスコードバリデータを設定します。Endpoint With Proxyからサーバの接続失敗時のみ再接続設定したいので、HTTPリクエストコンポーネントのレスポンスタブにあるレスポンスバリデータにサクセスコードバリデータを選択し、0 - 500のHTTPステータスコードはエクセプションを発生させないようにすることで、Endpoint With Proxyからサーバの接続失敗時のみ再接続する動作となります。
　次にUntilsuccessfulコンポーネントで囲むことで実装は完了です。
　考慮事項として、HTTPステータスのエラーが発生した場合は後続の処理で、対応する制御することになります。


``` http-proxy.xml
        <until-successful maxRetries="${reconn.count}" millisBetweenRetries="${reconn.frequency}">
        <http:request config-ref="http-request-config" method="#[attributes.method]" path="#[attributes.maskedRequestPath]">
            <http:headers>#[vars.proxyRequestHeaders]</http:headers>
            <http:uri-params>#[attributes.uriParams]</http:uri-params>
            <http:query-params>#[attributes.queryParams]</http:query-params>
            <http:response-validator>
                <http:success-status-code-validator values="0..599"/>
            </http:response-validator>
        </http:request>
        </until-successful>
```

# 結果の確認
 今回は、本番で発生しているSSL障害を発生させることが難しかったので、レスポンス時間を短くすることで同じようなエラーを発生させて、正しく動作するか確認します。

```
ERROR 2020-11-11 09:49:31,012 [Grizzly-IdleTimeoutFilter-IdleCheck] [processor: proxy/processors/0; event: c16c0000-23b7-11eb-8c5d-94e6f754ed3b] org.mule.runtime.core.internal.exception.OnErrorPropagateHandler: 
********************************************************************************
Message               : HTTP GET on resource 'https://acn-aflj-dlb.lb.anypointdns.net:443/account-mock-proxy/account' failed: Timeout exceeded.
Element               : proxy/processors/0 @ account-mutual-proxy-api-gateway-edit_v0.0.2:http-proxy.xml:25
Element DSL           : <http:request config-ref="http-request-config" path="/account-mock-proxy/account" method="GET">
<reconnect count="10"></reconnect>
```
　Untilsuccessfulの再接続メカニズムを適応する下記のメッセージになります。

```
ERROR 2020-11-11 10:06:03,765 [Grizzly-IdleTimeoutFilter-IdleCheck] [processor: proxy/processors/0/processors/0; event: 11a3d190-23ba-11eb-ae37-94e6f754ed3b] org.mule.extension.http.internal.request.HttpRequester: Error sending HTTP request to https://acn-aflj-dlb.lb.anypointdns.net:443/account-mock-proxy/account
ERROR 2020-11-11 10:06:03,766 [Grizzly-IdleTimeoutFilter-IdleCheck] [processor: proxy/processors/0/processors/0; event: 11a3d190-23ba-11eb-ae37-94e6f754ed3b] org.mule.runtime.core.internal.routing.UntilSuccessfulRouter: Retrying execution of event, attempt 1 of 5.
```

# まとめ
　Untilsuccessfulコンポーネントとサクセスコードバリデータを利用することで、再接続できるようになりました。
　ただ、気を付けるべき点はエラーが解消していないところです。
　接続時にエラーがまだ発生しますが、エラーを検知すると再接続処理が動作して、結果利用アプリケーションに正常な値を返すことができることをお客様に説明する必要があります。では、