diff --git a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterClient.java b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterClient.java index 08c1fd6..2ae968f 100644 --- a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterClient.java +++ b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterClient.java @@ -53,7 +53,7 @@ public ConfigCenterClient(AddressManager addressManager, HttpTransport httpTrans @Override public QueryConfigurationsResponse queryConfigurations(QueryConfigurationsRequest request) { - String dimensionsInfo = buildDimensionsInfo(request); + String dimensionsInfo = buildDimensionsInfo(request, true); QueryConfigurationsResponse queryConfigurationsResponse = new QueryConfigurationsResponse(); Map configurations = new HashMap<>(); @@ -79,7 +79,7 @@ public QueryConfigurationsResponse queryConfigurations(QueryConfigurationsReques configurations.putAll(allConfigMap.get(APPLICATION_CONFIG)); } - if (allConfigMap.get(request.getServiceName()) != null) { + if (allConfigMap.get(buildDimensionsInfo(request, false)) != null) { configurations.putAll(allConfigMap.get(request.getServiceName())); } @@ -109,11 +109,11 @@ public QueryConfigurationsResponse queryConfigurations(QueryConfigurationsReques } } - private String buildDimensionsInfo(QueryConfigurationsRequest request) { + private String buildDimensionsInfo(QueryConfigurationsRequest request, boolean withVersion) { String result = request.getServiceName() + DEFAULT_APP_SEPARATOR + request.getApplication(); - if (!StringUtils.isEmpty(request.getVersion())) { + if (withVersion && !StringUtils.isEmpty(request.getVersion())) { result = result + DEFAULT_SERVICE_SEPARATOR + request .getVersion(); } diff --git a/config/servicecomb-config-center/src/main/java/com/huaweicloud/dubbo/config/ConfigurationSpringInitializer.java b/config/servicecomb-config-center/src/main/java/com/huaweicloud/dubbo/config/ConfigurationSpringInitializer.java index 020b040..12fff4c 100644 --- a/config/servicecomb-config-center/src/main/java/com/huaweicloud/dubbo/config/ConfigurationSpringInitializer.java +++ b/config/servicecomb-config-center/src/main/java/com/huaweicloud/dubbo/config/ConfigurationSpringInitializer.java @@ -20,13 +20,8 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; +import java.util.Properties; -import org.apache.dubbo.common.config.configcenter.ConfigChangeType; -import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent; -import org.apache.dubbo.common.config.configcenter.ConfigurationListener; -import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.servicecomb.config.center.client.AddressManager; import org.apache.servicecomb.config.center.client.ConfigCenterClient; import org.apache.servicecomb.config.center.client.ConfigCenterManager; @@ -115,6 +110,22 @@ public void onConfigurationChangedEvent(ConfigurationChangedEvent event) { notifyGovernanceDataChange(event.getConfigurations()); } + @Override + protected Properties mergeProperties() throws IOException { + Properties properties = super.mergeProperties(); + properties.putAll(this.sources); + return properties; + } + + @Override + protected String resolvePlaceholder(String placeholder, Properties props) { + String propertyValue = super.resolvePlaceholder(placeholder, props); + if (propertyValue == null) { + return this.sources.get(placeholder) == null ? null : this.sources.get(placeholder).toString(); + } + return propertyValue; + } + @Subscribe public void onRegistrationReadyEvent(RegistrationReadyEvent event) { // 注册完成发送一次配置变更, 保证订阅者能够读取到配置 diff --git a/integration-tests/discovery-tests/README.md b/integration-tests/discovery-tests/README.md new file mode 100644 index 0000000..82334dc --- /dev/null +++ b/integration-tests/discovery-tests/README.md @@ -0,0 +1,13 @@ +运行测试的步骤: + +1. 安装本地微服务引擎并启动 +2. 运行 PriceApplication +3. 运行 OrderApplication +4. 配置中心下发配置项: + + [全局配置] dubbo.servicecomb.test.configuration: peizhi + [服务配置:price-provider] dubbo.servicecomb.test.configurationService: peizhi_service + [全局配置] dubbo.servicecomb.governance: {"providerInfos":[{"serviceName":"price-provider","schemaInfos":[{"schemaId":"com.huaweicloud.it.price.PriceService","parameters":{"timeout":5000}}]}]} + +5. 运行 PortalApplication 查看测试结果, 如果成功,输出 `running all test cases successfully` + diff --git a/integration-tests/discovery-tests/common-api/src/main/java/com/huaweicloud/it/price/PriceService.java b/integration-tests/discovery-tests/common-api/src/main/java/com/huaweicloud/it/price/PriceService.java index d3abe5a..306734f 100644 --- a/integration-tests/discovery-tests/common-api/src/main/java/com/huaweicloud/it/price/PriceService.java +++ b/integration-tests/discovery-tests/common-api/src/main/java/com/huaweicloud/it/price/PriceService.java @@ -23,4 +23,8 @@ public interface PriceService { String sayHello(String name); CompletableFuture sayHelloAsync(String name); + + String testConfiguration(String value); + + String testConfigurationService(String value); } diff --git a/integration-tests/discovery-tests/discovery-tests-client/pom.xml b/integration-tests/discovery-tests/discovery-tests-client/pom.xml index 470f288..98e2c63 100644 --- a/integration-tests/discovery-tests/discovery-tests-client/pom.xml +++ b/integration-tests/discovery-tests/discovery-tests-client/pom.xml @@ -24,12 +24,93 @@ 1.3.2-SNAPSHOT + + 2.1.6.RELEASE + 5.1.14.RELEASE + + 1.3.2 + + + 4.0.0 discovery-tests-client + + + + com.huaweicloud + spring-cloud-huawei-dependencies + ${spring-cloud-huawei.version} + pom + import + + + org.springframework + spring-framework-bom + ${spring.version} + pom + import + + + com.huaweicloud.dubbo-servicecomb + dubbo-servicecomb-dependencies + ${project.version} + import + pom + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + jakarta.servlet + jakarta.servlet-api + 4.0.3 + + + jakarta.validation + jakarta.validation-api + 2.0.2 + + + org.hibernate.validator + hibernate-validator + 6.1.5.Final + + + org.yaml + snakeyaml + 1.24 + + + junit + junit + 4.12 + + + - + + com.huaweicloud.dubbo-servicecomb + discovery-common-api + ${project.version} + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + com.huaweicloud + spring-cloud-starter-huawei-servicecomb-discovery + diff --git a/integration-tests/discovery-tests/discovery-tests-client/src/main/java/com/huaweicloud/it/portal/PortalApplication.java b/integration-tests/discovery-tests/discovery-tests-client/src/main/java/com/huaweicloud/it/portal/PortalApplication.java new file mode 100644 index 0000000..4e01a8f --- /dev/null +++ b/integration-tests/discovery-tests/discovery-tests-client/src/main/java/com/huaweicloud/it/portal/PortalApplication.java @@ -0,0 +1,57 @@ +/* + * 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 com.huaweicloud.it.portal; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.loadbalancer.LoadBalanced; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +@SpringBootApplication +@Component +public class PortalApplication { + private static PortalController portalController; + + @LoadBalanced + @Bean + public RestTemplate restTemplate() { + RestTemplate restTemplate = new RestTemplate(); + return restTemplate; + } + + @Autowired + void setPortalController(PortalController portalController) { + PortalApplication.portalController = portalController; + } + + + public static void main(String[] args) throws Exception { + try { + SpringApplication.run(PortalApplication.class); + } catch (Throwable e) { + e.printStackTrace(); + } + + System.out.println("running all test cases"); + portalController.testAll(); + System.out.println("running all test cases successfully"); + } +} diff --git a/integration-tests/discovery-tests/discovery-tests-client/src/main/java/com/huaweicloud/it/portal/PortalController.java b/integration-tests/discovery-tests/discovery-tests-client/src/main/java/com/huaweicloud/it/portal/PortalController.java new file mode 100644 index 0000000..73ea6ed --- /dev/null +++ b/integration-tests/discovery-tests/discovery-tests-client/src/main/java/com/huaweicloud/it/portal/PortalController.java @@ -0,0 +1,48 @@ +/* + * 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 com.huaweicloud.it.portal; + +import org.junit.Assert; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; + +@RestController +@RequestMapping(path = "/portal") +public class PortalController { + @Autowired + private RestTemplate restTemplate; + + @GetMapping(path = "testAll") + public void testAll() { + + String result = restTemplate.getForObject("http://order-consumer/price/sayHello?name={name}", String.class, "hello world"); + Assert.assertEquals(result, "hello world"); + + result = restTemplate.getForObject("http://order-consumer/price/sayHello?name={name}", String.class, "timeout"); + Assert.assertEquals(result, "timeout"); + + result = restTemplate.getForObject("http://order-consumer/price/testConfiguration", String.class); + Assert.assertEquals(result, "peizhi"); + + result = restTemplate.getForObject("http://order-consumer/price/testConfigurationService", String.class); + Assert.assertEquals(result, "peizhi_service"); + } +} diff --git a/integration-tests/discovery-tests/discovery-tests-client/src/main/resources/application.yml b/integration-tests/discovery-tests/discovery-tests-client/src/main/resources/application.yml new file mode 100644 index 0000000..6633a4b --- /dev/null +++ b/integration-tests/discovery-tests/discovery-tests-client/src/main/resources/application.yml @@ -0,0 +1,31 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +server: + port: 8088 + +spring: + application: + name: portal-consumer + cloud: + servicecomb: + discovery: + enabled: true + address: http://127.0.0.1:30100 + appName: discovery + serviceName: portal-consumer + version: 0.0.1 \ No newline at end of file diff --git a/integration-tests/discovery-tests/order-consumer/pom.xml b/integration-tests/discovery-tests/order-consumer/pom.xml index 92d8763..88854ef 100644 --- a/integration-tests/discovery-tests/order-consumer/pom.xml +++ b/integration-tests/discovery-tests/order-consumer/pom.xml @@ -60,6 +60,10 @@ org.apache.dubbo dubbo-rpc-dubbo + + org.apache.dubbo + dubbo-rpc-rest + org.apache.dubbo dubbo-remoting-netty4 diff --git a/integration-tests/discovery-tests/order-consumer/src/main/java/com/huaweicloud/it/order/PriceServiceRestImpl.java b/integration-tests/discovery-tests/order-consumer/src/main/java/com/huaweicloud/it/order/PriceServiceRestImpl.java new file mode 100644 index 0000000..dd7d647 --- /dev/null +++ b/integration-tests/discovery-tests/order-consumer/src/main/java/com/huaweicloud/it/order/PriceServiceRestImpl.java @@ -0,0 +1,71 @@ +/* + * 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 com.huaweicloud.it.order; + +import java.util.concurrent.CompletableFuture; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; + +import com.huaweicloud.it.price.PriceService; + +@Path("/price") +public class PriceServiceRestImpl implements PriceService { + @Autowired + @Qualifier("priceService") + private PriceService priceService; + + @Override + @GET + @Path("/sayHello") + @Produces({MediaType.APPLICATION_JSON}) + public String sayHello(@QueryParam("name") String name) { + return priceService.sayHello(name); + } + + // dubbo do not support CompletableFuture, this example can not work + @Override + @GET + @Path("/sayHelloAsync") + @Produces({MediaType.APPLICATION_JSON}) + public CompletableFuture sayHelloAsync(@QueryParam("name") String name) { + return CompletableFuture.completedFuture(name); + } + + @Override + @GET + @Path("/testConfiguration") + @Produces({MediaType.APPLICATION_JSON}) + public String testConfiguration(String value) { + return priceService.testConfiguration(value); + } + + @Override + @GET + @Path("/testConfigurationService") + @Produces({MediaType.APPLICATION_JSON}) + public String testConfigurationService(String value) { + return priceService.testConfigurationService(value); + } +} diff --git a/integration-tests/discovery-tests/order-consumer/src/main/resources/spring/dubbo-provider.xml b/integration-tests/discovery-tests/order-consumer/src/main/resources/spring/dubbo-provider.xml index 269932e..8ebcaa1 100644 --- a/integration-tests/discovery-tests/order-consumer/src/main/resources/spring/dubbo-provider.xml +++ b/integration-tests/discovery-tests/order-consumer/src/main/resources/spring/dubbo-provider.xml @@ -23,10 +23,15 @@ + + + + + diff --git a/integration-tests/discovery-tests/price-provider/src/main/java/com/huaweicloud/it/price/PriceServiceImpl.java b/integration-tests/discovery-tests/price-provider/src/main/java/com/huaweicloud/it/price/PriceServiceImpl.java index b102a4f..43996ad 100644 --- a/integration-tests/discovery-tests/price-provider/src/main/java/com/huaweicloud/it/price/PriceServiceImpl.java +++ b/integration-tests/discovery-tests/price-provider/src/main/java/com/huaweicloud/it/price/PriceServiceImpl.java @@ -19,7 +19,15 @@ import java.util.concurrent.CompletableFuture; +import org.springframework.beans.factory.annotation.Value; + public class PriceServiceImpl implements PriceService { + @Value("${dubbo.servicecomb.test.configuration:hello}") + private String configuration; + + @Value("${dubbo.servicecomb.test.configurationService:hello}") + private String configurationService; + @Override public String sayHello(String name) { if ("timeout".equals(name)) { @@ -36,4 +44,14 @@ public String sayHello(String name) { public CompletableFuture sayHelloAsync(String name) { return CompletableFuture.completedFuture(sayHello(name)); } + + @Override + public String testConfiguration(String value) { + return configuration; + } + + @Override + public String testConfigurationService(String value) { + return configurationService; + } }