11.落地:微服务架构灰度发布方案
创始人
2024-06-03 15:37:46
0

前置知识

1.nacos 服务注册与发现

2.本地负载均衡器算法

3.gateway 网关

4.ThreadLocal

1.什么是灰度发布?
2.什么是灰度策略?
3.灰度发布落地方案有哪些
4.灰度发布架构设计原理 nginx+lua?
5.如何基于GateWay+Nacos构建灰度环境
6.GateWay负载均衡路由算法原理------改写
7.如何重写本地负载均衡器,走灰度环境
8.为何不基于nginx+lua实现?而使用GateWay
9.代码落地实战:构建微服务灰度发布环境

什么是灰度发布

接口地址----服务治理框架

灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式。在其上可以进行A/B testing,即让一部分用户继续用产品特性A,一部分用户开始用产品特性B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。

灰度期:灰度发布开始到结束期间的这一段时间,称为灰度期。

灰度发布能及早获得用户的意见反馈,完善产品功能,提升产品质量,让用户参与产品测试,加强与用户互动,降低产品升级所影响的用户范围。

整合服务注册中心

灰度发布落地方案

1.nginx+lua+nacos 实现(需要懂lua脚本);—

2.gateway+nacos+重写本地负载均衡器 (java实现)—java程序员推荐 性能没有直接

通过nginx实现效率高;

gateway+nacos实现灰度发布原理

img

服务注册

1.服务注册时,需要指定注册到nacos元数据 自定义版本号码:

例如:正式环境 version =1.0 灰度环境 version=2.0

img

2.配置文件中需要整合

server:port: 7053
spring:application:name: mayikt-member  #服务名称 在 注册中心展示服务名称 --cloud:nacos:discovery:server-addr: 127.0.0.1:8848 # nacos服务注册中心Server端 地址metadata:version: 2.0 # 指定 元数据版本号码

构建微服务网关

构建微服务网关

访问http://127.0.0.1:81/mayikt-member/member 路由转发到

会员服务。

配置文件内容:

spring:application:###服务的名称name: mayikt-gatewaycloud:nacos:discovery:###nacos注册地址server-addr: 127.0.0.1:8848config:server-addr: 127.0.0.1:8848file-extension: ymlgateway:routes:- id: mayikt-memberuri: lb://mayikt-memberfilters:- StripPrefix=1predicates:- Path=/mayikt-member/**

maven依赖:

org.springframework.cloudspring-cloud-starter-gateway2.0.0.RELEASEorg.springframework.cloudspring-cloud-starter-alibaba-nacos-discovery0.2.2.RELEASEorg.springframework.cloudspring-cloud-starter-alibaba-nacos-config0.2.2.RELEASE

编写灰度发布用户

  1. 自定义参数
  2. 指定token—userid
  3. 请求来源ip

创建过滤器判断是否是灰度用户

