[
https://issues.apache.org/jira/browse/SCB-652?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16507756#comment-16507756
]
ASF GitHub Bot commented on SCB-652:
------------------------------------
wujimin commented on a change in pull request #757: [SCB-652] Fix schema
register logic
URL:
https://github.com/apache/incubator-servicecomb-java-chassis/pull/757#discussion_r194313371
##########
File path:
service-registry/src/main/java/org/apache/servicecomb/serviceregistry/task/MicroserviceRegisterTask.java
##########
@@ -127,76 +133,207 @@ private boolean checkSchemaIdSet() {
schemaIdSetMatch = existSchemas.equals(localSchemas);
if (!schemaIdSetMatch) {
- LOGGER.error(
- "SchemaIds is different between local and service center. Please
change microservice version. "
- + "id={} appId={}, name={}, version={}, local schemaIds={},
service center schemaIds={}",
+ LOGGER.warn(
+ "SchemaIds is different between local and service center. "
+ + "serviceId=[{}] appId=[{}], name=[{}], version=[{}], env=[{}],
local schemaIds={}, service center schemaIds={}",
microservice.getServiceId(),
microservice.getAppId(),
microservice.getServiceName(),
microservice.getVersion(),
+ microservice.getEnvironment(),
localSchemas,
existSchemas);
return true;
}
LOGGER.info(
- "SchemaIds is equals to service center. id={} appId={}, name={},
version={}, schemaIds={}",
+ "SchemaIds are equals to service center. serviceId=[{}], appId=[{}],
name=[{}], version=[{}], env=[{}], schemaIds={}",
microservice.getServiceId(),
microservice.getAppId(),
microservice.getServiceName(),
microservice.getVersion(),
+ microservice.getEnvironment(),
localSchemas);
return true;
}
private boolean registerSchemas() {
- List<GetSchemaResponse> existSchemas =
srClient.getSchemas(microservice.getServiceId());
- for (Entry<String, String> entry : microservice.getSchemaMap().entrySet())
{
- String schemaId = entry.getKey();
- String content = entry.getValue();
- GetSchemaResponse existSchema = extractSchema(schemaId, existSchemas);
- boolean exists = existSchema != null && existSchema.getSummary() != null;
- LOGGER.info("schemaId [{}] exists {}", schemaId, exists);
- if (!exists) {
- if (!srClient.registerSchema(microservice.getServiceId(), schemaId,
content)) {
- return false;
- }
- } else {
- String curSchemaSummary = existSchema.getSummary();
- String schemaSummary = Hashing.sha256().newHasher().putString(content,
Charsets.UTF_8).hash().toString();
- if (!schemaSummary.equals(curSchemaSummary)) {
- if
(microservice.getEnvironment().equalsIgnoreCase(ServiceCombConstants.DEVELOPMENT_SERVICECOMB_ENV))
{
- LOGGER.info(
- "schemaId [{}]'s content changes and the current environment
is {}, so re-register it!",
- schemaId, ServiceCombConstants.DEVELOPMENT_SERVICECOMB_ENV);
- if (!srClient.registerSchema(microservice.getServiceId(),
schemaId, content)) {
- return false;
- }
- } else {
- throw new IllegalStateException("schemaId [" + schemaId
- + "] exists in service center, but the content does not match
the local content that means there are interface change "
- + "and you need to increment microservice version before
deploying. "
- + "Or you can configure service_description.environment="
- + ServiceCombConstants.DEVELOPMENT_SERVICECOMB_ENV
- + " to work in development environment and ignore this error");
- }
- }
+ Holder<List<GetSchemaResponse>> scSchemaHolder =
srClient.getSchemas(microservice.getServiceId());
+ if (Status.OK.getStatusCode() != scSchemaHolder.getStatusCode()) {
+ LOGGER.error("failed to get schemas from service center, statusCode =
[{}]", scSchemaHolder.getStatusCode());
+ return false;
+ }
+
+ Map<String, GetSchemaResponse> scSchemaMap =
convertScSchemaMap(scSchemaHolder);
+ // CHECK: local > sc, local != sc
+ for (Entry<String, String> localSchemaEntry :
microservice.getSchemaMap().entrySet()) {
+ if (!registerSchema(scSchemaMap, localSchemaEntry)) {
+ return false;
+ }
+ }
+
+ // CHECK: local < sc
+ checkRemainingSchema(scSchemaMap);
+
+ schemaIdSetMatch = true;
+ return true;
+ }
+
+ /**
+ * Check whether a local schema is equal to a sc schema.
+ * @return true if the local schema is equal to a sc schema, or be
registered to sc successfully;
+ * false if schema is registered to sc but failed.
+ * @throws IllegalStateException The environment is not modifiable, and the
local schema is different from sc schema
+ * or not exist in sc.
+ */
+ private boolean registerSchema(Map<String, GetSchemaResponse> scSchemaMap,
+ Entry<String, String> localSchemaEntry) {
+ GetSchemaResponse scSchema = scSchemaMap.get(localSchemaEntry.getKey());
+
+ boolean onlineSchemaExists = scSchema != null;
+ LOGGER.info("schemaId [{}] exists [{}], summary exists [{}]",
localSchemaEntry.getKey(), onlineSchemaExists,
+ scSchema != null && scSchema.getSummary() != null);
+ if (!onlineSchemaExists) {
+ // local > sc
+ return registerNewSchema(localSchemaEntry);
+ }
+
+ scSchemaMap.remove(localSchemaEntry.getKey());
+
+ // local != sc
+ return compareAndReRegisterSchema(localSchemaEntry, scSchema);
+ }
+
+ /**
+ * Try to register a new schema to service center, or throw exception if
cannot register.
+ * @param localSchemaEntry local schema to be registered.
+ * @return whether local schema is registered successfully.
+ * @throws IllegalStateException The environment is unmodifiable.
+ */
+ private boolean registerNewSchema(Entry<String, String> localSchemaEntry) {
+ // The ids of schemas are contained by microservice registry request,
which means once a microservice
+ // is registered in the service center, the schemas that it contains are
determined.
+ // If we get a microservice but cannot find the given schemaId in it's
schemaId list, this means that
+ // the schemas of this microservice has been changed, and we should decide
whether to register this new
+ // schema according to it's environment configuration.
+ if (onlineSchemaIsModifiable()) {
+ return registerSingleSchema(localSchemaEntry.getKey(),
localSchemaEntry.getValue());
+ }
+
+ throw new IllegalStateException(
+ "There is a schema only existing in local microservice: [" +
localSchemaEntry.getKey()
+ + "], which means there are interfaces changed. "
+ + "You need to increment microservice version before deploying, "
+ + "or you can configure service_description.environment="
+ + ServiceCombConstants.DEVELOPMENT_SERVICECOMB_ENV
+ + " to work in development environment and ignore this error");
+ }
+
+ /**
+ * Compare schema summary and determine whether to re-register schema or
throw exception.
+ * @param localSchemaEntry local schema
+ * @param scSchema schema in service center
+ * @return true if the two copies of schema are the same, or local schema is
re-registered successfully,
+ * false if the local schema is re-registered to service center but failed.
+ * @throws IllegalStateException The two copies of schema are different and
the environment is not modifiable.
+ */
+ private boolean compareAndReRegisterSchema(Entry<String, String>
localSchemaEntry, GetSchemaResponse scSchema) {
+ String scSchemaSummary = getScSchemaSummary(scSchema);
+
+ if (null == scSchemaSummary) {
+ // cannot get scSchemaSummary, which means there is no schema content in
sc, register schema directly
+ return registerSingleSchema(localSchemaEntry.getKey(),
localSchemaEntry.getValue());
+ }
+
+ String localSchemaSummary =
RegistryUtils.calcSchemaSummary(localSchemaEntry.getValue());
+ if (!localSchemaSummary.equals(scSchemaSummary)) {
+ if (onlineSchemaIsModifiable()) {
+ LOGGER.info(
+ "schema[{}]'s content is changed and the current environment is
[{}], so re-register it!",
+ localSchemaEntry.getKey(),
ServiceCombConstants.DEVELOPMENT_SERVICECOMB_ENV);
+ return registerSingleSchema(localSchemaEntry.getKey(),
localSchemaEntry.getValue());
}
+
+ // env is not development, throw an exception and break the init
procedure
+ throw new IllegalStateException(
+ "The schema(id=[" + localSchemaEntry.getKey()
+ + "]) content held by this instance and the service center is
different. "
+ + "You need to increment microservice version before deploying. "
+ + "Or you can configure service_description.environment="
+ + ServiceCombConstants.DEVELOPMENT_SERVICECOMB_ENV
+ + " to work in development environment and ignore this error");
}
+
+ // summaries are the same
return true;
}
- private GetSchemaResponse extractSchema(String schemaId,
List<GetSchemaResponse> schemas) {
- if (schemas == null || schemas.isEmpty()) {
- return null;
+ /**
+ * Try to get or calculate scSchema summary.
+ * @return summary of scSchema,
+ * or null if there is no schema content in service center
+ */
+ private String getScSchemaSummary(GetSchemaResponse scSchema) {
+ String scSchemaSummary = scSchema.getSummary();
+ if (null != scSchemaSummary) {
+ return scSchemaSummary;
}
- GetSchemaResponse schema = null;
- for (GetSchemaResponse tempSchema : schemas) {
- if (tempSchema.getSchemaId().equals(schemaId)) {
- schema = tempSchema;
- break;
+
+ // if there is no online summery, query online schema content directly and
calculate summary
+ String onlineSchemaContent =
srClient.getSchema(microservice.getServiceId(), scSchema.getSchemaId());
+ if (null != onlineSchemaContent) {
+ scSchemaSummary = RegistryUtils.calcSchemaSummary(onlineSchemaContent);
+ }
+
+ return scSchemaSummary;
+ }
+
+ /**
+ * Check whether there are schemas remaining in service center but not exist
in local microservice.
+ * @throws IllegalStateException There are schemas only existing in service
center, and the environment is unmodifiable.
+ */
+ private void checkRemainingSchema(Map<String, GetSchemaResponse>
scSchemaMap) {
+ if (!scSchemaMap.isEmpty()) {
+ // there are some schemas only exist in service center
+ if (!onlineSchemaIsModifiable()) {
+ // env is not development, throw an exception and break the init
procedure
+ throw new IllegalStateException("There are schemas only existing in
service center: " + scSchemaMap.keySet()
+ + ", which means there are interfaces changed. "
+ + "You need to increment microservice version before deploying, "
+ + "or if service_description.environment="
+ + ServiceCombConstants.DEVELOPMENT_SERVICECOMB_ENV
+ + ", you can delete microservice information in service center and
restart this instance.");
}
+
+ // Currently nothing to do but print a warning
+ LOGGER.warn("There are schemas only existing in service center: {},
which means there are interfaces changed. "
Review comment:
change microservice version just only make it can deploy
but it's not compatible, it's better write something about this in log.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
> Fix schema registry environment configuration
> ---------------------------------------------
>
> Key: SCB-652
> URL: https://issues.apache.org/jira/browse/SCB-652
> Project: Apache ServiceComb
> Issue Type: Bug
> Components: Java-Chassis
> Reporter: YaoHaishi
> Assignee: YaoHaishi
> Priority: Major
> Attachments: SchemaRegisterFlowChart.svg
>
>
> In schema registry, change environment config from
> instance_description.environment to service_description.environment and
> improve the registry logic.
> There is a flow chart in attatchments for reference:
> [^SchemaRegisterFlowChart.svg]
> If schema registry fails, the bootup procedure will be terminated or the
> registry task will be rerun until the registry success.
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)