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 <[email protected]> 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 &&
