From 935bb2a45478780366d64576318888f93828def9 Mon Sep 17 00:00:00 2001 From: tanghc Date: Thu, 16 Jan 2020 18:20:58 +0800 Subject: [PATCH] 3.0.0 --- doc/docs/_sidebar.md | 69 +++++++------- doc/docs/files/10110_预发布灰度发布.md | 22 +++-- ...14_原理分析之预发布灰度发布.md | 92 +++++++++++++++++++ ...项.md => 90099_2.x升3.x注意事项.md} | 0 .../BaseGatewayConfiguration.java | 4 +- .../LoadBalanceServerChooser.java | 7 +- 6 files changed, 148 insertions(+), 46 deletions(-) create mode 100644 doc/docs/files/90014_原理分析之预发布灰度发布.md rename doc/docs/files/{90014_2.x升3.x注意事项.md => 90099_2.x升3.x注意事项.md} (100%) diff --git a/doc/docs/_sidebar.md b/doc/docs/_sidebar.md index b0701362..b48ca6d2 100644 --- a/doc/docs/_sidebar.md +++ b/doc/docs/_sidebar.md @@ -1,36 +1,37 @@ -* [首页](/?t=1578910309712) +* [首页](/?t=1579169719974) * 开发文档 - * [快速体验](files/10010_快速体验.md?t=1578910309714) - * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1578910309731) - * [新增接口](files/10020_新增接口.md?t=1578910309732) - * [开发流程](files/10021_开发流程.md?t=1578910309732) - * [业务参数校验](files/10030_业务参数校验.md?t=1578910309732) - * [错误处理](files/10040_错误处理.md?t=1578910309732) - * [编写文档](files/10041_编写文档.md?t=1578910309732) - * [接口交互详解](files/10050_接口交互详解.md?t=1578910309732) - * [easyopen支持](files/10070_easyopen支持.md?t=1578910309732) - * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1578910309732) - * [ISV管理](files/10085_ISV管理.md?t=1578910309732) - * [自定义返回结果](files/10087_自定义返回结果.md?t=1578910309733) - * [自定义过滤器](files/10088_自定义过滤器.md?t=1578910309733) - * [自定义校验token](files/10089_自定义校验token.md?t=1578910309733) - * [路由授权](files/10090_路由授权.md?t=1578910309733) - * [接口限流](files/10092_接口限流.md?t=1578910309733) - * [监控日志](files/10093_监控日志.md?t=1578910309733) - * [SDK开发](files/10095_SDK开发.md?t=1578910309733) - * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1578910309733) - * [应用授权](files/10097_应用授权.md?t=1578910309733) - * [提供restful接口](files/10100_提供restful接口.md?t=1578910309733) - * [文件上传](files/10104_文件上传.md?t=1578910309734) - * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1578910309734) - * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1578910309734) - * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1578910309734) - * [使用eureka](files/10112_使用eureka.md?t=1578910309734) - * [扩展其它注册中心](files/10113_扩展其它注册中心.md?t=1578910309734) + * [快速体验](files/10010_快速体验.md?t=1579169719976) + * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1579169719993) + * [新增接口](files/10020_新增接口.md?t=1579169719993) + * [开发流程](files/10021_开发流程.md?t=1579169719993) + * [业务参数校验](files/10030_业务参数校验.md?t=1579169719993) + * [错误处理](files/10040_错误处理.md?t=1579169719993) + * [编写文档](files/10041_编写文档.md?t=1579169719993) + * [接口交互详解](files/10050_接口交互详解.md?t=1579169719993) + * [easyopen支持](files/10070_easyopen支持.md?t=1579169719993) + * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1579169719993) + * [ISV管理](files/10085_ISV管理.md?t=1579169719994) + * [自定义返回结果](files/10087_自定义返回结果.md?t=1579169719994) + * [自定义过滤器](files/10088_自定义过滤器.md?t=1579169719994) + * [自定义校验token](files/10089_自定义校验token.md?t=1579169719994) + * [路由授权](files/10090_路由授权.md?t=1579169719994) + * [接口限流](files/10092_接口限流.md?t=1579169719994) + * [监控日志](files/10093_监控日志.md?t=1579169719994) + * [SDK开发](files/10095_SDK开发.md?t=1579169719994) + * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1579169719994) + * [应用授权](files/10097_应用授权.md?t=1579169719994) + * [提供restful接口](files/10100_提供restful接口.md?t=1579169719995) + * [文件上传](files/10104_文件上传.md?t=1579169719995) + * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1579169719995) + * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1579169719995) + * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1579169719995) + * [使用eureka](files/10112_使用eureka.md?t=1579169719995) + * [扩展其它注册中心](files/10113_扩展其它注册中心.md?t=1579169719995) * 原理分析 - * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1578910309734) - * [原理分析之如何存储路由](files/90011_原理分析之如何存储路由.md?t=1578910309734) - * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1578910309734) - * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1578910309734) - * [2.x升3.x注意事项](files/90014_2.x升3.x注意事项.md?t=1578910309734) - * [常见问题](files/90100_常见问题.md?t=1578910309734) + * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1579169719995) + * [原理分析之如何存储路由](files/90011_原理分析之如何存储路由.md?t=1579169719995) + * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1579169719995) + * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1579169719996) + * [原理分析之预发布灰度发布](files/90014_原理分析之预发布灰度发布.md?t=1579169719996) + * [2.x升3.x注意事项](files/90099_2.x升3.x注意事项.md?t=1579169719996) + * [常见问题](files/90100_常见问题.md?t=1579169719996) diff --git a/doc/docs/files/10110_预发布灰度发布.md b/doc/docs/files/10110_预发布灰度发布.md index a468e932..6b469196 100644 --- a/doc/docs/files/10110_预发布灰度发布.md +++ b/doc/docs/files/10110_预发布灰度发布.md @@ -4,14 +4,20 @@ ## 使用预发布 -假设网关工程在阿里云负载均衡有两台服务器,域名分别为: +SOP中预发布的思路如下: + +假设网关工程sop-gateway在阿里云负载均衡有两台服务器,域名分别为: |域名|说明| |:---- |:---- | |open1.domain.com |网关服务器1 | |openpre.domain.com | 网关服务器2,作为预发布请求入口| -线上网关入口为`http://open.domain.com/`,请求网关`http://open.domain.com/`会负载均衡到这两台服务器 +SLB对外域名为:`open.domain.com`,即开放平台入口为:`http://open.domain.com` + +访问`open.domain.com`会负载均衡到`open1.domain.com`和`openpre.domain.com`这两台实例 + +如果单独从`openpre.domain.com`访问,则会访问到预发布微服务。 SOP开启预发布步骤如下: @@ -21,13 +27,16 @@ SOP开启预发布步骤如下: # 预发布网关域名,多个用英文逗号(,)隔开 pre.domain=openpre.domain.com ``` + 重启网关 + 微服务启动参数添加:`--spring.cloud.nacos.discovery.metadata.env=pre`(eureka下是:`--eureka.instance.metadata-map.env=pre`)。 -建议线上配两套启动脚本,其中预发布启动脚本添加启动参数`--eureka.instance.metadata-map.env=pre` +建议线上配两套启动脚本,其中预发布启动脚本添加启动参数`--spring.cloud.nacos.discovery.metadata.env=pre` + +登录SOP-Admin,在服务列表中点击预发布。 -登录SOP-Admin,在服务列表中点击预发布,然后预发布请求地址变成:`http://openpre.domain.com/`。 -从`openpre.domain.com`请求进来的用户都会进预发布服务器,其它情况都走非预发布服务器。 +从`openpre.domain.com`请求进来的用户都会进预发布服务器,从SLB域名进来请求路由到非预发服务器 ## 使用灰度发布 @@ -41,8 +50,7 @@ pre.domain=openpre.domain.com 参考类: -- SopLoadBalancerClient.java gateway网关下预发布/灰度服务选取 -- EnvironmentServerChooser.java zuul网关下预发布/灰度服务选取 +- LoadBalanceServerChooser.java 预发布/灰度发布服务实例选择 ### 自定义判断灰度用户 diff --git a/doc/docs/files/90014_原理分析之预发布灰度发布.md b/doc/docs/files/90014_原理分析之预发布灰度发布.md new file mode 100644 index 00000000..04bc5350 --- /dev/null +++ b/doc/docs/files/90014_原理分析之预发布灰度发布.md @@ -0,0 +1,92 @@ +# 原理分析之预发布灰度发布 + +SOP网关采用`自定义负载均衡策略`来实现对预发布/灰度发布服务器实例的选择。 + +spring cloud gateway默认的负载均衡实现类在:`org.springframework.cloud.gateway.filter.LoadBalancerClientFilter.java`中 + +这个类主要做了几件事情: + +1. 解析出请求路径中的scheme +2. 如果scheme不是以`lb`协议开头直接跳过 +3. 如果scheme以`lb`协议开头,则说明需要进行负载均衡,选出一台微服务实例 +4. 将`lb`协议解析成`http://ip:port`,继续向下请求 + +其中第4步是由`org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient`来完成的, +我们只要分别继承`LoadBalancerClientFilter`和`RibbonLoadBalancerClient`,然后重写其中的方法就能完成自定义负载均衡。 + +SOP中的重写类是:`SopLoadBalancerClientFilter`和`SopLoadBalancerClient`,核心代码委托给了`LoadBalanceServerChooser`处理,核心代码如下: + +```java + /** + * 选择服务器 + * + * @param serviceId serviceId,仅gateway网关有作用 + * @param exchange 请求上下文 + * @param loadBalancer loadBalancer + * @param superChooser 父类默认的选择 + * @param serverChooserFunction 执行选择操作 + * @return 返回服务器实例,没有选到则返回null + */ + public R choose( + String serviceId + , T exchange + , ILoadBalancer loadBalancer + , Supplier superChooser + , Function, R> serverChooserFunction) { + // 获取所有服务实例 + List servers = loadBalancer.getReachableServers(); + + // 存放预发服务器 + List preServers = new ArrayList<>(4); + // 存放灰度发布服务器 + List grayServers = new ArrayList<>(4); + // 存放非预发服务器 + List notPreServers = new ArrayList<>(4); + + for (Server server : servers) { + // 获取实例metadata + Map metadata = getMetadata(serviceId, server); + // 是否开启了预发模式 + if (this.isPreServer(metadata)) { + preServers.add(server); + } else if (this.isGrayServer(metadata)) { + grayServers.add(server); + } else { + notPreServers.add(server); + } + } + notPreServers.addAll(grayServers); + // 如果没有开启预发布服务和灰度发布,直接用默认的方式 + if (preServers.isEmpty() && grayServers.isEmpty()) { + return superChooser.get(); + } + // 如果是从预发布域名访问过来,则认为是预发布请求,选出预发服务器 + if (this.isRequestFromPreDomain(exchange)) { + return serverChooserFunction.apply(preServers); + } + // 如果是灰度请求,则认为是灰度用户,选出灰度服务器 + if (this.isRequestGrayServer(exchange)) { + return serverChooserFunction.apply(grayServers); + } + + // 到这里说明不能访问预发/灰度服务器,则需要路由到非预发服务器 + // 注意:这里允许走灰度服务器,如果不允许走,注释notPreServers.addAll(grayServers);这行 + return serverChooserFunction.apply(notPreServers); + } +``` + +其业务逻辑如下: + +1. 选出`serviceId`对应的所有服务器实例 +2. 将服务器实例进行分类,分别放进`预发布List`,`灰度List`,`非预发布List`中 +3. 如果`预发布List`,`灰度List`都为空,表示没有开启任何预发/灰度服务,直接使用父类的负载均衡策略 +4. 如果是从预发布域名访问过来,则认为是预发布请求,选出预发服务器 +5. 如果是灰度请求,则认为是灰度用户,选出灰度服务器 +6. 最后剩下的是正常用户,正常用户不能走预发环境 + +## 参考类 + +- com.gitee.sop.gatewaycommon.gateway.filter.SopLoadBalancerClientFilter +- com.gitee.sop.gatewaycommon.gateway.loadbalancer.SopLoadBalancerClient +- com.gitee.sop.gatewaycommon.gateway.loadbalancer.GatewayLoadBalanceServerChooser + diff --git a/doc/docs/files/90014_2.x升3.x注意事项.md b/doc/docs/files/90099_2.x升3.x注意事项.md similarity index 100% rename from doc/docs/files/90014_2.x升3.x注意事项.md rename to doc/docs/files/90099_2.x升3.x注意事项.md diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/configuration/BaseGatewayConfiguration.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/configuration/BaseGatewayConfiguration.java index 815ff647..f65151a4 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/configuration/BaseGatewayConfiguration.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/configuration/BaseGatewayConfiguration.java @@ -119,7 +119,7 @@ public class BaseGatewayConfiguration extends AbstractConfiguration { } /** - * 扩展默认的负载均衡选择,默认使用的是RibbonLoadBalancerClient。当配置了pre.domain时才生效 + * 扩展默认的负载均衡选择,默认使用的是RibbonLoadBalancerClient * @param clientFactory * @return */ @@ -129,7 +129,7 @@ public class BaseGatewayConfiguration extends AbstractConfiguration { } /** - * 扩展默认的负载均衡过滤器,默认是LoadBalancerClientFilter。当配置了pre.domain时才生效 + * 扩展默认的负载均衡过滤器,默认是LoadBalancerClientFilter * @param sopLoadBalancerClient SopLoadBalancerClient * @param loadBalancerProperties loadBalancerProperties * @return diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/LoadBalanceServerChooser.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/LoadBalanceServerChooser.java index 0cea6478..11dba443 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/LoadBalanceServerChooser.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/loadbalancer/LoadBalanceServerChooser.java @@ -32,7 +32,7 @@ public abstract class LoadBalanceServerChooser implements ServerChooserCon * @param loadBalancer loadBalancer * @param superChooser 父类默认的选择 * @param serverChooserFunction 执行选择操作 - * @return 返回服务器实例 + * @return 返回服务器实例,没有选到则返回null */ public R choose( String serviceId @@ -67,16 +67,17 @@ public abstract class LoadBalanceServerChooser implements ServerChooserCon if (preServers.isEmpty() && grayServers.isEmpty()) { return superChooser.get(); } - // 如果是从预发布域名访问过来,则认为是预发布请求 + // 如果是从预发布域名访问过来,则认为是预发布请求,选出预发服务器 if (this.isRequestFromPreDomain(exchange)) { return serverChooserFunction.apply(preServers); } - // 如果是灰度请求 + // 如果是灰度请求,则认为是灰度用户,选出灰度服务器 if (this.isRequestGrayServer(exchange)) { return serverChooserFunction.apply(grayServers); } // 到这里说明不能访问预发/灰度服务器,则需要路由到非预发服务器 + // 注意:这里允许走灰度服务器,如果不允许走,注释notPreServers.addAll(grayServers);这行 return serverChooserFunction.apply(notPreServers); }