import com.mayikt.gateway.manage.GrayscaleThreadLocalEnvironment;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.util.List;/*** @author 余胜军* @ClassName GrayscaleGateway* @qq 644064779* @addres www.mayikt.com* 微信:yushengjun644*/
@Component
@RefreshScope
public class GrayscaleGlobalFilter implements GlobalFilter, Ordered {@Value("${mayikt.gateway.grayscaleUserConfig}")private String[] grayscaleUserConfig;@Value("${mayikt.gateway.grayscale.version}")private String grayscaleVersion;@Value("${mayikt.gateway.formal.version}")private String formalVersion;@Overridepublic Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 1.获取到ServerHttpRequestServerHttpRequest request = exchange.getRequest();ServerHttpResponse response = exchange.getResponse();// 2.判断是否是灰度用户 根据参数判断List mayiktParameGrayscales = request.getHeaders().get("mayiktParameGrayscale");if (mayiktParameGrayscales != null && mayiktParameGrayscales.size() > 0) {// 3.如果是灰度用户grayscale(mayiktParameGrayscales);} else {// 设置当前环境为正式环境GrayscaleThreadLocalEnvironment.setCurrentEnvironment(formalVersion);}return chain.filter(exchange.mutate().request(request).build());}/*** 灰度流程*/private void grayscale(List mayiktParameGrayscales) {String mayiktParameGrayscale = mayiktParameGrayscales.get(0);if (StringUtils.isEmpty(mayiktParameGrayscale)) {return;}for (String userConfig :grayscaleUserConfig) {if (userConfig.equals(mayiktParameGrayscale)) {// 设置当前用户灰度的环境GrayscaleThreadLocalEnvironment.setCurrentEnvironment(grayscaleVersion);return;}}// 设置当前环境为正式环境GrayscaleThreadLocalEnvironment.setCurrentEnvironment(formalVersion);}public int getOrder() {return -1;}
}
/*** @author 余胜军* @ClassName Grayscale* @qq 644064779* @addres www.mayikt.com* 微信:yushengjun644*/
public class GrayscaleThreadLocalEnvironment {private static ThreadLocal threadLocal = new ThreadLocal();/*** 设置当前线程对应的版本** @param currentEnvironmentVsersion*/public static void setCurrentEnvironment(String currentEnvironmentVsersion) {threadLocal.set(currentEnvironmentVsersion);}/*** 获取当前环境配置** @return*/public static String getCurrentEnvironment() {return threadLocal.get();}
}

重写本地负载均衡器算法

