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/03/27 03:54:06 UTC

[servicecomb-java-chassis] 01/02: [SCB-1822]fix problems when using multiple consumer interface for one operation and using CseHttpEntity to set localcontext

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

commit 06e7c07ba0e6475c2bd651ece33c29580fe90aa6
Author: liubao <bi...@qq.com>
AuthorDate: Wed Mar 25 17:27:18 2020 +0800

    [SCB-1822]fix problems when using multiple consumer interface for one operation and using CseHttpEntity to set localcontext
---
 .../client/CustomEndpointDiscoveryFilter.java      | 41 ++++++++++++++
 .../demo/springmvc/client/TestDateTimeSchema.java  | 62 +++++++++++++++++++++
 .../src/main/resources/microservice.yaml           |  1 +
 .../apache/servicecomb/provider/pojo/Invoker.java  |  4 +-
 .../pojo/definition/PojoConsumerMapKey.java        | 65 ++++++++++++++++++++++
 .../provider/pojo/definition/PojoConsumerMeta.java | 19 +++----
 .../servicecomb/provider/pojo/TestInvoker.java     |  2 +-
 .../springmvc/reference/CseClientHttpRequest.java  |  3 +-
 8 files changed, 182 insertions(+), 15 deletions(-)

diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CustomEndpointDiscoveryFilter.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CustomEndpointDiscoveryFilter.java
new file mode 100644
index 0000000..126a7d4
--- /dev/null
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CustomEndpointDiscoveryFilter.java
@@ -0,0 +1,41 @@
+/*
+ * 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 org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
+import org.apache.servicecomb.serviceregistry.discovery.AbstractEndpointDiscoveryFilter;
+import org.apache.servicecomb.serviceregistry.discovery.DiscoveryContext;
+import org.apache.servicecomb.serviceregistry.discovery.DiscoveryTreeNode;
+
+public class CustomEndpointDiscoveryFilter extends AbstractEndpointDiscoveryFilter {
+  @Override
+  protected String findTransportName(DiscoveryContext context, DiscoveryTreeNode parent) {
+    //only need rest endpoints
+    return "rest";
+  }
+
+  @Override
+  protected Object createEndpoint(String transportName, String endpoint, MicroserviceInstance instance) {
+    return endpoint;
+  }
+
+  @Override
+  public int getOrder() {
+    return 0;
+  }
+}
diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDateTimeSchema.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDateTimeSchema.java
index b22f8c7..4762f36 100644
--- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDateTimeSchema.java
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDateTimeSchema.java
@@ -21,11 +21,22 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.Date;
+import java.util.List;
 
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
 import org.apache.servicecomb.demo.CategorizedTestCase;
 import org.apache.servicecomb.demo.TestMgr;
+import org.apache.servicecomb.foundation.common.cache.VersionedCache;
+import org.apache.servicecomb.loadbalance.LoadbalanceHandler;
 import org.apache.servicecomb.provider.pojo.RpcReference;
+import org.apache.servicecomb.provider.springmvc.reference.CseHttpEntity;
+import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder;
+import org.apache.servicecomb.serviceregistry.discovery.DiscoveryContext;
+import org.apache.servicecomb.serviceregistry.discovery.DiscoveryTree;
+import org.apache.servicecomb.swagger.invocation.context.InvocationContext;
+import org.springframework.http.HttpMethod;
 import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
 
 interface DateTimeSchemaInf {
   Date getDate(Date date);
@@ -47,11 +58,25 @@ interface DateTimeSchemaInf {
   LocalDateTime postLocalDateTime(LocalDateTime date);
 }
 
+interface DateTimeSchemaWithContextInf {
+  Date getDate(InvocationContext context, Date date);
+}
+
 @Component
 public class TestDateTimeSchema implements CategorizedTestCase {
   @RpcReference(microserviceName = "springmvc", schemaId = "DateTimeSchema")
   private DateTimeSchemaInf dateTimeSchemaInf;
 
+  @RpcReference(microserviceName = "springmvc", schemaId = "DateTimeSchema")
+  private DateTimeSchemaWithContextInf dateTimeSchemaWithContextInf;
+
+  private DiscoveryTree discoveryTree = new DiscoveryTree();
+
+  public TestDateTimeSchema() {
+    discoveryTree.addFilter(new CustomEndpointDiscoveryFilter());
+    discoveryTree.sort();
+  }
+
   @Override
   public void testRestTransport() throws Exception {
 
@@ -65,6 +90,8 @@ public class TestDateTimeSchema implements CategorizedTestCase {
   @Override
   public void testAllTransport() throws Exception {
     testDateTimeSchema();
+    testDateTimeSchemaMulticast();
+    testDateTimeSchemaMulticastRestTemplate();
   }
 
   private void testDateTimeSchema() {
@@ -92,4 +119,39 @@ public class TestDateTimeSchema implements CategorizedTestCase {
         dateTimeSchemaInf.postLocalDateTime(localDateTime)
             .format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS")));
   }
+
+  private void testDateTimeSchemaMulticast() {
+    DiscoveryContext context = new DiscoveryContext();
+    VersionedCache serversVersionedCache = discoveryTree.discovery(context, "springmvctest", "springmvc", "0+");
+    List<String> enpoints = serversVersionedCache.data();
+
+    for (String endpoint : enpoints) {
+      InvocationContext invocationContext = new InvocationContext();
+      invocationContext.addLocalContext(LoadbalanceHandler.SERVICECOMB_SERVER_ENDPOINT, endpoint);
+      Date date = new Date();
+      TestMgr.check(date.getTime(), dateTimeSchemaWithContextInf.getDate(invocationContext, date).getTime());
+    }
+  }
+
+  private void testDateTimeSchemaMulticastRestTemplate() throws Exception {
+    DiscoveryContext context = new DiscoveryContext();
+    VersionedCache serversVersionedCache = discoveryTree.discovery(context, "springmvctest", "springmvc", "0+");
+    List<String> enpoints = serversVersionedCache.data();
+
+    RestTemplate restTemplate = RestTemplateBuilder.create();
+
+    for (String endpoint : enpoints) {
+      CseHttpEntity<?> entity = new CseHttpEntity<>(null);
+      InvocationContext invocationContext = new InvocationContext();
+      invocationContext.addLocalContext(LoadbalanceHandler.SERVICECOMB_SERVER_ENDPOINT, endpoint);
+      entity.setContext(invocationContext);
+
+      Date date = new Date();
+      String dateValue = RestObjectMapperFactory.getRestObjectMapper().convertToString(date);
+      TestMgr.check(date.getTime(),
+          restTemplate
+              .exchange("cse://springmvc/dateTime/getDate?date={1}", HttpMethod.GET,
+                  entity, Date.class, dateValue).getBody().getTime());
+    }
+  }
 }
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 c8c33bc..95b2b43 100644
--- a/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml
+++ b/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml
@@ -56,6 +56,7 @@ servicecomb:
     enabled: true
     samplingRate: 0.5
   loadbalance:
+    userDefinedEndpoint.enabled: true
     strategy:
       name: WeightedResponse
     retryEnabled: true
diff --git a/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/Invoker.java b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/Invoker.java
index 89cf49d..f254ad9 100644
--- a/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/Invoker.java
+++ b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/Invoker.java
@@ -148,7 +148,7 @@ public class Invoker implements InvocationHandler {
     }
 
     PojoConsumerOperationMeta pojoConsumerOperationMeta = consumerMeta
-        .findOperationMeta(MethodUtils.findSwaggerMethodName(method));
+        .findOperationMeta(MethodUtils.findSwaggerMethodName(method), consumerIntf);
     if (pojoConsumerOperationMeta == null) {
       throw new IllegalStateException(
           String.format(
@@ -162,6 +162,8 @@ public class Invoker implements InvocationHandler {
 
     SwaggerConsumerOperation consumerOperation = pojoConsumerOperationMeta.getSwaggerConsumerOperation();
     OperationMeta operationMeta = pojoConsumerOperationMeta.getOperationMeta();
+    // operation meta is static data based on swagger, while consumer operation based on invoker, have interface info
+    operationMeta.setSwaggerConsumerOperation(consumerOperation);
     Invocation invocation = InvocationFactory.forConsumer(
         findReferenceConfig(operationMeta),
         operationMeta,
diff --git a/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/definition/PojoConsumerMapKey.java b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/definition/PojoConsumerMapKey.java
new file mode 100644
index 0000000..26a8c09
--- /dev/null
+++ b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/definition/PojoConsumerMapKey.java
@@ -0,0 +1,65 @@
+/*
+ * 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.definition;
+
+/**
+ * In consumer, every schema may have many consumer interfaces, each interface may contain part of the
+ * scheme operations.
+ */
+public class PojoConsumerMapKey {
+  private final String operationId;
+
+  private final Class<?> consumerIntf;
+
+  public PojoConsumerMapKey(String operationId, Class<?> consumerIntf) {
+    this.operationId = operationId;
+    this.consumerIntf = consumerIntf;
+  }
+
+  public String getOperationId() {
+    return operationId;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    PojoConsumerMapKey that = (PojoConsumerMapKey) o;
+
+    if (!operationId.equals(that.operationId)) {
+      return false;
+    }
+    return consumerIntf.equals(that.consumerIntf);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = operationId.hashCode();
+    result = 31 * result + consumerIntf.hashCode();
+    return result;
+  }
+
+  public Class<?> getConsumerIntf() {
+    return consumerIntf;
+  }
+}
diff --git a/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/definition/PojoConsumerMeta.java b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/definition/PojoConsumerMeta.java
index 7436ad4..1587a92 100644
--- a/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/definition/PojoConsumerMeta.java
+++ b/providers/provider-pojo/src/main/java/org/apache/servicecomb/provider/pojo/definition/PojoConsumerMeta.java
@@ -31,20 +31,17 @@ import org.apache.servicecomb.swagger.generator.SwaggerGenerator;
 public class PojoConsumerMeta {
   private MicroserviceReferenceConfig microserviceReferenceConfig;
 
-  private Class<?> consumerIntf;
-
   private SchemaMeta schemaMeta;
 
   // key is consumer method name
-  private Map<String, PojoConsumerOperationMeta> operationMetas = new HashMap<>();
+  private Map<PojoConsumerMapKey, PojoConsumerOperationMeta> operationMetas = new HashMap<>();
 
   public PojoConsumerMeta(MicroserviceReferenceConfig microserviceReferenceConfig, SwaggerConsumer swaggerConsumer,
       SchemaMeta schemaMeta) {
     this.microserviceReferenceConfig = microserviceReferenceConfig;
-    this.consumerIntf = swaggerConsumer.getConsumerIntf();
     this.schemaMeta = schemaMeta;
 
-    SwaggerGenerator intfSwaggerGenerator = SwaggerGenerator.create(consumerIntf);
+    SwaggerGenerator intfSwaggerGenerator = SwaggerGenerator.create(swaggerConsumer.getConsumerIntf());
     intfSwaggerGenerator.scanClassAnnotation();
     for (SwaggerConsumerOperation swaggerConsumerOperation : swaggerConsumer.getOperations().values()) {
       String operationId = swaggerConsumerOperation.getSwaggerOperation().getOperationId();
@@ -57,7 +54,9 @@ public class PojoConsumerMeta {
       PojoConsumerOperationMeta pojoConsumerOperationMeta = new PojoConsumerOperationMeta(this, operationMeta,
           swaggerConsumerOperation, intfSwaggerGenerator.getSwagger(), intfOperationGenerator.getOperation());
 
-      operationMetas.put(swaggerConsumerOperation.getSchemaOperationId(), pojoConsumerOperationMeta);
+      operationMetas.put(
+          new PojoConsumerMapKey(swaggerConsumerOperation.getSchemaOperationId(), swaggerConsumer.getConsumerIntf()),
+          pojoConsumerOperationMeta);
     }
   }
 
@@ -65,10 +64,6 @@ public class PojoConsumerMeta {
     return microserviceReferenceConfig;
   }
 
-  public Class<?> getConsumerIntf() {
-    return consumerIntf;
-  }
-
   public boolean isExpired() {
     return microserviceReferenceConfig.isExpired();
   }
@@ -81,7 +76,7 @@ public class PojoConsumerMeta {
     return schemaMeta;
   }
 
-  public PojoConsumerOperationMeta findOperationMeta(String consumerMethodName) {
-    return operationMetas.get(consumerMethodName);
+  public PojoConsumerOperationMeta findOperationMeta(String consumerMethodName, Class<?> consumerInf) {
+    return operationMetas.get(new PojoConsumerMapKey(consumerMethodName, consumerInf));
   }
 }
diff --git a/providers/provider-pojo/src/test/java/org/apache/servicecomb/provider/pojo/TestInvoker.java b/providers/provider-pojo/src/test/java/org/apache/servicecomb/provider/pojo/TestInvoker.java
index c85b725..88167a1 100644
--- a/providers/provider-pojo/src/test/java/org/apache/servicecomb/provider/pojo/TestInvoker.java
+++ b/providers/provider-pojo/src/test/java/org/apache/servicecomb/provider/pojo/TestInvoker.java
@@ -277,7 +277,7 @@ public class TestInvoker {
     Deencapsulation.invoke(invoker, "ensureStatusUp");
     PojoConsumerMeta meta = Deencapsulation.invoke(invoker, "refreshMeta");
 
-    JavaType javaType = meta.findOperationMeta("download").getResponsesMeta().findResponseType(200);
+    JavaType javaType = meta.findOperationMeta("download", DownloadIntf.class).getResponsesMeta().findResponseType(200);
     Assert.assertSame(Part.class, javaType.getRawClass());
 
     scbEngine.destroy();
diff --git a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java
index 14b4bfe..6e42671 100644
--- a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java
+++ b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java
@@ -218,7 +218,8 @@ public class CseClientHttpRequest implements ClientHttpRequest {
         path + (this.uri.getRawQuery() == null ? "" : "?" + this.uri.getRawQuery()));
 
     if (context != null) {
-      invocation.addContext(context);
+      invocation.addContext(context.getContext());
+      invocation.addLocalContext(context.getLocalContext());
     }
 
     if (responseType != null &&