一部のユースケースでは、ApacheAPIによって送信されたリクエストをカウントできる必要があります。たとえば、Web APIを大量にリクエストする場合、どのAPIがAPIキーを介した認証を必要とし、どのTOSが各キーのリクエストカウントを時間内に制限します。
ケースをより具体的https://domain1/fooNeedNoKey
にお願いしたいのhttps://domain2/fooNeedKeyWithRequestsCountRestrictions
ですが、その回答分析データに応じて、お願いします。これらの1対2のリクエストシーケンスのすべての送信は、単一のorg.apache.http.impl.client.FutureRequestExecutionServiceを介して実行されます。
現在のところ、org.apache.httpcomponents:httpclient:4.3.3に応じて、次のAPI要素を使用しています。
final CloseableHttpClient httpClient = HttpClients.custom() // the auto-retry feature of the Apache API will retry up to 5 // times on failure, being also allowed to send again requests // that were already sent if necessary (I don't really understand // the purpose of the second parameter below) .setRetryHandler(new StandardHttpRequestRetryHandler(5, true)) // for HTTP 503 'Service unavailable' errors, also retrying up to // 5 times, waiting 500ms between each retry. Guessed is that those // 5 retries are part of the previous "global" 5 retries setting. // The below setting, when used alone, would allow to only enable // retries for HTTP 503, or to get a greater count of retries for // this specific error .setServiceUnavailableRetryStrategy(new DefaultServiceUnavailableRetryStrategy(5, 500)) .build();
、ApacheAPIの再試行動作をカスタマイズしますトピックに戻る:
編集1:ApacheAPIではこれを許可しないようです。APIの内部から引用すると、RetryExecはAPIコードI / Oで拡張可能ではありません。
package org.apache.http.impl.execchain;
public class RetryExec implements ClientExecChain {
..
public CloseableHttpResponse execute(
final HttpRoute route,
final HttpRequestWrapper request,
final HttpClientContext context,
final HttpExecutionAware execAware) throws IOException, HttpException {
..
for (int execCount = 1;; execCount++) {
try {
return this.requestExecutor.execute(route, request, context, execAware);
} catch (final IOException ex) {
..
if (retryHandler.retryRequest(ex, execCount, context)) {
..
}
..
}
}
'execCount'変数は必要な情報であり、ローカルでのみ使用されるためアクセスできません。
同様に、「retryHandler」を拡張して、その中のリクエストを手動でカウントすることもできますが、「retryHandler.retryRequest(ex、execCount、context)」には「request」変数が提供されていないため、私たちが何であるかを知ることができません。カウンターのインクリメント(特定のドメインに送信された要求のカウンターのみをインクリメントしたい場合があります)。
私はそれについてのJavaのアイデアが不足しています。サードパーティの代替手段:Javaプロセスにディスク上のファイルをポーリングさせ、必要な要求をカウントするシェルスクリプトによって管理します。確かにそれは多くのディスク読み取りアクセスを行い、ハードウェアキラーオプションになるでしょう。
回避策は簡単でした。APIのHttpContextクラスはこれを目的としています。
// optionnally, in case your HttpCLient is configured for retry
class URIAwareHttpRequestRetryHandler extends StandardHttpRequestRetryHandler {
public URIAwareHttpRequestRetryHandler(final int retryCount, final boolean requestSentRetryEnabled)
{
super(retryCount, requestSentRetryEnabled);
}
@Override
public boolean retryRequest(final IOException exception, final int executionCount, final HttpContext context)
{
final boolean ret = super.retryRequest(exception, executionCount, context);
if (ret) {
doForEachRequestSentOnURI((String) context.getAttribute("requestURI"));
}
return ret;
}
}
// optionnally, in addition to the previous one, in case your HttpClient has specific settings for the 'Service unavailable' errors retries
class URIAwareServiceUnavailableRetryStrategy extends DefaultServiceUnavailableRetryStrategy {
public URIAwareServiceUnavailableRetryStrategy(final int maxRetries, final int retryInterval)
{
super(maxRetries, retryInterval);
}
@Override
public boolean retryRequest(final HttpResponse response, final int executionCount, final HttpContext context)
{
final boolean ret = super.retryRequest(response, executionCount, context);
if (ret) {
doForEachRequestSentOnURI((String) context.getAttribute("requestURI"));
}
return ret;
}
}
// main HTTP querying code: retain the URI in the HttpContext to make it available in the custom retry-handlers code
httpContext.setAttribute("requestURI", httpGET.getURI().toString());
try {
httpContext.setAttribute("requestURI", httpGET.getURI().toString());
httpClient.execute(httpGET, getHTTPResponseHandlerLazy(), httpContext);
// if request got successful with no need of retries, of if it succeeded on the last send: in any cases, this is the last query sent to server and it got successful
doForEachRequestSentOnURI(httpGET.getURI().toString());
} catch (final ClientProtocolException e) {
// if request definitively failed after retries: it's the last query sent to server, and it failed
doForEachRequestSentOnURI(httpGET.getURI().toString());
} catch (final IOException e) {
// if request definitively failed after retries: it's the last query sent to server, and it failed
doForEachRequestSentOnURI(httpGET.getURI().toString());
} finally {
// restoring the context as it was initially
httpContext.removeAttribute("requestURI");
}
解決しました。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加