Skip to content

Commit 389015d

Browse files
committed
feat: Support retry in open api client
(cherry picked from commit 56a47ed)
1 parent 5821922 commit 389015d

File tree

3 files changed

+56
-2
lines changed

3 files changed

+56
-2
lines changed

apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/client/ApolloOpenApiClient.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.ctrip.framework.apollo.openapi.client;
1818

1919
import com.ctrip.framework.apollo.openapi.client.constant.ApolloOpenApiConstants;
20+
import com.ctrip.framework.apollo.openapi.client.extend.ApolloStandardHttpRequestRetryHandler;
2021
import com.ctrip.framework.apollo.openapi.client.service.AppOpenApiService;
2122
import com.ctrip.framework.apollo.openapi.client.service.ClusterOpenApiService;
2223
import com.ctrip.framework.apollo.openapi.client.service.ItemOpenApiService;
@@ -55,10 +56,11 @@ public class ApolloOpenApiClient {
5556
private final InstanceOpenApiService instanceService;
5657
private static final Gson GSON = new GsonBuilder().setDateFormat(ApolloOpenApiConstants.JSON_DATE_FORMAT).create();
5758

58-
private ApolloOpenApiClient(String portalUrl, String token, RequestConfig requestConfig) {
59+
private ApolloOpenApiClient(String portalUrl, String token, RequestConfig requestConfig, int retryCount) {
5960
this.portalUrl = portalUrl;
6061
this.token = token;
6162
CloseableHttpClient client = HttpClients.custom().setDefaultRequestConfig(requestConfig)
63+
.setRetryHandler(retryCount > 0 ? new ApolloStandardHttpRequestRetryHandler(retryCount) : null)
6264
.setDefaultHeaders(Lists.newArrayList(new BasicHeader("Authorization", token))).build();
6365

6466
String baseUrl = this.portalUrl + ApolloOpenApiConstants.OPEN_API_V1_PREFIX;
@@ -273,6 +275,7 @@ public static class ApolloOpenApiClientBuilder {
273275
private String token;
274276
private int connectTimeout = -1;
275277
private int readTimeout = -1;
278+
private int retryCount = -1;
276279

277280
/**
278281
* @param portalUrl The apollo portal url, e.g http://localhost:8070
@@ -306,6 +309,11 @@ public ApolloOpenApiClientBuilder withReadTimeout(int readTimeout) {
306309
return this;
307310
}
308311

312+
public ApolloOpenApiClientBuilder withRetryCount(int retryCount) {
313+
this.retryCount = retryCount;
314+
return this;
315+
}
316+
309317
public ApolloOpenApiClient build() {
310318
Preconditions.checkArgument(!Strings.isNullOrEmpty(portalUrl), "Portal url should not be null or empty!");
311319
Preconditions.checkArgument(portalUrl.startsWith("http://") || portalUrl.startsWith("https://"), "Portal url should start with http:// or https://" );
@@ -322,7 +330,7 @@ public ApolloOpenApiClient build() {
322330
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connectTimeout)
323331
.setSocketTimeout(readTimeout).build();
324332

325-
return new ApolloOpenApiClient(portalUrl, token, requestConfig);
333+
return new ApolloOpenApiClient(portalUrl, token, requestConfig, retryCount);
326334
}
327335
}
328336
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.ctrip.framework.apollo.openapi.client.extend;
2+
3+
import org.apache.http.HttpRequest;
4+
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
5+
6+
import javax.net.ssl.SSLException;
7+
import java.net.ConnectException;
8+
import java.net.NoRouteToHostException;
9+
import java.net.UnknownHostException;
10+
import java.util.Arrays;
11+
import java.util.Locale;
12+
import java.util.Map;
13+
import java.util.concurrent.ConcurrentHashMap;
14+
15+
/**
16+
*
17+
* @author zth9
18+
* @date 2025-05-07
19+
*/
20+
public class ApolloStandardHttpRequestRetryHandler extends DefaultHttpRequestRetryHandler {
21+
22+
private final Map<String, Boolean> idempotentMethods;
23+
24+
public ApolloStandardHttpRequestRetryHandler(int retryCount) {
25+
super(retryCount, true, Arrays.asList(
26+
UnknownHostException.class,
27+
ConnectException.class,
28+
NoRouteToHostException.class,
29+
SSLException.class));
30+
this.idempotentMethods = new ConcurrentHashMap<>();
31+
this.idempotentMethods.put("GET", Boolean.TRUE);
32+
this.idempotentMethods.put("HEAD", Boolean.TRUE);
33+
this.idempotentMethods.put("PUT", Boolean.TRUE);
34+
this.idempotentMethods.put("DELETE", Boolean.TRUE);
35+
this.idempotentMethods.put("OPTIONS", Boolean.TRUE);
36+
this.idempotentMethods.put("TRACE", Boolean.TRUE);
37+
}
38+
39+
@Override
40+
protected boolean handleAsIdempotent(final HttpRequest request) {
41+
final String method = request.getRequestLine().getMethod().toUpperCase(Locale.ROOT);
42+
final Boolean b = this.idempotentMethods.get(method);
43+
return b != null && b.booleanValue();
44+
}
45+
}

apollo-openapi/src/test/java/com/ctrip/framework/apollo/openapi/client/ApolloOpenApiClientIntegrationTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ ApolloOpenApiClient newClient() {
6363
.withToken(someToken)
6464
.withReadTimeout(2000 * 1000)
6565
.withConnectTimeout(2000 * 1000)
66+
.withRetryCount(3)
6667
.build();
6768
}
6869

0 commit comments

Comments
 (0)