From a41abb6e3bff8be22196ab49909cb3cb2f0f6910 Mon Sep 17 00:00:00 2001 From: lepdou Date: Wed, 20 Jul 2022 20:15:11 +0800 Subject: [PATCH] add feature-env examples --- CHANGELOG.md | 1 + .../PolarisLoadBalancerCompositeRule.java | 7 +- .../feign/RouterLabelFeignInterceptor.java | 8 +- .../README-zh.md | 152 ++++++++++++++++++ .../base/base-backend/pom.xml | 16 ++ .../basebackend/BackendController.java | 44 +++++ .../basebackend/BaseBackendApplication.java | 34 ++++ .../src/main/resources/bootstrap.yml | 15 ++ .../base/base-front/pom.xml | 16 ++ .../basefront/BaseFrontApplication.java | 34 ++++ .../featureenv/basefront/FrontController.java | 51 ++++++ .../featureenv/basefront/MiddleService.java | 33 ++++ .../src/main/resources/bootstrap.yml | 15 ++ .../base/base-middle/pom.xml | 18 +++ .../featureenv/basemiddle/BackendService.java | 33 ++++ .../basemiddle/BaseMiddleApplication.java | 34 ++++ .../basemiddle/MiddleController.java | 51 ++++++ .../src/main/resources/bootstrap.yml | 15 ++ .../base/pom.xml | 33 ++++ .../feature1/feature1-backend/pom.xml | 16 ++ .../feature1backend/BackendController.java | 51 ++++++ .../Feature1BackendApplication.java | 34 ++++ .../src/main/resources/bootstrap.yml | 19 +++ .../feature1/feature1-middle/pom.xml | 16 ++ .../feature1middle/BackendService.java | 33 ++++ .../Feature1MiddleApplication.java | 34 ++++ .../feature1middle/MiddleController.java | 58 +++++++ .../src/main/resources/bootstrap.yml | 19 +++ .../feature1/pom.xml | 32 ++++ .../feature2/feature2-backend/pom.xml | 16 ++ .../feature2backend/BackendController.java | 51 ++++++ .../Feature2BackendApplication.java | 34 ++++ .../src/main/resources/bootstrap.yml | 19 +++ .../feature2/feature2-front/pom.xml | 17 ++ .../Feature2FrontApplication.java | 34 ++++ .../feature2front/FrontController.java | 58 +++++++ .../feature2front/MiddleService.java | 33 ++++ .../src/main/resources/bootstrap.yml | 19 +++ .../feature2/pom.xml | 32 ++++ .../featureenv-gateway/pom.xml | 30 ++++ .../gateway/FeatureEnvScgApplication.java | 33 ++++ .../src/main/resources/bootstrap.yml | 68 ++++++++ .../imgs/structs.png | Bin 0 -> 56389 bytes .../polaris-router-featureenv-example/pom.xml | 34 ++++ spring-cloud-tencent-examples/pom.xml | 1 + 45 files changed, 1392 insertions(+), 9 deletions(-) create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/README-zh.md create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/pom.xml create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/basebackend/BackendController.java create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/basebackend/BaseBackendApplication.java create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/resources/bootstrap.yml create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/pom.xml create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/BaseFrontApplication.java create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/FrontController.java create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/MiddleService.java create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/resources/bootstrap.yml create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/pom.xml create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/BackendService.java create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/BaseMiddleApplication.java create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/MiddleController.java create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/resources/bootstrap.yml create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/base/pom.xml create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/pom.xml create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1backend/BackendController.java create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1backend/Feature1BackendApplication.java create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/resources/bootstrap.yml create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/pom.xml create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/BackendService.java create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/Feature1MiddleApplication.java create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/MiddleController.java create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/resources/bootstrap.yml create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/pom.xml create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/pom.xml create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2backend/BackendController.java create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2backend/Feature2BackendApplication.java create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/resources/bootstrap.yml create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/pom.xml create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/Feature2FrontApplication.java create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/FrontController.java create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/MiddleService.java create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/resources/bootstrap.yml create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/pom.xml create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/pom.xml create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/src/main/java/com/tencent/cloud/polaris/featureenv/gateway/FeatureEnvScgApplication.java create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/src/main/resources/bootstrap.yml create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/imgs/structs.png create mode 100644 spring-cloud-tencent-examples/polaris-router-featureenv-example/pom.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index 23e4ccd13..79acf4fc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - [Feature: Optimized configuration update](https://github.com/Tencent/spring-cloud-tencent/pull/423) - [[Optimize] improve load-balance ut and support configurable heartbeat interval](https://github.com/Tencent/spring-cloud-tencent/pull/427) - [Feature: add feature-env plugin & add spring cloud gateway staining plugin](https://github.com/Tencent/spring-cloud-tencent/pull/428) +- [Feature: add feature env examples](https://github.com/Tencent/spring-cloud-tencent/pull/450) - [Optimize: add EncodeTransferMedataRestTemplateInterceptor to RestTemplate](https://github.com/Tencent/spring-cloud-tencent/pull/434) - [feat:enhance Feign and RestTemplate and support Polaris monitor.](https://github.com/Tencent/spring-cloud-tencent/pull/435) - [Optimize: Specification apollo code reference notes](https://github.com/Tencent/spring-cloud-tencent/pull/442) diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRule.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRule.java index f3763a13f..752ccce00 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRule.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/PolarisLoadBalancerCompositeRule.java @@ -107,6 +107,7 @@ public class PolarisLoadBalancerCompositeRule extends AbstractLoadBalancerRule { return null; } + ILoadBalancer loadBalancer = new SimpleLoadBalancer(); // 2. filter by router if (key instanceof PolarisRouterContext) { PolarisRouterContext routerContext = (PolarisRouterContext) key; @@ -114,10 +115,12 @@ public class PolarisLoadBalancerCompositeRule extends AbstractLoadBalancerRule { // 3. filter by load balance. // A LoadBalancer needs to be regenerated for each request, // because the list of servers may be different after filtered by router - ILoadBalancer loadBalancer = new SimpleLoadBalancer(); loadBalancer.addServers(serversAfterRouter); - delegateRule.setLoadBalancer(loadBalancer); } + else { + loadBalancer.addServers(allServers); + } + delegateRule.setLoadBalancer(loadBalancer); return delegateRule.choose(key); } diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptor.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptor.java index cee13cb63..9c8dd60bf 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptor.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/feign/RouterLabelFeignInterceptor.java @@ -103,16 +103,10 @@ public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered } // labels from downstream - Map transitiveLabels = MetadataContextHolder.get() - .getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE); + Map transitiveLabels = MetadataContextHolder.get().getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE); labels.putAll(transitiveLabels); // pass label by header - if (labels.size() == 0) { - requestTemplate.header(RouterConstants.ROUTER_LABEL_HEADER); - return; - } - String encodedLabelsContent; try { encodedLabelsContent = URLEncoder.encode(JacksonUtils.serialize2Json(labels), UTF_8); diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/README-zh.md b/spring-cloud-tencent-examples/polaris-router-featureenv-example/README-zh.md new file mode 100644 index 000000000..769682156 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/README-zh.md @@ -0,0 +1,152 @@ +# 多测试环境样例说明 + +## 一、部署结构 + + + +如上图所示,一共有三个环境: +1. 基线环境,包含 FrontService、MiddleService、BackendService +2. feature1 环境,包含 MiddleService、BackendService +3. feature2 环境,包含 FrontService、BackendService + +并且在入口处,部署网关服务。 + +三条请求链路: +1. 基线环境链路,Gateway -> FrontService(基线) -> MiddleService(基线) -> BackendService(基线) +2. feature1 环境链路,Gateway -> FrontService(基线) -> MiddleService(feature1) -> BackendService(feature1) +3. feature2 环境链路,Gateway -> FrontService(feature2) -> MiddleService(基线) -> BackendService(feature2) + + +## 二、运行样例 + +无需任何代码变更,直接启动 base、feature1、feature2、featureenv-gateway 下所有应用即可。 + +应用默认指向北极星官方的体验环境,启动成功后可直接到体验站点查看服务注册数据。 + +- 管控台地址: http://14.116.241.63:8080/ + - 账号:polaris + - 密码:polaris + +## 三、测试 + +### 方式一:客户端打标 + +#### 基线环境链路 +```` +curl http://127.0.0.1:9999/featureenv-front-example/router/rest +```` +响应结果(base 表示基线环境) +```` +featureenv-front-example[base] -> featureenv-middle-example[base] -> featureenv-backend-example[base] +```` + +#### feature1 环境链路 + +通过 X-Polaris-Metadata-Transitive-featureenv 请求头指定特性环境。 + +```` +curl -H'X-Polaris-Metadata-Transitive-featureenv:feature1' http://127.0.0.1:9999/featureenv-front-example/router/rest +```` +响应结果 +```` +featureenv-front-example[base] -> featureenv-middle-example[feature1] -> featureenv-backend-example[feature1] +```` + +#### feature2 环境链路 + +通过 X-Polaris-Metadata-Transitive-featureenv 请求头指定特性环境。 + +```` +curl -H'X-Polaris-Metadata-Transitive-featureenv:feature2' http://127.0.0.1:9999/featureenv-front-example/router/rest +```` +响应结果 +```` +featureenv-front-example[feature2] -> featureenv-middle-example[base] -> featureenv-backend-example[feature2] +```` + +### 方式二:网关流量染色 + +模拟一种实际的场景,假设客户端请求有一个 uid 请求参数,期望: +1. uid=1000 的请求打到 feature1 环境 +2. uid=2000 的请求打到 feature2 环境 +3. 其它 uid 的请求打到基线环境 + +**配置染色规则** + +配置地址:http://14.116.241.63:8080/#/filegroup-detail?group=featureenv-gateway&namespace=default + +修改 rule/staining.json 配置文件,填写以下规则: + +````json +{ + "rules":[ + { + "conditions":[ + { + "key":"${http.query.uid}", + "values":["1000"], + "operation":"EQUAL" + } + ], + "labels":[ + { + "key":"featureenv", + "value":"feature1" + } + ] + }, + { + "conditions":[ + { + "key":"${http.query.uid}", + "values":["2000"], + "operation":"EQUAL" + } + ], + "labels":[ + { + "key":"featureenv", + "value":"feature2" + } + ] + } + ] +} +```` + +填写完后发布配置即可。 + +#### 基线环境链路 +```` +curl http://127.0.0.1:9999/featureenv-front-example/router/rest?uid=3000 +```` +响应结果(base 表示基线环境) +```` +featureenv-front-example[base] -> featureenv-middle-example[base] -> featureenv-backend-example[base] +```` + +#### feature1 环境链路 + +通过 X-Polaris-Metadata-Transitive-featureenv 请求头指定特性环境。 + +```` +curl http://127.0.0.1:9999/featureenv-front-example/router/rest?uid=1000 +```` +响应结果 +```` +featureenv-front-example[base] -> featureenv-middle-example[feature1] -> featureenv-backend-example[feature1] +```` + +#### feature2 环境链路 + +通过 X-Polaris-Metadata-Transitive-featureenv 请求头指定特性环境。 + +```` +curl http://127.0.0.1:9999/featureenv-front-example/router/rest?uid=2000 +```` +响应结果 +```` +featureenv-front-example[feature2] -> featureenv-middle-example[base] -> featureenv-backend-example[feature2] +```` + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/pom.xml new file mode 100644 index 000000000..8c2c1f422 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/pom.xml @@ -0,0 +1,16 @@ + + + + polaris-router-featureenv-base + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + base-backend + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/basebackend/BackendController.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/basebackend/BackendController.java new file mode 100644 index 000000000..db7121ded --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/basebackend/BackendController.java @@ -0,0 +1,44 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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.tencent.cloud.polaris.router.featureenv.basebackend; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author lepdou 2022-07-20 + */ +@RestController +@RequestMapping("/router") +public class BackendController { + + @Value("${spring.application.name}") + private String appName; + + /** + * Get information of callee. + * @return information of callee + */ + @GetMapping("/rest") + public String rest() { + return appName + "[base]"; + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/basebackend/BaseBackendApplication.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/basebackend/BaseBackendApplication.java new file mode 100644 index 000000000..755704d1d --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/basebackend/BaseBackendApplication.java @@ -0,0 +1,34 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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.tencent.cloud.polaris.router.featureenv.basebackend; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @author lepdou 2022-07-20 + */ +@SpringBootApplication +@EnableFeignClients +public class BaseBackendApplication { + + public static void main(String[] args) { + SpringApplication.run(BaseBackendApplication.class, args); + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..34267f03e --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-backend/src/main/resources/bootstrap.yml @@ -0,0 +1,15 @@ +server: + session-timeout: 1800 + port: 10002 +spring: + application: + name: featureenv-backend-example + cloud: + polaris: + address: grpc://183.47.111.80:8091 + namespace: default + enabled: true +logging: + level: + org.springframework.cloud.gateway: info + com.tencent.cloud.polaris: debug diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/pom.xml new file mode 100644 index 000000000..62f304679 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/pom.xml @@ -0,0 +1,16 @@ + + + + polaris-router-featureenv-base + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + base-front + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/BaseFrontApplication.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/BaseFrontApplication.java new file mode 100644 index 000000000..4197f2367 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/BaseFrontApplication.java @@ -0,0 +1,34 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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.tencent.cloud.polaris.router.featureenv.basefront; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @author lepdou 2022-07-20 + */ +@SpringBootApplication +@EnableFeignClients +public class BaseFrontApplication { + + public static void main(String[] args) { + SpringApplication.run(BaseFrontApplication.class, args); + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/FrontController.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/FrontController.java new file mode 100644 index 000000000..08bc61d5e --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/FrontController.java @@ -0,0 +1,51 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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.tencent.cloud.polaris.router.featureenv.basefront; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author lepdou 2022-07-20 + */ +@RestController +@RequestMapping("/router") +public class FrontController { + + @Value("${spring.application.name}") + private String appName; + + @Autowired + private MiddleService middleService; + + /** + * Get information of callee. + * @return information of callee + */ + @GetMapping("/rest") + public String rest() { + String curName = appName + "[base]"; + String resp = middleService.rest(); + + return curName + " -> " + resp; + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/MiddleService.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/MiddleService.java new file mode 100644 index 000000000..0602481f7 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/basefront/MiddleService.java @@ -0,0 +1,33 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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.tencent.cloud.polaris.router.featureenv.basefront; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; + +/** + * @author lepdou 2022-07-20 + */ +@FeignClient("featureenv-middle-example") +public interface MiddleService { + + @GetMapping("/router/rest") + String rest(); + +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..aab4e3e1d --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-front/src/main/resources/bootstrap.yml @@ -0,0 +1,15 @@ +server: + session-timeout: 1800 + port: 10000 +spring: + application: + name: featureenv-front-example + cloud: + polaris: + address: grpc://183.47.111.80:8091 + namespace: default + enabled: true +logging: + level: + org.springframework.cloud.gateway: info + com.tencent.cloud.polaris: debug diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/pom.xml new file mode 100644 index 000000000..17cc3b701 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/pom.xml @@ -0,0 +1,18 @@ + + + + polaris-router-featureenv-base + com.tencent.cloud + ${revision} + ../pom.xml + + + 4.0.0 + + base-middle + + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/BackendService.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/BackendService.java new file mode 100644 index 000000000..35818bb39 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/BackendService.java @@ -0,0 +1,33 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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.tencent.cloud.polaris.router.featureenv.basemiddle; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; + +/** + * @author lepdou 2022-07-20 + */ +@FeignClient("featureenv-backend-example") +public interface BackendService { + + @GetMapping("/router/rest") + String rest(); + +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/BaseMiddleApplication.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/BaseMiddleApplication.java new file mode 100644 index 000000000..2a88780cf --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/BaseMiddleApplication.java @@ -0,0 +1,34 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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.tencent.cloud.polaris.router.featureenv.basemiddle; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @author lepdou 2022-07-20 + */ +@SpringBootApplication +@EnableFeignClients +public class BaseMiddleApplication { + + public static void main(String[] args) { + SpringApplication.run(BaseMiddleApplication.class, args); + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/MiddleController.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/MiddleController.java new file mode 100644 index 000000000..276993caf --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/basemiddle/MiddleController.java @@ -0,0 +1,51 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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.tencent.cloud.polaris.router.featureenv.basemiddle; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author lepdou 2022-07-20 + */ +@RestController +@RequestMapping("/router") +public class MiddleController { + + @Value("${spring.application.name}") + private String appName; + + @Autowired + private BackendService backendService; + + /** + * Get information of callee. + * @return information of callee + */ + @GetMapping("/rest") + public String rest() { + String curName = appName + "[base]"; + String resp = backendService.rest(); + + return curName + " -> " + resp; + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..d4a9b9312 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/base-middle/src/main/resources/bootstrap.yml @@ -0,0 +1,15 @@ +server: + session-timeout: 1800 + port: 10001 +spring: + application: + name: featureenv-middle-example + cloud: + polaris: + address: grpc://183.47.111.80:8091 + namespace: default + enabled: true +logging: + level: + org.springframework.cloud.gateway: info + com.tencent.cloud.polaris: debug diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/pom.xml new file mode 100644 index 000000000..c0bea706e --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/base/pom.xml @@ -0,0 +1,33 @@ + + + + polaris-router-featureenv-example + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + polaris-router-featureenv-base + pom + + + base-front + base-middle + base-backend + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/pom.xml new file mode 100644 index 000000000..57fa48b17 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/pom.xml @@ -0,0 +1,16 @@ + + + + feature1 + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + feature1-backend + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1backend/BackendController.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1backend/BackendController.java new file mode 100644 index 000000000..9291ba52f --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1backend/BackendController.java @@ -0,0 +1,51 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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.tencent.cloud.polaris.router.featureenv.feature1backend; + +import com.tencent.cloud.common.metadata.StaticMetadataManager; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author lepdou 2022-07-20 + */ +@RestController +@RequestMapping("/router") +public class BackendController { + + @Autowired + private StaticMetadataManager staticMetadataManager; + + @Value("${spring.application.name}") + private String appName; + + /** + * Get information of callee. + * @return information of callee + */ + @GetMapping("/rest") + public String rest() { + String featureEnv = staticMetadataManager.getMergedStaticMetadata().get("featureenv"); + return appName + "[" + featureEnv + "]"; + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1backend/Feature1BackendApplication.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1backend/Feature1BackendApplication.java new file mode 100644 index 000000000..4af96c17f --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1backend/Feature1BackendApplication.java @@ -0,0 +1,34 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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.tencent.cloud.polaris.router.featureenv.feature1backend; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @author lepdou 2022-07-20 + */ +@SpringBootApplication +@EnableFeignClients +public class Feature1BackendApplication { + + public static void main(String[] args) { + SpringApplication.run(Feature1BackendApplication.class, args); + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..04b3ca3a8 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-backend/src/main/resources/bootstrap.yml @@ -0,0 +1,19 @@ +server: + session-timeout: 1800 + port: 11002 +spring: + application: + name: featureenv-backend-example + cloud: + polaris: + address: grpc://183.47.111.80:8091 + namespace: default + enabled: true + tencent: + metadata: + content: + featureenv: feature1 +logging: + level: + org.springframework.cloud.gateway: info + com.tencent.cloud.polaris: debug diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/pom.xml new file mode 100644 index 000000000..873bd1394 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/pom.xml @@ -0,0 +1,16 @@ + + + + feature1 + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + feature1-middle + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/BackendService.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/BackendService.java new file mode 100644 index 000000000..65b91a922 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/BackendService.java @@ -0,0 +1,33 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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.tencent.cloud.polaris.router.featureenv.feature1middle; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; + +/** + * @author lepdou 2022-07-20 + */ +@FeignClient("featureenv-backend-example") +public interface BackendService { + + @GetMapping("/router/rest") + String rest(); + +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/Feature1MiddleApplication.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/Feature1MiddleApplication.java new file mode 100644 index 000000000..c46db04ab --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/Feature1MiddleApplication.java @@ -0,0 +1,34 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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.tencent.cloud.polaris.router.featureenv.feature1middle; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @author lepdou 2022-07-20 + */ +@SpringBootApplication +@EnableFeignClients +public class Feature1MiddleApplication { + + public static void main(String[] args) { + SpringApplication.run(Feature1MiddleApplication.class, args); + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/MiddleController.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/MiddleController.java new file mode 100644 index 000000000..41da83613 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature1middle/MiddleController.java @@ -0,0 +1,58 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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.tencent.cloud.polaris.router.featureenv.feature1middle; + +import com.tencent.cloud.common.metadata.StaticMetadataManager; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author lepdou 2022-07-20 + */ +@RestController +@RequestMapping("/router") +public class MiddleController { + + @Value("${spring.application.name}") + private String appName; + + @Autowired + private BackendService backendService; + + @Autowired + private StaticMetadataManager staticMetadataManager; + + /** + * Get information of callee. + * @return information of callee + */ + @GetMapping("/rest") + public String rest() { + String featureEnv = staticMetadataManager.getMergedStaticMetadata().get("featureenv"); + + String curName = appName + "[" + featureEnv + "]"; + String resp = backendService.rest(); + + return curName + " -> " + resp; + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..1a46790a3 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/feature1-middle/src/main/resources/bootstrap.yml @@ -0,0 +1,19 @@ +server: + session-timeout: 1800 + port: 11001 +spring: + application: + name: featureenv-middle-example + cloud: + polaris: + address: grpc://183.47.111.80:8091 + namespace: default + enabled: true + tencent: + metadata: + content: + featureenv: feature1 +logging: + level: + org.springframework.cloud.gateway: info + com.tencent.cloud.polaris: debug diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/pom.xml new file mode 100644 index 000000000..b364b109c --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature1/pom.xml @@ -0,0 +1,32 @@ + + + + polaris-router-featureenv-example + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + feature1 + pom + + + feature1-middle + feature1-backend + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/pom.xml new file mode 100644 index 000000000..bc2f20a6f --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/pom.xml @@ -0,0 +1,16 @@ + + + + feature2 + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + feature2-backend + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2backend/BackendController.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2backend/BackendController.java new file mode 100644 index 000000000..8b416fb8c --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2backend/BackendController.java @@ -0,0 +1,51 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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.tencent.cloud.polaris.router.featureenv.feature2backend; + +import com.tencent.cloud.common.metadata.StaticMetadataManager; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author lepdou 2022-07-20 + */ +@RestController +@RequestMapping("/router") +public class BackendController { + + @Autowired + private StaticMetadataManager staticMetadataManager; + + @Value("${spring.application.name}") + private String appName; + + /** + * Get information of callee. + * @return information of callee + */ + @GetMapping("/rest") + public String rest() { + String featureEnv = staticMetadataManager.getMergedStaticMetadata().get("featureenv"); + return appName + "[" + featureEnv + "]"; + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2backend/Feature2BackendApplication.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2backend/Feature2BackendApplication.java new file mode 100644 index 000000000..fe1bd3c60 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2backend/Feature2BackendApplication.java @@ -0,0 +1,34 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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.tencent.cloud.polaris.router.featureenv.feature2backend; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @author lepdou 2022-07-20 + */ +@SpringBootApplication +@EnableFeignClients +public class Feature2BackendApplication { + + public static void main(String[] args) { + SpringApplication.run(Feature2BackendApplication.class, args); + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..aece1f3f8 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-backend/src/main/resources/bootstrap.yml @@ -0,0 +1,19 @@ +server: + session-timeout: 1800 + port: 12002 +spring: + application: + name: featureenv-backend-example + cloud: + polaris: + address: grpc://183.47.111.80:8091 + namespace: default + enabled: true + tencent: + metadata: + content: + featureenv: feature2 +logging: + level: + org.springframework.cloud.gateway: info + com.tencent.cloud.polaris: debug diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/pom.xml new file mode 100644 index 000000000..fb4268738 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/pom.xml @@ -0,0 +1,17 @@ + + + + feature2 + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + feature2-front + + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/Feature2FrontApplication.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/Feature2FrontApplication.java new file mode 100644 index 000000000..a6b8bd1fa --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/Feature2FrontApplication.java @@ -0,0 +1,34 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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.tencent.cloud.polaris.router.featureenv.feature2front; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + * @author lepdou 2022-07-20 + */ +@SpringBootApplication +@EnableFeignClients +public class Feature2FrontApplication { + + public static void main(String[] args) { + SpringApplication.run(Feature2FrontApplication.class, args); + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/FrontController.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/FrontController.java new file mode 100644 index 000000000..0c019d742 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/FrontController.java @@ -0,0 +1,58 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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.tencent.cloud.polaris.router.featureenv.feature2front; + +import com.tencent.cloud.common.metadata.StaticMetadataManager; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author lepdou 2022-07-20 + */ +@RestController +@RequestMapping("/router") +public class FrontController { + + @Autowired + private StaticMetadataManager staticMetadataManager; + + @Value("${spring.application.name}") + private String appName; + + @Autowired + private MiddleService middleService; + + /** + * Get information of callee. + * @return information of callee + */ + @GetMapping("/rest") + public String rest() { + String featureEnv = staticMetadataManager.getMergedStaticMetadata().get("featureenv"); + + String curName = appName + "[" + featureEnv + "]"; + String resp = middleService.rest(); + + return curName + " -> " + resp; + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/MiddleService.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/MiddleService.java new file mode 100644 index 000000000..2e0690fdd --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/java/com/tencent/cloud/polaris/router/featureenv/feature2front/MiddleService.java @@ -0,0 +1,33 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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.tencent.cloud.polaris.router.featureenv.feature2front; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; + +/** + * @author lepdou 2022-07-20 + */ +@FeignClient("featureenv-middle-example") +public interface MiddleService { + + @GetMapping("/router/rest") + String rest(); + +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..9fdaa2add --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/feature2-front/src/main/resources/bootstrap.yml @@ -0,0 +1,19 @@ +server: + session-timeout: 1800 + port: 12000 +spring: + application: + name: featureenv-front-example + cloud: + polaris: + address: grpc://183.47.111.80:8091 + namespace: default + enabled: true + tencent: + metadata: + content: + featureenv: feature2 +logging: + level: + org.springframework.cloud.gateway: info + com.tencent.cloud.polaris: debug diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/pom.xml new file mode 100644 index 000000000..f14cbd7d6 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/feature2/pom.xml @@ -0,0 +1,32 @@ + + + + polaris-router-featureenv-example + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + feature2 + pom + + + feature2-front + feature2-backend + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/pom.xml new file mode 100644 index 000000000..f26708819 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/pom.xml @@ -0,0 +1,30 @@ + + + + polaris-router-featureenv-example + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + featureenv-gateway + + + + + org.springframework.cloud + spring-cloud-starter-gateway + + + com.tencent.cloud + spring-cloud-tencent-gateway-plugin + + + com.tencent.cloud + spring-cloud-tencent-featureenv-plugin + + + diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/src/main/java/com/tencent/cloud/polaris/featureenv/gateway/FeatureEnvScgApplication.java b/spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/src/main/java/com/tencent/cloud/polaris/featureenv/gateway/FeatureEnvScgApplication.java new file mode 100644 index 000000000..41835822d --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/src/main/java/com/tencent/cloud/polaris/featureenv/gateway/FeatureEnvScgApplication.java @@ -0,0 +1,33 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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.tencent.cloud.polaris.featureenv.gateway; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author lepdou 2022-07-20 + */ +@SpringBootApplication +public class FeatureEnvScgApplication { + + public static void main(String[] args) { + SpringApplication.run(FeatureEnvScgApplication.class, args); + } + +} diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..6e1972557 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/featureenv-gateway/src/main/resources/bootstrap.yml @@ -0,0 +1,68 @@ +server: + session-timeout: 1800 + port: 9999 +spring: + application: + name: featureenv-gateway + cloud: + tencent: + plugin: + scg: + staining: + enabled: true + rule-staining: + enabled: true + router: + feature-env: + enabled: true + polaris: + address: grpc://183.47.111.80:8091 + namespace: default + enabled: true + gateway: + discovery: + locator: + enabled: true + 'predicates[0]': + name: Path + args: + patterns: '''/'' + serviceId + ''/**''' + 'filters[0]': + name: RewritePath + args: + regexp: '''/'' + serviceId + ''/(?.*)''' + replacement: '''/$\{remaining}''' + 'filters[1]': + name: Retry + args: + retries: 3 + exceptions: + '[0]': '''java.net.ConnectException''' + '[1]': '''java.io.IOException''' + statuses: + '[0]': '''BAD_GATEWAY''' + '[1]': '''SERVICE_UNAVAILABLE''' + series: + '[0]': '''CLIENT_ERROR''' + methods: + '[0]': '''GET''' + '[1]': '''POST''' + '[2]': '''PUT''' + '[3]': '''DELETE''' + backoff: + firstBackoff: '''100ms''' + maxBackoff: '''500ms''' + factor: 2 + basedOnPreviousValue: false + routes: + - id: featureenv-front-example + uri: lb://featureenv-front-example + predicates: + - Path=/featureenv-front-example/** + filters: + - StripPrefix=1 + +logging: + level: + org.springframework.cloud.gateway: info + com.tencent.cloud.polaris: debug diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/imgs/structs.png b/spring-cloud-tencent-examples/polaris-router-featureenv-example/imgs/structs.png new file mode 100644 index 0000000000000000000000000000000000000000..2b8a9c8a11853359c386603b7aeaae595f81163d GIT binary patch literal 56389 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 literal 0 HcmV?d00001 diff --git a/spring-cloud-tencent-examples/polaris-router-featureenv-example/pom.xml b/spring-cloud-tencent-examples/polaris-router-featureenv-example/pom.xml new file mode 100644 index 000000000..c9308f4ba --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-featureenv-example/pom.xml @@ -0,0 +1,34 @@ + + + + spring-cloud-tencent-examples + com.tencent.cloud + ${revision} + ../pom.xml + + 4.0.0 + + polaris-router-featureenv-example + pom + + + base + feature1 + feature2 + featureenv-gateway + + + + + com.tencent.cloud + spring-cloud-starter-tencent-polaris-discovery + + + + com.tencent.cloud + spring-cloud-tencent-featureenv-plugin + + + diff --git a/spring-cloud-tencent-examples/pom.xml b/spring-cloud-tencent-examples/pom.xml index a4c6c9bda..3395e9b04 100644 --- a/spring-cloud-tencent-examples/pom.xml +++ b/spring-cloud-tencent-examples/pom.xml @@ -24,6 +24,7 @@ polaris-router-example metadata-transfer-example polaris-router-grayrelease-example + polaris-router-featureenv-example