package com.mayikt.gateway.config;import com.mayikt.gateway.manage.GrayscaleThreadLocalEnvironment;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.RoundRobinRule;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.alibaba.nacos.ribbon.NacosServer;
import org.springframework.stereotype.Component;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;/*** @author 余胜军* @ClassName MayiktRoundRobinRule* @qq 644064779* @addres www.mayikt.com* 微信:yushengjun644*/
@Component
@Slf4j
public class MayiktRoundRobinRule extends RoundRobinRule {private AtomicInteger nextServerCyclicCounter;private static final boolean AVAILABLE_ONLY_SERVERS = true;private static final boolean ALL_SERVERS = false;public MayiktRoundRobinRule() {nextServerCyclicCounter = new AtomicInteger(0);}public Server choose(ILoadBalancer lb, Object key) {if (lb == null) {log.warn("no load balancer");return null;}Server server = null;int count = 0;while (server == null && count++ < 10) {List reachableServers = lb.getReachableServers();List allServers = lb.getAllServers();int upCount = reachableServers.size();int serverCount = allServers.size();if ((upCount == 0) || (serverCount == 0)) {log.warn("No up servers available from load balancer: " + lb);return null;}List filterServers = new ArrayList<>();String currentEnvironmentVersion = GrayscaleThreadLocalEnvironment.getCurrentEnvironment();for (Server serverInfo :allServers) {NacosServer nacosServer = (NacosServer) serverInfo;String version = nacosServer.getMetadata().get("version");if (version.equals(currentEnvironmentVersion)) {filterServers.add(nacosServer);}}int filterServerCount = filterServers.size();int nextServerIndex = incrementAndGetModulo(filterServerCount);server = filterServers.get(nextServerIndex);if (server == null) {/* Transient. */Thread.yield();continue;}if (server.isAlive() && (server.isReadyToServe())) {return (server);}// Next.server = null;}if (count >= 10) {log.warn("No available alive servers after 10 tries from load balancer: "+ lb);}return server;}private int incrementAndGetModulo(int modulo) {for (; ; ) {int current = nextServerCyclicCounter.get();int next = (current + 1) % modulo;if (nextServerCyclicCounter.compareAndSet(current, next))return next;}}
}

演示效果

http://127.0.0.1:81/mayikt-member/member 请求设定参数 mayiktParameGrayscale=mayikt

测走灰度用户。

正常流程:

1.先走过滤器---- 判断该用户是否 是为灰度用户

是如果为灰度用户的话 设定当前线程版本号码=2.0

----- 最优先加载的

2.本地路由负载均衡算法— 获取当前线程

对应的版本号码=2.0 在从nacos上获取2.0 版本接口地址 本地实现

负载均衡。

相关内容

热门资讯

离开旧爱,想坐慢车,看透彻了心... 离开旧爱,想坐慢车,看透彻了心就会是晴朗的 是哪首歌?分手快乐,梁静茹的一首老歌分手快乐 梁静茹 我...
火影忍者决斗场什么忍者能卡进墙... 火影忍者决斗场什么忍者能卡进墙里波风水门。1、利用瞬身术进竖核入墙内:首先选信尘择一个合适的墙壁,然...
只有再爱一次,才能忘记前男友吗... 只有再爱一次,才能忘记前男友吗?你可以多和你的好朋友谈心啊,多结交一些朋友一样可以让你淡忘他,不一定...
女的穿越时空回到古代朝鲜的言情... 女的穿越时空回到古代朝鲜的言情小说古灵的《替身》
求一部动漫,很久以前看的,忘记... 求一部动漫,很久以前看的,忘记了名字。是关于一个少女变身用扑克牌行窃的故事。圣少女(提醒:变身后穿黑...
好听的歌 劲爆的 伤感的 忧伤... 好听的歌 劲爆的 伤感的 忧伤的 都行求要听的 欢快 忧伤的都行 只要好听 分享下呗Gee-少...
汤圆创作里面容易签约嘛?难度怎... 汤圆创作里面容易签约嘛?难度怎么样?是特别好看的文文才会成功嘛?什么地方,没听说过。
异界小说 男主被冰封了 然后有... 异界小说 男主被冰封了 然后有一帮来拍电影的女的在洗澡的时候发现了他! 好像是这样的就记得这些还有点...
选择词语填在横线上(快来帮帮我... 选择词语填在横线上(快来帮帮我吧)调整 整顿 矗立 伫立1、调整 整顿2、耸立 伫立调整 整顿矗立...
朴灿烈香水百瑞德,灿烈用的是百... 朴灿烈香水百瑞德,灿烈用的是百瑞德哪种香味的香水?朴灿烈喜欢用的百瑞德香水是银色山泉这款,这款香水是...
精神分析的学习与自我成长的联系... 精神分析的学习与自我成长的联系?心理学专业人士来答卡伦 霍尼《神经症与人的成长》,如果你是专业的,你...
怎么就没一首我喜欢听的歌 怎么就没一首我喜欢听的歌你最喜欢听的歌,听久了也会腻。心情不要那么浮躁,就会找到你喜欢的那首歌
如果把地球直线挖通的话,人跳进... 如果把地球直线挖通的话,人跳进去会摔死还是会掉到另一端呢?应该会直接摔死,因为地球中心才是非常复杂的...
和男朋友分手,他居然说谢谢我给... 和男朋友分手,他居然说谢谢我给他上了一堂人生课,什么意思?虽然你们分手了,但是你们一起度过了一段人生...
带口哨的纯音乐 带口哨的纯音乐曲名:The Voyage艺人:The Mountaineering Club Orc...
禾葡兰的禾善基金的理念是什么? 禾葡兰的禾善基金的理念是什么?禾善基金是有什么理念呢?禾善基金是禾葡兰创办的互助基金会,基金会的救助...
名侦探柯南给工藤新一的挑战书每... 名侦探柯南给工藤新一的挑战书每集开头那段音乐,有完整的吗,不是剧场和动画那个!那首歌是仓木麻衣的《T...
路漫漫其修远兮的下一句 路漫漫其修远兮的下一句路漫漫其修远兮,吾将上下而求索”这句出自屈原的名作《离骚》。“路漫漫其修远兮,...
海伦凯勒的背景 海伦凯勒的背景 海伦·凯勒(Helen Keller)(1880年6月27日-1968年6月1日...
激情燃烧的岁月实际上就是中国人... 激情燃烧的岁月实际上就是中国人焕发出巨大的劳动热情2.咱们工人有力量的歌曲,焕发的是现代人的激情。以...