You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2020/11/25 03:51:45 UTC
[servicecomb-java-chassis] branch master updated: [SCB-2125] third
service support multi schemas (#2078)
This is an automated email from the ASF dual-hosted git repository.
liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git
The following commit(s) were added to refs/heads/master by this push:
new b307b38 [SCB-2125] third service support multi schemas (#2078)
b307b38 is described below
commit b307b380d1c73e8d06b181972f2a83e9f3e1ad3d
Author: wujimin <wu...@huawei.com>
AuthorDate: Wed Nov 25 11:51:13 2020 +0800
[SCB-2125] third service support multi schemas (#2078)
---
.../core/registry/ThirdServiceRegister.java | 179 +++++++++++++++++++++
.../demo/springmvc/client/SpringmvcClient.java | 11 ++
.../demo/springmvc/client/ThirdSvc.java | 46 ++++++
.../src/main/resources/microservice.yaml | 7 +-
.../consumer/StaticMicroserviceVersions.java | 86 +++++-----
.../registry/ThirdServiceWithInvokerRegister.java | 80 +++++++++
6 files changed, 369 insertions(+), 40 deletions(-)
diff --git a/core/src/main/java/org/apache/servicecomb/core/registry/ThirdServiceRegister.java b/core/src/main/java/org/apache/servicecomb/core/registry/ThirdServiceRegister.java
new file mode 100644
index 0000000..3c76938
--- /dev/null
+++ b/core/src/main/java/org/apache/servicecomb/core/registry/ThirdServiceRegister.java
@@ -0,0 +1,179 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.core.registry;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.apache.servicecomb.core.BootListener;
+import org.apache.servicecomb.core.invocation.endpoint.EndpointUtils;
+import org.apache.servicecomb.registry.DiscoveryManager;
+import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
+import org.apache.servicecomb.registry.consumer.MicroserviceVersions;
+import org.apache.servicecomb.registry.consumer.StaticMicroserviceVersions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.EnvironmentAware;
+import org.springframework.core.env.Environment;
+import org.springframework.util.CollectionUtils;
+
+/**
+ * <pre>
+ * for declare a 3rd service as a servicecomb service
+ * assume a 3rd service:
+ * 1. named svc
+ * 2. have 2 address: https://svc-1 and https://svc-2
+ * 3. have 2 schemas: schema1 and schema2
+ *
+ * usage:
+ * 1. define schema interface in JAX-RS or springMVC mode
+ * 1) schema1
+ * {@code
+ * @Path("/v1/svc")
+ * public interface Schema1Client {
+ * @GET
+ * @Path("/add")
+ * int add(@QueryParam("q-x") int x, @QueryParam("q-y") int y);
+ *
+ * @GET
+ * @Path("/minus")
+ * int minus(@QueryParam("q-x") int x, @QueryParam("q-y") int y);
+ * }
+ * }
+ * 2) schema2
+ * 2. add configuration to microservice.yaml
+ * {@code
+ * svc:
+ * urls:
+ * - https://svc-1
+ * - https://svc-2
+ * }
+ * 3. declare the 3rd service
+ * {@code
+ * @Configuration
+ * public class Svc extends ThirdServiceRegister {
+ * public static final String NAME = "svc";
+ *
+ * public Svc() {
+ * super(NAME);
+ *
+ * addSchema("schema1", Schema1Client.class);
+ * addSchema("schema2", Schema2Client.class);
+ * }
+ * }
+ * }
+ * </pre>
+ */
+public abstract class ThirdServiceRegister implements BootListener, EnvironmentAware {
+ private static final Logger LOGGER = LoggerFactory.getLogger(ThirdServiceRegister.class);
+
+ public static final int ORDER = -1000;
+
+ private static final String VERSION = "1.0";
+
+ /**
+ * role: {@link EndpointUtils}<br>
+ * default to any address
+ */
+ protected List<String> urls = Collections.singletonList("http://127.0.0.1");
+
+ protected String appId;
+
+ protected final String microserviceName;
+
+ // for 3rd service, schema interface is client interface too
+ protected final Map<String, Class<?>> schemaByIdMap = new HashMap<>();
+
+ public ThirdServiceRegister(String microserviceName) {
+ this.microserviceName = microserviceName;
+ }
+
+ @Override
+ public int getOrder() {
+ return ORDER;
+ }
+
+ public List<String> getUrls() {
+ return urls;
+ }
+
+ @Override
+ public void setEnvironment(Environment environment) {
+ String urlKey = microserviceName + ".urls";
+ @SuppressWarnings("unchecked")
+ List<String> urls = environment.getProperty(urlKey, List.class);
+ setUrls(urlKey, urls);
+ }
+
+ public void setUrls(String urlKey, List<String> urls) {
+ if (CollectionUtils.isEmpty(urls)) {
+ LOGGER.warn("missing configuration, key = {}", urlKey);
+ return;
+ }
+
+ this.urls = urls;
+ }
+
+ protected void addSchema(String schemaId, Class<?> schemaCls) {
+ schemaByIdMap.put(schemaId, schemaCls);
+ }
+
+ @Override
+ public void onAfterRegistry(BootEvent event) {
+ appId = event.getScbEngine().getAppId();
+ registerMicroserviceMapping();
+ }
+
+ protected void registerMicroserviceMapping() {
+ List<String> endpoints = createEndpoints();
+ List<MicroserviceInstance> instances = createInstances(endpoints);
+
+ DiscoveryManager.INSTANCE.getAppManager()
+ .getOrCreateMicroserviceManager(appId)
+ .getVersionsByName()
+ .computeIfAbsent(microserviceName, svcName -> createMicroserviceVersions(instances));
+
+ LOGGER.info("register third service, name={}, endpoints={}.", microserviceName, endpoints);
+ }
+
+ protected List<String> createEndpoints() {
+ return urls.stream()
+ .map(EndpointUtils::formatFromUri)
+ .collect(Collectors.toList());
+ }
+
+ protected List<MicroserviceInstance> createInstances(List<String> endpoints) {
+ return endpoints.stream()
+ .map(endpoint -> {
+ MicroserviceInstance instance = new MicroserviceInstance();
+ instance.setEndpoints(Collections.singletonList(endpoint));
+ return instance;
+ })
+ .collect(Collectors.toList());
+ }
+
+ protected MicroserviceVersions createMicroserviceVersions(List<MicroserviceInstance> instances) {
+ return new StaticMicroserviceVersions(
+ DiscoveryManager.INSTANCE.getAppManager(),
+ appId,
+ microserviceName)
+ .init(schemaByIdMap, VERSION, instances);
+ }
+}
diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java
index 6f7bdde..e8c31a1 100644
--- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java
@@ -17,6 +17,7 @@
package org.apache.servicecomb.demo.springmvc.client;
+import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@@ -26,6 +27,7 @@ import org.apache.servicecomb.demo.DemoConst;
import org.apache.servicecomb.demo.TestMgr;
import org.apache.servicecomb.demo.controller.Controller;
import org.apache.servicecomb.demo.controller.Person;
+import org.apache.servicecomb.demo.springmvc.client.ThirdSvc.ThirdSvcClient;
import org.apache.servicecomb.foundation.common.utils.BeanUtils;
import org.apache.servicecomb.foundation.common.utils.Log4jUtils;
import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
@@ -205,9 +207,18 @@ public class SpringmvcClient {
testRequiredBody(templateUrlWithServiceName, microserviceName);
testSpringMvcDefaultValuesAllTransport(templateUrlWithServiceName, microserviceName);
testSpringMvcDefaultValuesJavaPrimitiveAllTransport(templateUrlWithServiceName, microserviceName);
+ testThirdService();
}
}
+ private static void testThirdService() {
+ ThirdSvcClient client = BeanUtils.getContext().getBean(ThirdSvcClient.class);
+
+ Date date = new Date();
+ ResponseEntity<Date> responseEntity = client.responseEntity(date);
+ TestMgr.check(date, responseEntity.getBody());
+ }
+
private static void testControllerRest(RestTemplate template, String microserviceName) {
String prefix = "cse://" + microserviceName;
diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ThirdSvc.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ThirdSvc.java
new file mode 100644
index 0000000..ae855e2
--- /dev/null
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ThirdSvc.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.demo.springmvc.client;
+
+import java.util.Date;
+
+import org.apache.servicecomb.provider.pojo.registry.ThirdServiceWithInvokerRegister;
+import org.apache.servicecomb.swagger.extend.annotations.ResponseHeaders;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RequestAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import io.swagger.annotations.ResponseHeader;
+
+@Configuration
+public class ThirdSvc extends ThirdServiceWithInvokerRegister {
+ @RequestMapping(path = "/codeFirstSpringmvc")
+ public interface ThirdSvcClient {
+ @ResponseHeaders({@ResponseHeader(name = "h1", response = String.class),
+ @ResponseHeader(name = "h2", response = String.class)})
+ @RequestMapping(path = "/responseEntity", method = RequestMethod.POST)
+ ResponseEntity<Date> responseEntity(@RequestAttribute("date") Date date);
+ }
+
+ public ThirdSvc() {
+ super("3rd-svc");
+
+ addSchema("schema-1", ThirdSvcClient.class);
+ }
+}
diff --git a/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml b/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml
index 95b2b43..cc63f46 100644
--- a/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml
+++ b/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml
@@ -35,7 +35,7 @@ servicecomb:
interval: 90
watch: true
autodiscovery: true
-# can download config center from https://cse-bucket.obs.myhwclouds.com/LocalCSE/Local-CSE-1.0.0.zip to test dynamic config
+ # can download config center from https://cse-bucket.obs.myhwclouds.com/LocalCSE/Local-CSE-1.0.0.zip to test dynamic config
config:
client:
serverUri: http://127.0.0.1:30113
@@ -127,6 +127,11 @@ cse:
timeoutInMilliseconds: 1000
test:
duplicate2: newer
+
+3rd-svc:
+ urls:
+ - http://localhost:8080
+
#########SSL options
ssl.protocols: TLSv1.2
ssl.authPeer: true
diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/StaticMicroserviceVersions.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/StaticMicroserviceVersions.java
index 6a249e4..08f1fdd 100644
--- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/StaticMicroserviceVersions.java
+++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/StaticMicroserviceVersions.java
@@ -18,61 +18,82 @@
package org.apache.servicecomb.registry.consumer;
import java.util.List;
-import java.util.UUID;
+import java.util.Map;
+import org.apache.servicecomb.registry.RegistrationManager;
import org.apache.servicecomb.registry.api.registry.FindInstancesResponse;
import org.apache.servicecomb.registry.api.registry.Microservice;
import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
import org.apache.servicecomb.registry.api.registry.MicroserviceInstances;
-import org.apache.servicecomb.registry.RegistrationManager;
import org.apache.servicecomb.registry.version.Version;
import org.apache.servicecomb.swagger.SwaggerUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.collect.ImmutableMap;
+
import io.swagger.models.Swagger;
public class StaticMicroserviceVersions extends MicroserviceVersions {
-
private static final Logger LOGGER = LoggerFactory.getLogger(StaticMicroserviceVersions.class);
- private Class<?> schemaIntfCls;
-
- private Microservice microservice = new Microservice();
+ protected final Microservice microservice = new Microservice();
- private MicroserviceInstances microserviceInstances = new MicroserviceInstances();
+ protected final MicroserviceInstances microserviceInstances = new MicroserviceInstances();
public StaticMicroserviceVersions(AppManager appManager, String appId, String microserviceName) {
super(appManager, appId, microserviceName);
}
public StaticMicroserviceVersions init(Class<?> schemaIntfCls, String version,
- List<MicroserviceInstance> addedInstances) {
- this.schemaIntfCls = schemaIntfCls;
- Swagger swagger = RegistrationManager.INSTANCE.getSwaggerLoader()
- .registerSwagger(appId, shortName, shortName, schemaIntfCls);
- String swaggerContent = SwaggerUtils.swaggerToString(swagger);
- LOGGER.info("generate swagger for 3rd party service [{}]/[{}], swagger: {}",
- getMicroserviceName(), version, swaggerContent);
- microservice.addSchema(shortName, swaggerContent);
+ List<MicroserviceInstance> instances) {
+ return init(ImmutableMap.of(microserviceName, schemaIntfCls), version, instances);
+ }
+ public StaticMicroserviceVersions init(Map<String, Class<?>> schemaByIdMap, String version,
+ List<MicroserviceInstance> instances) {
createMicroservice(version);
-
- for (MicroserviceInstance instance : addedInstances) {
- instance.setServiceId(microservice.getServiceId());
- instance.setInstanceId(microservice.getServiceId() + "-" + UUID.randomUUID());
- }
- microserviceInstances.setMicroserviceNotExist(false);
- microserviceInstances.setInstancesResponse(new FindInstancesResponse());
- microserviceInstances.getInstancesResponse().setInstances(addedInstances);
-
+ addSchemas(schemaByIdMap);
+ addInstances(instances);
pullInstances();
return this;
}
- public Class<?> getSchemaIntfCls() {
- return schemaIntfCls;
+ protected void createMicroservice(String version) {
+ String environment = RegistrationManager.INSTANCE.getMicroservice().getEnvironment();
+
+ microservice.setAppId(this.getAppId());
+ microservice.setServiceName(this.getShortName());
+ microservice.setVersion(new Version(version).getVersion());
+ microservice.setServiceId(this.getAppId() + "-"
+ + environment + "-"
+ + this.getMicroserviceName() + "-"
+ + microservice.getVersion());
+ microservice.setEnvironment(environment);
+ }
+
+ protected void addSchemas(Map<String, Class<?>> schemaByIdMap) {
+ schemaByIdMap.forEach(this::addSchema);
+ }
+
+ protected void addSchema(String schemaId, Class<?> schemaClass) {
+ Swagger swagger = RegistrationManager.INSTANCE.getSwaggerLoader()
+ .registerSwagger(appId, shortName, schemaId, schemaClass);
+ String swaggerContent = SwaggerUtils.swaggerToString(swagger);
+ LOGGER.debug("generate swagger for 3rd party service [{}], swagger: {}", microserviceName, swaggerContent);
+ microservice.addSchema(schemaId, swaggerContent);
+ }
+
+ protected void addInstances(List<MicroserviceInstance> instances) {
+ for (int idx = 0; idx < instances.size(); idx++) {
+ MicroserviceInstance instance = instances.get(idx);
+ instance.setServiceId(microservice.getServiceId());
+ instance.setInstanceId(microservice.getServiceId() + "-" + idx);
+ }
+ microserviceInstances.setMicroserviceNotExist(false);
+ microserviceInstances.setInstancesResponse(new FindInstancesResponse());
+ microserviceInstances.getInstancesResponse().setInstances(instances);
}
@Override
@@ -87,17 +108,4 @@ public class StaticMicroserviceVersions extends MicroserviceVersions {
protected MicroserviceVersion createMicroserviceVersion(String microserviceId, List<MicroserviceInstance> instances) {
return new MicroserviceVersion(this, microservice, microserviceName, instances);
}
-
- private void createMicroservice(String version) {
- String environment = RegistrationManager.INSTANCE.getMicroservice().getEnvironment();
-
- microservice.setAppId(this.getAppId());
- microservice.setServiceName(this.getShortName());
- microservice.setVersion(new Version(version).getVersion());
- microservice.setServiceId(this.getAppId() + "-"
- + environment + "-"
- + this.getMicroserviceName() + "-"
- + microservice.getVersion());
- microservice.setEnvironment(environment);
- }
}
diff --git a/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/registry/ThirdServiceWithInvokerRegister.java b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/registry/ThirdServiceWithInvokerRegister.java
new file mode 100644
index 0000000..f131024
--- /dev/null
+++ b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/registry/ThirdServiceWithInvokerRegister.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.provider.pojo.registry;
+
+import java.util.Map.Entry;
+
+import org.apache.servicecomb.core.registry.ThirdServiceRegister;
+import org.apache.servicecomb.provider.pojo.Invoker;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+
+/**
+ * <pre>
+ * extend {@link ThirdServiceRegister} to register consumer client bean
+ *
+ * usage:
+ * 1. declare the 3rd service
+ * {@code
+ * @Configuration
+ * public class Svc extends ThirdServiceWithInvokerRegister {
+ * public static final String NAME = "svc";
+ *
+ * public Svc() {
+ * super(NAME);
+ *
+ * addSchema("schema1", Schema1Client.class);
+ * addSchema("schema2", Schema2Client.class);
+ * }
+ * }
+ * }
+ * 2. invoke the 3rd service same to normal servicecomb service
+ * {@code
+ * @Bean
+ * public class SomeService {
+ * private Schema1Client client;
+ *
+ * @Autowired
+ * public void setClient(Schema1Client client) {
+ * this.client = client;
+ * }
+ *
+ * public int add(int x, int y) {
+ * return client.add(x, y);
+ * }
+ * }
+ * }
+ * </pre>
+ */
+public abstract class ThirdServiceWithInvokerRegister extends ThirdServiceRegister implements BeanFactoryPostProcessor {
+ public ThirdServiceWithInvokerRegister(String microserviceName) {
+ super(microserviceName);
+ }
+
+ @Override
+ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
+ for (Entry<String, Class<?>> entry : schemaByIdMap.entrySet()) {
+ Object instance = createClientProxy(entry.getKey(), entry.getValue());
+ beanFactory.registerSingleton(microserviceName + "_" + entry.getKey(), instance);
+ }
+ }
+
+ protected Object createClientProxy(String schemaId, Class<?> consumerIntf) {
+ return Invoker.createProxy(microserviceName, schemaId, consumerIntf);
+ }
+}