Skip to content

Commit 12f69ce

Browse files
authored
[issue #189] schema registration error when env is production (#190)
1 parent 22dfece commit 12f69ce

File tree

11 files changed

+164
-29
lines changed

11 files changed

+164
-29
lines changed
Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
package com.huaweicloud.common.schema;
22

3+
import java.util.List;
4+
import java.util.Map;
5+
36
/**
47
* @Author GuoYl123
58
* @Date 2019/12/17
69
**/
710
public interface ServiceCombSwaggerHandler {
811

9-
void initAndRegister(String appName, String serviceName, String microserviceId);
12+
void init(String appName, String serviceName);
13+
14+
void registerSwagger(String microserviceId, List<String> schemas);
15+
16+
List<String> getSchemas();
17+
18+
Map<String, String> getSchemasSummaryMap();
1019
}

spring-cloud-huawei-common/src/main/java/com/huaweicloud/common/transport/BackOff.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ public class BackOff {
1515

1616
private int retryDelayTime = 1000;
1717

18+
public BackOff() {
19+
}
20+
21+
public BackOff(int retryDelayTime) {
22+
this.retryDelayTime = retryDelayTime;
23+
}
24+
1825
public void backOff() {
1926
if (MAX_DELAY_TIME == retryDelayTime) {
2027
return;

spring-cloud-huawei-servicecomb-discovery/src/main/java/com/huaweicloud/servicecomb/discovery/client/ServiceCombClient.java

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,16 @@
1818
package com.huaweicloud.servicecomb.discovery.client;
1919

2020
import com.fasterxml.jackson.core.JsonProcessingException;
21+
import com.fasterxml.jackson.core.type.TypeReference;
22+
import com.fasterxml.jackson.databind.DeserializationFeature;
2123
import com.google.common.base.Charsets;
2224
import com.google.common.collect.Maps;
2325
import com.google.common.hash.Hashing;
26+
import com.huaweicloud.common.exception.ServiceCombRuntimeException;
2427
import com.huaweicloud.common.transport.URLConfig;
2528
import com.huaweicloud.servicecomb.discovery.client.model.HeardBeatStatus;
2629
import com.huaweicloud.servicecomb.discovery.client.model.SchemaRequest;
30+
import com.huaweicloud.servicecomb.discovery.client.model.SchemaResponse;
2731
import com.huaweicloud.servicecomb.discovery.discovery.MicroserviceHandler;
2832
import java.io.IOException;
2933
import java.net.URI;
@@ -34,6 +38,7 @@
3438

3539
import java.util.Map;
3640
import java.util.stream.Collectors;
41+
import javax.lang.model.type.ReferenceType;
3742
import org.apache.http.HttpStatus;
3843
import org.apache.http.client.utils.URIBuilder;
3944
import org.apache.http.entity.ByteArrayEntity;
@@ -195,7 +200,31 @@ public String getServiceId(Microservice microservice) throws ServiceCombExceptio
195200
.readValue(response.getContent(), HashMap.class);
196201
return result.get("serviceId");
197202
} else if (response.getStatusCode() == HttpStatus.SC_BAD_REQUEST) {
198-
LOGGER.info(response.getStatusMessage());
203+
LOGGER.info(response.getContent());
204+
return null;
205+
} else {
206+
throw new RemoteOperationException(
207+
"read response failed. status:" + response.getStatusCode() + "; message:" + response
208+
.getStatusMessage() + "; content:" + response.getContent());
209+
}
210+
} catch (URISyntaxException e) {
211+
throw new RemoteOperationException("build url failed.", e);
212+
} catch (IOException e) {
213+
handleRemoteOperationException(response, e);
214+
}
215+
return null;
216+
}
217+
218+
public SchemaResponse getSchemas(String serviceId) throws ServiceCombException {
219+
Response response = null;
220+
try {
221+
response = httpTransport
222+
.sendGetRequest(buildURI("/registry/microservices/" + serviceId + "/schemas"));
223+
if (response.getStatusCode() == HttpStatus.SC_OK) {
224+
return JsonUtils.OBJ_MAPPER
225+
.readValue(response.getContent(), SchemaResponse.class);
226+
} else if (response.getStatusCode() == HttpStatus.SC_BAD_REQUEST) {
227+
LOGGER.info(response.getContent());
199228
return null;
200229
} else {
201230
throw new RemoteOperationException(
@@ -460,7 +489,8 @@ public boolean registerSchema(String microserviceId, String schemaId, String sch
460489
LOGGER.info("register schema {}/{} success.", microserviceId, schemaId);
461490
return true;
462491
}
463-
LOGGER.error("Register schema {}/{} failed.", microserviceId, schemaId);
492+
LOGGER.error("Register schema {}/{} failed, code:{} , msg:{} ", microserviceId, schemaId,
493+
response.getStatusCode(), response.getContent());
464494
return false;
465495
} catch (JsonProcessingException e) {
466496
LOGGER.error("registerSchema serialization failed : {}", e.getMessage());
@@ -497,6 +527,7 @@ private String addParam2URI(String path, String type, String revision, Microserv
497527
uriBuilder.setParameter("appId", microservice.getAppId());
498528
uriBuilder.setParameter("serviceName", microservice.getServiceName());
499529
uriBuilder.setParameter("version", microservice.getVersion());
530+
uriBuilder.setParameter("env", microservice.getEnvironment());
500531
return uriBuilder.build().toString();
501532
}
502533

spring-cloud-huawei-servicecomb-discovery/src/main/java/com/huaweicloud/servicecomb/discovery/client/model/Framework.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public class Framework {
2525

2626
public static final String DEFAULT_NAME = "springCloud";
2727

28-
public static final String DEFAULT_VERSION = "1.2.0";
28+
public static final String DEFAULT_VERSION = "1.3.2";
2929

3030
private String name = DEFAULT_NAME;
3131

spring-cloud-huawei-servicecomb-discovery/src/main/java/com/huaweicloud/servicecomb/discovery/client/model/SchemaRequest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
package com.huaweicloud.servicecomb.discovery.client.model;
1919

20+
import com.fasterxml.jackson.annotation.JsonIgnore;
21+
2022
/**
2123
* @Author GuoYl123
2224
* @Date 2019/12/18
@@ -25,8 +27,18 @@ public class SchemaRequest {
2527

2628
private String schema;
2729

30+
private String schemaId;
31+
2832
private String summary;
2933

34+
public String getSchemaId() {
35+
return schemaId;
36+
}
37+
38+
public void setSchemaId(String schemaId) {
39+
this.schemaId = schemaId;
40+
}
41+
3042
public String getSchema() {
3143
return schema;
3244
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.huaweicloud.servicecomb.discovery.client.model;
2+
3+
import java.util.List;
4+
5+
/**
6+
* @Author GuoYl123
7+
* @Date 2020/5/9
8+
**/
9+
public class SchemaResponse {
10+
11+
List<SchemaRequest> schemas;
12+
13+
public List<SchemaRequest> getSchemas() {
14+
return schemas;
15+
}
16+
17+
public void setSchemas(
18+
List<SchemaRequest> schemas) {
19+
this.schemas = schemas;
20+
}
21+
}

spring-cloud-huawei-servicecomb-discovery/src/main/java/com/huaweicloud/servicecomb/discovery/registry/HeartbeatScheduler.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -111,15 +111,8 @@ private void refreshLocalMap(String instanceId, ScheduledFuture currentTask) {
111111
private void retryRegister(ServiceCombRegistration registration, String oldInstanceID) {
112112
LOGGER.info("retry registry to service center.");
113113
Microservice microservice = RegistryHandler.buildMicroservice(registration);
114+
String serviceID = RegisterCache.getServiceID();
114115
try {
115-
String serviceID = serviceCombClient.getServiceId(microservice);
116-
if (null == serviceID) {
117-
serviceID = serviceCombClient.registerMicroservice(microservice);
118-
}
119-
if (serviceCombSwaggerHandler != null) {
120-
serviceCombSwaggerHandler.initAndRegister(serviceCombDiscoveryProperties.getAppName(),
121-
serviceCombDiscoveryProperties.getServiceName(), serviceID);
122-
}
123116
MicroserviceInstance microserviceInstance = RegistryHandler
124117
.buildMicroServiceInstances(serviceID, microservice, serviceCombDiscoveryProperties,
125118
tagsProperties);

spring-cloud-huawei-servicecomb-discovery/src/main/java/com/huaweicloud/servicecomb/discovery/registry/ServiceCombServiceRegistry.java

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,15 @@
1717

1818
package com.huaweicloud.servicecomb.discovery.registry;
1919

20+
import com.huaweicloud.common.exception.ServiceCombRuntimeException;
2021
import com.huaweicloud.common.schema.ServiceCombSwaggerHandler;
22+
import com.huaweicloud.servicecomb.discovery.client.model.SchemaResponse;
2123
import com.huaweicloud.servicecomb.discovery.client.model.ServiceRegistryConfig;
2224
import java.net.URI;
2325
import java.net.URISyntaxException;
26+
import java.util.ArrayList;
27+
import java.util.List;
28+
import java.util.Map;
2429
import org.slf4j.Logger;
2530
import org.slf4j.LoggerFactory;
2631
import org.springframework.beans.factory.annotation.Autowired;
@@ -97,15 +102,22 @@ private void startWatch() {
97102

98103
private void loopRegister(ServiceCombRegistration registration) {
99104
Microservice microservice = RegistryHandler.buildMicroservice(registration);
105+
if (serviceCombSwaggerHandler != null) {
106+
serviceCombSwaggerHandler.init(serviceCombDiscoveryProperties.getAppName(),
107+
serviceCombDiscoveryProperties.getServiceName());
108+
microservice.setSchemas(serviceCombSwaggerHandler.getSchemas());
109+
}
100110
while (true) {
101111
try {
102112
serviceID = serviceCombClient.getServiceId(microservice);
103113
if (null == serviceID) {
104114
serviceID = serviceCombClient.registerMicroservice(microservice);
105-
}
106-
if (serviceCombSwaggerHandler != null) {
107-
serviceCombSwaggerHandler.initAndRegister(serviceCombDiscoveryProperties.getAppName(),
108-
serviceCombDiscoveryProperties.getServiceName(), serviceID);
115+
if (serviceCombSwaggerHandler != null) {
116+
serviceCombSwaggerHandler.registerSwagger(serviceID, microservice.getSchemas());
117+
}
118+
} else if (serviceCombSwaggerHandler != null) {
119+
List<String> schemas = filterSchema(serviceCombSwaggerHandler.getSchemasSummaryMap());
120+
serviceCombSwaggerHandler.registerSwagger(serviceID, schemas);
109121
}
110122
MicroserviceInstance microserviceInstance = RegistryHandler
111123
.buildMicroServiceInstances(serviceID, microservice, serviceCombDiscoveryProperties,
@@ -123,6 +135,36 @@ private void loopRegister(ServiceCombRegistration registration) {
123135
}
124136
}
125137

138+
/**
139+
* production时:
140+
* 1.先检查,对于已经注册的契约:i.没有删除 ii.没有summary变更的schema
141+
* 2.检查不通过 启动失败
142+
* 3.检查成功,只注册新增的接口
143+
* 非production时:
144+
* 1.全部重新注册
145+
*
146+
* @param localSchemas
147+
* @return
148+
* @throws ServiceCombException
149+
*/
150+
private List<String> filterSchema(Map<String, String> localSchemas) throws ServiceCombException {
151+
152+
if (!serviceCombDiscoveryProperties.getEnvironment().equals("production")) {
153+
return new ArrayList<>(localSchemas.keySet());
154+
}
155+
SchemaResponse schemas = serviceCombClient.getSchemas(serviceID);
156+
schemas.getSchemas().forEach(schema -> {
157+
if (!localSchemas.containsKey(schema.getSchemaId()) ||
158+
!localSchemas.get(schema.getSchemaId()).equals(schema.getSummary())) {
159+
LOGGER.warn(
160+
"schemas {} is changed , won't registry. if want to overwrite schema please upgrade version.",
161+
schema.getSchemaId());
162+
}
163+
localSchemas.remove(schema.getSchemaId());
164+
});
165+
return new ArrayList<>(localSchemas.keySet());
166+
}
167+
126168
@Override
127169
public void deregister(ServiceCombRegistration registration) {
128170
heartbeatScheduler.remove();

spring-cloud-huawei-servicecomb-discovery/src/main/java/com/huaweicloud/servicecomb/discovery/registry/ServiceCombWatcher.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public class ServiceCombWatcher {
2727

2828
private String url;
2929

30-
private BackOff backOff = new BackOff();
30+
private BackOff backOff = new BackOff(5000);
3131

3232
private ScheduledExecutorService EXECUTOR = Executors.newScheduledThreadPool(1, (r) -> {
3333
Thread thread = new Thread(r);

spring-cloud-huawei-swagger/src/main/java/com/huaweicloud/swagger/ServiceCombSwaggerHandlerImpl.java

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
package com.huaweicloud.swagger;
1818

1919
import com.fasterxml.jackson.core.JsonProcessingException;
20+
import com.google.common.base.Charsets;
2021
import com.google.common.collect.HashMultimap;
2122
import com.google.common.collect.Multimap;
23+
import com.google.common.hash.Hashing;
2224
import com.huaweicloud.common.exception.RemoteOperationException;
2325
import com.huaweicloud.common.schema.ServiceCombSwaggerHandler;
2426
import com.huaweicloud.servicecomb.discovery.client.ServiceCombClient;
@@ -35,9 +37,11 @@
3537
import java.util.Iterator;
3638
import java.util.List;
3739
import java.util.Map;
40+
import java.util.Map.Entry;
3841
import java.util.Set;
3942
import java.util.StringJoiner;
4043
import java.util.concurrent.Executors;
44+
import java.util.stream.Collectors;
4145
import org.slf4j.Logger;
4246
import org.slf4j.LoggerFactory;
4347
import org.springframework.beans.factory.annotation.Autowired;
@@ -83,7 +87,7 @@ public class ServiceCombSwaggerHandlerImpl implements ServiceCombSwaggerHandler
8387
/**
8488
* Split registration
8589
*/
86-
private void init(String appName, String serviceName) {
90+
public void init(String appName, String serviceName) {
8791
Documentation documentation = documentationCache
8892
.documentationByGroup(Docket.DEFAULT_GROUP_NAME);
8993
if (documentation == null) {
@@ -137,29 +141,41 @@ private void init(String appName, String serviceName) {
137141
return;
138142
}
139143

140-
public void initAndRegister(String appName, String serviceName, String microserviceId) {
141-
init(appName, serviceName);
142-
if (swaggerMap.isEmpty()) {
143-
return;
144-
}
145-
registerSwagger(microserviceId, new ArrayList<>(swaggerMap.keySet()));
146-
}
147-
148144
/**
149145
* todo: schema generate also can be async , use aop around method
150146
* schema注册调用接口可以改为异步,在和java-chassis组网场景下需要同步加载
151147
*
152148
* @param microserviceId
153149
* @param schemaIds
154150
*/
155-
private void registerSwagger(String microserviceId, List<String> schemaIds) {
151+
public void registerSwagger(String microserviceId, List<String> schemaIds) {
156152
if (withJavaChassis) {
157153
registerSwaggerSync(microserviceId, schemaIds);
158154
} else {
159155
registerSwaggerAsync(microserviceId, schemaIds);
160156
}
161157
}
162158

159+
public List<String> getSchemas() {
160+
return new ArrayList<>(swaggerMap.keySet());
161+
}
162+
163+
public Map<String, String> getSchemasSummaryMap() {
164+
return swaggerMap.entrySet().stream()
165+
.collect(Collectors.toMap(Entry::getKey, entry -> {
166+
try {
167+
return calcSchemaSummary(Yaml.mapper().writeValueAsString(entry.getValue()));
168+
} catch (JsonProcessingException e) {
169+
LOGGER.error("error when calcSchemaSummary.");
170+
}
171+
return null;
172+
}));
173+
}
174+
175+
private static String calcSchemaSummary(String schemaContent) {
176+
return Hashing.sha256().newHasher().putString(schemaContent, Charsets.UTF_8).hash().toString();
177+
}
178+
163179
/**
164180
* for every method delete UsingGET/UsingXXXX at the end of operationId
165181
* a method with different httpMethod need be abandoned

0 commit comments

Comments
 (0)