Skip to content

Commit 66b2dfb

Browse files
committed
feat: Support retry in open api client
1 parent 5821922 commit 66b2dfb

File tree

4 files changed

+73
-2
lines changed

4 files changed

+73
-2
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Apollo Java 2.5.0
88

99
* [Feature Provide a new open APl to return the organization list](https://github.com/apolloconfig/apollo-java/pull/102)
1010
* [Feature Added a new feature to get instance count by namespace.](https://github.com/apolloconfig/apollo-java/pull/103)
11+
* [Feature Support retry in open api client.](https://github.com/apolloconfig/apollo-java/pull/105)
1112

1213
------------------
1314
All issues and pull requests are [here](https://github.com/apolloconfig/apollo-java/milestone/5?closed=1)

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: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright 2022 Apollo Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
package com.ctrip.framework.apollo.openapi.client.extend;
18+
19+
import org.apache.http.HttpRequest;
20+
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
21+
22+
import javax.net.ssl.SSLException;
23+
import java.net.ConnectException;
24+
import java.net.NoRouteToHostException;
25+
import java.net.UnknownHostException;
26+
import java.util.Arrays;
27+
import java.util.Locale;
28+
import java.util.Map;
29+
import java.util.concurrent.ConcurrentHashMap;
30+
31+
/**
32+
*
33+
* @author zth9
34+
* @date 2025-05-07
35+
*/
36+
public class ApolloStandardHttpRequestRetryHandler extends DefaultHttpRequestRetryHandler {
37+
38+
private final Map<String, Boolean> idempotentMethods;
39+
40+
public ApolloStandardHttpRequestRetryHandler(int retryCount) {
41+
super(retryCount, true, Arrays.asList(
42+
UnknownHostException.class,
43+
ConnectException.class,
44+
NoRouteToHostException.class,
45+
SSLException.class));
46+
this.idempotentMethods = new ConcurrentHashMap<>();
47+
this.idempotentMethods.put("GET", Boolean.TRUE);
48+
this.idempotentMethods.put("HEAD", Boolean.TRUE);
49+
this.idempotentMethods.put("PUT", Boolean.TRUE);
50+
this.idempotentMethods.put("DELETE", Boolean.TRUE);
51+
this.idempotentMethods.put("OPTIONS", Boolean.TRUE);
52+
this.idempotentMethods.put("TRACE", Boolean.TRUE);
53+
}
54+
55+
@Override
56+
protected boolean handleAsIdempotent(final HttpRequest request) {
57+
final String method = request.getRequestLine().getMethod().toUpperCase(Locale.ROOT);
58+
final Boolean b = this.idempotentMethods.get(method);
59+
return b != null && b.booleanValue();
60+
}
61+
}

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)