From 553667fc165dc8dae86734a8344a9de985800481 Mon Sep 17 00:00:00 2001 From: andrew shan <45474304+andrewshan@users.noreply.github.com> Date: Tue, 24 May 2022 21:08:15 +0800 Subject: [PATCH] optimize gray-release router example 1. optimize gray-release router example 2. fix some router bugs --- .../feign/RouterLabelFeignInterceptor.java | 4 + .../README-zh.md | 263 ++++++++++++++++++ .../README.md | 262 +++++++++++++++++ .../gateway/GatewayController.java | 96 +++---- .../grayrelease/gateway/RouterService.java | 4 +- .../polaris/context/ServiceRuleManager.java | 1 + 6 files changed, 581 insertions(+), 49 deletions(-) create mode 100644 spring-cloud-tencent-examples/polaris-router-grayrelease-example/README-zh.md create mode 100644 spring-cloud-tencent-examples/polaris-router-grayrelease-example/README.md 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 a8d2a5659..ef4ac450f 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 @@ -116,6 +116,10 @@ public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered } // pass label by header + if (escapeLabels.size() == 0) { + requestTemplate.header(RouterConstants.ROUTER_LABEL_HEADER); + return; + } requestTemplate.header(RouterConstants.ROUTER_LABEL_HEADER, JacksonUtils.serialize2Json(escapeLabels)); } diff --git a/spring-cloud-tencent-examples/polaris-router-grayrelease-example/README-zh.md b/spring-cloud-tencent-examples/polaris-router-grayrelease-example/README-zh.md new file mode 100644 index 000000000..eb80b2cc6 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-grayrelease-example/README-zh.md @@ -0,0 +1,263 @@ +# Spring Cloud Polaris Gray Release Example + +[English](./README.md) | 简体中文 + +## 项目说明 + +本项目演示如何使用 Spring Cloud Tencent 的路由和标签透传功能 完成 Spring Cloud 应用的全链路灰度。 + +## 示例架构 + +![](https://qcloudimg.tencent-cloud.cn/raw/488182fd3001b3e77d9450e2c8798ff3.png) + +本示例请求都通过最上层网关进行分发,分发的目的地主要涉及3个环境: +- 灰度环境1(只针对uid=1的请求放开),环境标识为env=green(绿色环境) +- 灰度环境2(只针对uid=2的请求放开),环境标识为env=purple(紫色环境) +- 基线环境(稳定的业务版本,针对其他请求放开),环境标识为env=blue(蓝色环境) + +## 如何接入 + +### 启动网关服务 + +1. 添加环境变量 + + - 北极星服务端地址:polaris_address=grpc://127.0.0.1:8091 + - 可观测性PushGateway地址:prometheus_address=127.0.0.1:9091 + +2. 启动router-grayrelease-gateway应用 + + - IDE直接启动:找到主类 `GrayReleaseGatewayApplication`,执行 main 方法启动应用。 + - 打包编译后启动:首先执行 `mvn clean package` 将工程编译打包,然后执行 `java -jar router-grayrelease-gateway-${verion}.jar`启动应用。 + +3. 添加路由规则 + + 通过往北极星接口发送以下数据,为网关服务添加路由规则,路由规则可以针对用户ID进行环境的分发。 + ```` + POST /naming/v1/routings + + [{ + "service": "gray-release-gateway", + "namespace": "default", + "outbounds": [ + { + "sources": [ + { + "service": "gray-release-gateway", + "namespace": "default", + "metadata": { + "${http.header.uid}": { + "type": "EXACT", + "value": "2" + } + } + }], + "destinations": [ + { + "service": "*", + "namespace": "*", + "metadata": { + "env": { + "type": "EXACT", + "value": "purple" + } + }, + "priority": 0, + "weight": 100, + "isolate": false + }] + }, + { + "sources": [ + { + "service": "gray-release-gateway", + "namespace": "default", + "metadata": { + "${http.header.uid}": { + "type": "EXACT", + "value": "1" + } + } + }], + "destinations": [ + { + "service": "*", + "namespace": "*", + "metadata": { + "env": { + "type": "EXACT", + "value": "green" + } + }, + "priority": 0, + "weight": 100, + "isolate": false + }] + }, + { + "sources": [ + { + "service": "gray-release-gateway", + "namespace": "default", + "metadata": { + "*": { + "type": "EXACT", + "value": "*" + } + } + }], + "destinations": [ + { + "service": "*", + "namespace": "*", + "metadata": { + "env": { + "type": "EXACT", + "value": "blue" + } + }, + "priority": 0, + "weight": 100, + "isolate": false + }] + } + ] + }] + ```` + + 路由规则也可以通过北极星控制台进行定义,最终控制台效果如下: + + ![](https://qcloudimg.tencent-cloud.cn/raw/28e3d734c4b73624869a5b9b7059b118.png) + +### 启动Front服务 + +#### 启动基线环境(蓝色) + +1. 添加环境变量 + + - 北极星服务端地址:polaris_address=grpc://127.0.0.1:8091 + - 可观测性PushGateway地址:prometheus_address=127.0.0.1:9091 + - 环境标识:SCT_METADATA_CONTENT_env=blue + - 透传环境标识:SCT_METADATA_CONTENT_TRANSITIVE=env + +2. 启动router-grayrelease-frontend应用 + + - IDE直接启动:找到主类 `GrayReleaseFrontApplication`,执行 main 方法启动应用。 + - 打包编译后启动:首先执行 `mvn clean package` 将工程编译打包,然后执行 `java -jar router-grayrelease-frontend-${verion}.jar`启动应用。 + +#### 启动灰度环境1(绿色) + +1. 添加环境变量 + + - 北极星服务端地址:polaris_address=grpc://127.0.0.1:8091 + - 可观测性PushGateway地址:prometheus_address=127.0.0.1:9091 + - 环境标识:SCT_METADATA_CONTENT_env=green + - 透传环境标识:SCT_METADATA_CONTENT_TRANSITIVE=env + +2. 启动router-grayrelease-frontend应用(与前面一致) + + 如果遇到端口冲突,可以通过-Dserver.port来指定端口 + +#### 启动灰度环境2(紫色) + +1. 添加环境变量 + + - 北极星服务端地址:polaris_address=grpc://127.0.0.1:8091 + - 可观测性PushGateway地址:prometheus_address=127.0.0.1:9091 + - 环境标识:SCT_METADATA_CONTENT_env=purple + - 透传环境标识:SCT_METADATA_CONTENT_TRANSITIVE=env + +2. 启动router-grayrelease-frontend应用(与前面一致) + +#### 启动后效果 + +在北极星控制台,可以看到gray-release-front服务下有3个节点,每个节点有不同的环境标识。 + +![](https://qcloudimg.tencent-cloud.cn/raw/96d2bdd2fb3495f737ab278e31a4a2e7.png) + +### 启动middle服务 + +#### 启动基线环境(蓝色) + +1. 添加环境变量 + + - 北极星服务端地址:polaris_address=grpc://127.0.0.1:8091 + - 可观测性PushGateway地址:prometheus_address=127.0.0.1:9091 + - 环境标识:SCT_METADATA_CONTENT_env=blue + - 透传环境标识:SCT_METADATA_CONTENT_TRANSITIVE=env + +2. 启动router-grayrelease-middle应用 + + - IDE直接启动:找到主类 `GrayReleaseMiddleApplication`,执行 main 方法启动应用。 + - 打包编译后启动:首先执行 `mvn clean package` 将工程编译打包,然后执行 `java -jar router-grayrelease-middle-${verion}.jar`启动应用。 + + +#### 启动灰度环境2(紫色) + +1. 添加环境变量 + + - 北极星服务端地址:polaris_address=grpc://127.0.0.1:8091 + - 可观测性PushGateway地址:prometheus_address=127.0.0.1:9091 + - 环境标识:SCT_METADATA_CONTENT_env=purple + - 透传环境标识:SCT_METADATA_CONTENT_TRANSITIVE=env + +2. 启动router-grayrelease-middle应用(与前面一致) + +### 启动back服务 + +#### 启动基线环境(蓝色) + +1. 添加环境变量 + + - 北极星服务端地址:polaris_address=grpc://127.0.0.1:8091 + - 可观测性PushGateway地址:prometheus_address=127.0.0.1:9091 + - 环境标识:SCT_METADATA_CONTENT_env=blue + - 透传环境标识:SCT_METADATA_CONTENT_TRANSITIVE=env + +2. 启动router-grayrelease-backend应用 + + - IDE直接启动:找到主类 `GrayReleaseBackendApplication`,执行 main 方法启动应用。 + - 打包编译后启动:首先执行 `mvn clean package` 将工程编译打包,然后执行 `java -jar router-grayrelease-backend-${verion}.jar`启动应用。 + +#### 启动灰度环境1(绿色) + +1. 添加环境变量 + + - 北极星服务端地址:polaris_address=grpc://127.0.0.1:8091 + - 可观测性PushGateway地址:prometheus_address=127.0.0.1:9091 + - 环境标识:SCT_METADATA_CONTENT_env=green + - 透传环境标识:SCT_METADATA_CONTENT_TRANSITIVE=env + +2. 启动router-grayrelease-backend应用(与前面一致) + +### 测试 + +#### 基线环境路由 + +```` +curl -H'uid:0' 127.0.0.1:59100/router/gray/route_rule +```` +获取结果 +```` +gray-release-gateway -> gray-release-front[blue] -> gray-release-middle[blue] -> gray-release-back[blue] +```` + +#### 灰度环境1(绿色)路由 + +```` +curl -H'uid:1' 127.0.0.1:59100/router/gray/route_rule +```` +获取结果 +```` +gray-release-gateway -> gray-release-front[green] -> gray-release-middle[blue] -> gray-release-back[green] +```` + +#### 灰度环境2(紫色)路由 + +```` +curl -H'uid:2' 127.0.0.1:59100/router/gray/route_rule +```` +获取结果 +```` +gray-release-gateway -> gray-release-front[purple] -> gray-release-middle[purple] -> gray-release-back[blue] +```` + diff --git a/spring-cloud-tencent-examples/polaris-router-grayrelease-example/README.md b/spring-cloud-tencent-examples/polaris-router-grayrelease-example/README.md new file mode 100644 index 000000000..8ad68bbeb --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-grayrelease-example/README.md @@ -0,0 +1,262 @@ +# Spring Cloud Polaris Gray Release Example + +English | [简体中文](./README-zh.md) + +## Project Explanation + +This project shows how to use Spring Cloud Tencent route and transitive feature to do the full chain gray releasing. + +## Architecture + +![](https://qcloudimg.tencent-cloud.cn/raw/488182fd3001b3e77d9450e2c8798ff3.png) + +Incoming requests dispatched from Gateway service to 3 environments: +- gray1(match uid=1), env=green(green environment) +- gray2(match uid=2), env=purple(purple environment) +- baseline(stable environment, match all other requests), env=blue(blue environment) + +## How to access + +### Start Gateway service + +1. add environment variables + + - polaris server address: polaris_address=grpc://127.0.0.1:8091 + - pushgateway address: prometheus_address=127.0.0.1:9091 + +2. start router-grayrelease-gateway application + + - Launch by IDE:Start the main class `GrayReleaseGatewayApplication`. + - Launch by Jar:Execute `mvn clean package` to compile with jar package, then use `java -jar router-grayrelease-gateway-${verion}.jar` to launch application. + +3. add the route rule + + Send http request to polaris server to add the route rule, make requests dispatched to 3 environments. + ```` + POST /naming/v1/routings + + [{ + "service": "gray-release-gateway", + "namespace": "default", + "outbounds": [ + { + "sources": [ + { + "service": "gray-release-gateway", + "namespace": "default", + "metadata": { + "${http.header.uid}": { + "type": "EXACT", + "value": "2" + } + } + }], + "destinations": [ + { + "service": "*", + "namespace": "*", + "metadata": { + "env": { + "type": "EXACT", + "value": "purple" + } + }, + "priority": 0, + "weight": 100, + "isolate": false + }] + }, + { + "sources": [ + { + "service": "gray-release-gateway", + "namespace": "default", + "metadata": { + "${http.header.uid}": { + "type": "EXACT", + "value": "1" + } + } + }], + "destinations": [ + { + "service": "*", + "namespace": "*", + "metadata": { + "env": { + "type": "EXACT", + "value": "green" + } + }, + "priority": 0, + "weight": 100, + "isolate": false + }] + }, + { + "sources": [ + { + "service": "gray-release-gateway", + "namespace": "default", + "metadata": { + "*": { + "type": "EXACT", + "value": "*" + } + } + }], + "destinations": [ + { + "service": "*", + "namespace": "*", + "metadata": { + "env": { + "type": "EXACT", + "value": "blue" + } + }, + "priority": 0, + "weight": 100, + "isolate": false + }] + } + ] + }] + ```` + + The route rule can be added by polaris console: + + ![](https://qcloudimg.tencent-cloud.cn/raw/28e3d734c4b73624869a5b9b7059b118.png) + +### Start Front service + +#### Start baseline environment (blue) + +1. add environment variables + + - polaris server address: polaris_address=grpc://127.0.0.1:8091 + - pushgateway address: prometheus_address=127.0.0.1:9091 + - env tag:SCT_METADATA_CONTENT_env=blue + - transitive tag:SCT_METADATA_CONTENT_TRANSITIVE=env + +2. start router-grayrelease-frontend application + + - Launch by IDE:Start the main class `GrayReleaseFrontApplication`. + - Launch by Jar:Execute `mvn clean package` to compile with jar package, then use `java -jar router-grayrelease-frontend-${verion}.jar` to launch application. + +#### Start gray1 environment (green) + +1. add environment variables + + - polaris server address: polaris_address=grpc://127.0.0.1:8091 + - pushgateway address: prometheus_address=127.0.0.1:9091 + - env tag:SCT_METADATA_CONTENT_env=green + - transitive tag:SCT_METADATA_CONTENT_TRANSITIVE=env + +2. start router-grayrelease-frontend application (same as previous instruction) + + If port conflicted, you can specify another port by -Dserver.port + +#### Start gray2 environment (purple) + +1. add environment variables + + - polaris server address: polaris_address=grpc://127.0.0.1:8091 + - pushgateway address: prometheus_address=127.0.0.1:9091 + - env tag:SCT_METADATA_CONTENT_env=purple + - transitive tag:SCT_METADATA_CONTENT_TRANSITIVE=env + +2. start router-grayrelease-frontend application (same as previous instruction) + +#### Start effective + +You can find the instances with different tags in polaris console. + +![](https://qcloudimg.tencent-cloud.cn/raw/96d2bdd2fb3495f737ab278e31a4a2e7.png) + +### Start Middle service + +#### Start baseline environment (blue) + +1. add environment variables + + - polaris server address: polaris_address=grpc://127.0.0.1:8091 + - pushgateway address: prometheus_address=127.0.0.1:9091 + - env tag:SCT_METADATA_CONTENT_env=blue + - transitive tag:SCT_METADATA_CONTENT_TRANSITIVE=env + +2. start router-grayrelease-middle application + + - Launch by IDE:Start the main class `GrayReleaseMiddleApplication`. + - Launch by Jar:Execute `mvn clean package` to compile with jar package, then use `java -jar router-grayrelease-middle-${verion}.jar` to launch application. + +#### Start gray2 environment (purple) + +1. add environment variables + + - polaris server address: polaris_address=grpc://127.0.0.1:8091 + - pushgateway address: prometheus_address=127.0.0.1:9091 + - env tag:SCT_METADATA_CONTENT_env=purple + - transitive tag:SCT_METADATA_CONTENT_TRANSITIVE=env + +2. start router-grayrelease-middle application (same as previous instruction) + +### Start Back service + +#### Start baseline environment (blue) + +1. add environment variables + + - polaris server address: polaris_address=grpc://127.0.0.1:8091 + - pushgateway address: prometheus_address=127.0.0.1:9091 + - env tag:SCT_METADATA_CONTENT_env=blue + - transitive tag:SCT_METADATA_CONTENT_TRANSITIVE=env + +2. start router-grayrelease-backend application + + - Launch by IDE:Start the main class `GrayReleaseBackendApplication`. + - Launch by Jar:Execute `mvn clean package` to compile with jar package, then use `java -jar router-grayrelease-backend-${verion}.jar` to launch application. + +#### Start gray1 environment (green) + +1. add environment variables + + - polaris server address: polaris_address=grpc://127.0.0.1:8091 + - pushgateway address: prometheus_address=127.0.0.1:9091 + - env tag:SCT_METADATA_CONTENT_env=green + - transitive tag:SCT_METADATA_CONTENT_TRANSITIVE=env + +2. start router-grayrelease-backend application (same as previous instruction) + +### Test + +#### Baseline routing + +```` +curl -H'uid:0' 127.0.0.1:59100/router/gray/route_rule +```` +Got result +```` +gray-release-gateway -> gray-release-front[blue] -> gray-release-middle[blue] -> gray-release-back[blue] +```` + +#### Green routing + +```` +curl -H'uid:1' 127.0.0.1:59100/router/gray/route_rule +```` +Got result +```` +gray-release-gateway -> gray-release-front[green] -> gray-release-middle[blue] -> gray-release-back[green] +```` + +#### Purple routing + +```` +curl -H'uid:2' 127.0.0.1:59100/router/gray/route_rule +```` +Got result +```` +gray-release-gateway -> gray-release-front[purple] -> gray-release-middle[purple] -> gray-release-back[blue] +```` + diff --git a/spring-cloud-tencent-examples/polaris-router-grayrelease-example/router-grayrelease-gateway/src/main/java/com/tencent/cloud/polaris/router/grayrelease/gateway/GatewayController.java b/spring-cloud-tencent-examples/polaris-router-grayrelease-example/router-grayrelease-gateway/src/main/java/com/tencent/cloud/polaris/router/grayrelease/gateway/GatewayController.java index 1486d334c..cee5a465c 100644 --- a/spring-cloud-tencent-examples/polaris-router-grayrelease-example/router-grayrelease-gateway/src/main/java/com/tencent/cloud/polaris/router/grayrelease/gateway/GatewayController.java +++ b/spring-cloud-tencent-examples/polaris-router-grayrelease-example/router-grayrelease-gateway/src/main/java/com/tencent/cloud/polaris/router/grayrelease/gateway/GatewayController.java @@ -1,47 +1,49 @@ -/* - * 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.grayrelease.gateway; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.env.Environment; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/router/gray") -public class GatewayController { - - @Autowired - private Environment environment; - - @Autowired - private RouterService routerService; - - /** - * Get information of callee. - * @return information of callee - */ - @GetMapping("/entry") - public String rest() { - String appName = environment.getProperty("spring.application.name"); - String resp = routerService.rest(); - return appName + " -> " + resp; - } -} +/* + * 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.grayrelease.gateway; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/router/gray") +public class GatewayController { + + @Autowired + private Environment environment; + + @Autowired + private RouterService routerService; + + /** + * Get information of callee. + * @return information of callee + */ + @GetMapping("/route_rule") + public String routeRule(@RequestHeader("uid") int userId) { + String appName = environment.getProperty("spring.application.name"); + String resp = routerService.restByUser(userId); + return appName + " -> " + resp; + } + +} diff --git a/spring-cloud-tencent-examples/polaris-router-grayrelease-example/router-grayrelease-gateway/src/main/java/com/tencent/cloud/polaris/router/grayrelease/gateway/RouterService.java b/spring-cloud-tencent-examples/polaris-router-grayrelease-example/router-grayrelease-gateway/src/main/java/com/tencent/cloud/polaris/router/grayrelease/gateway/RouterService.java index 95f066f8a..23ffb30a0 100644 --- a/spring-cloud-tencent-examples/polaris-router-grayrelease-example/router-grayrelease-gateway/src/main/java/com/tencent/cloud/polaris/router/grayrelease/gateway/RouterService.java +++ b/spring-cloud-tencent-examples/polaris-router-grayrelease-example/router-grayrelease-gateway/src/main/java/com/tencent/cloud/polaris/router/grayrelease/gateway/RouterService.java @@ -20,6 +20,7 @@ package com.tencent.cloud.polaris.router.grayrelease.gateway; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; /** * Router callee feign client. @@ -30,6 +31,5 @@ import org.springframework.web.bind.annotation.GetMapping; public interface RouterService { @GetMapping("/router/gray/rest") - String rest(); - + String restByUser(@RequestHeader("uid") int user); } diff --git a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/ServiceRuleManager.java b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/ServiceRuleManager.java index 8b3fb16d4..1a0af32b4 100644 --- a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/ServiceRuleManager.java +++ b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/ServiceRuleManager.java @@ -84,6 +84,7 @@ public class ServiceRuleManager { ServiceEventKey srcSvcEventKey = new ServiceEventKey(new ServiceKey(namespace, sourceService), ServiceEventKey.EventType.ROUTING); + routerKeys.add(srcSvcEventKey); DefaultServiceEventKeysProvider svcKeysProvider = new DefaultServiceEventKeysProvider(); svcKeysProvider.setSvcEventKeys(routerKeys);