SpringCloud全链路灰度发布

日升时奋斗,日落时自省 

目录

1、实现框架

2、负载均衡模块

3、封装负载均衡器

4、网关模块

5、服务模块

5.1、注册为灰度服务实例

5.2、设置负载均衡器

5.3、传递灰度标签


1、实现框架

Spring Cloud全链路灰色发布实现构架:

灰度发布的具体实现 :

前端程序在灰度测试用户Header头中打上标签,例如Header中添加一个参数"gray-tay:true",其表示要进行会灰度测试的(访问灰度服务),而其他则为正式服务

在负载均衡器Spring Cloud LoadBalancer中,拿到Header中的"gray-tag"进行判断,如果此标签不为空,并等于"true"的话,表示要访问灰度发布的服务,否则只访问正式的服务

在网关Spring Cloud Gateway中,Header标签"gray-tag:true"继续往下一服务中传传递(因为通过网关的时候,是从新发送请求,Header中是没有灰度标签的)

在后续的调用服务中,需要实现以下两个关键功能:

  • 在负载均衡器Spring Cloud LoadBalancer中,判断灰度发布标签,将请求分发到对应服务
  • 将灰度发布标签(如果存在),继续传递给下一个调用的服务

经过第四步的反复传递之后,整个Spring Cloud全链路的灰度发布就完成了

2、负载均衡模块

实现ReactorServiceInstanceLoadBalancer接口

public class GrayLoadBalancer implements ReactorServiceInstanceLoadBalancer{private static final Log log = LogFactory.getLog(GrayLoadBalancer.class);private final String serviceId;private AtomicInteger position; // 位置,下标private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;public GrayLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId) {this.serviceId = serviceId;this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;this.position = new AtomicInteger(new Random().nextInt(1000));  //随机进行设置一个值}public Mono<Response<ServiceInstance>> choose(Request request) {// 提供备选的服务实例列表ServiceInstanceListSupplier supplier = (ServiceInstanceListSupplier) this.serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);// 选择服务实例return supplier.get(request).next().map((serviceInstances) -> {return this.processInstanceResponse(supplier, serviceInstances, request);});}private Response<ServiceInstance> processInstanceResponse(ServiceInstanceListSupplier supplier,List<ServiceInstance> serviceInstances,Request request) {// 从备选的服务列表中选择一个具体的服务实例Response<ServiceInstance> serviceInstanceResponse = this.getInstanceResponse(serviceInstances,request);if (supplier instanceof SelectedInstanceCallback && serviceInstanceResponse.hasServer()) {((SelectedInstanceCallback) supplier).selectedServiceInstance((ServiceInstance) serviceInstanceResponse.getServer());}return serviceInstanceResponse;}private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances,Request request) {// 实例为空   首先进行实例判空if (instances.isEmpty()) {if (log.isWarnEnabled()) {//判空后 给予警告log.warn("No servers available for service: " + this.serviceId);}//返回响应return new EmptyResponse();} else { // 服务不为空// 灰度节点的业务实现// 0.得到 Request 对象[通过方法参数的传递得到此对象]// 1.从 Request 对象的 Header 中得到灰度标签RequestDataContext requestContext = (RequestDataContext) request.getContext();HttpHeaders headers = requestContext.getClientRequest().getHeaders();List<String> headersList = headers.get(GlobalVariable.GRAY_TAGE);if (headersList != null && headersList.size() > 0 &&headersList.get(0).equals("true")) { // 灰度请求// 灰度列表  这里采用lambda的方法进行过滤List<ServiceInstance> grayList = instances.stream().filter(i -> i.getMetadata().get(GlobalVariable.GRAY_TAGE) != null &&i.getMetadata().get(GlobalVariable.GRAY_TAGE).equals("true")).toList();if (grayList.size() > 0) { // 存在灰度服务节点instances = grayList;}} else { // 正式节点// 2.将实例进行分组【正式服务列表|灰度服务列表】instances = instances.stream().filter(i -> i.getMetadata().get(GlobalVariable.GRAY_TAGE) == null ||!i.getMetadata().get(GlobalVariable.GRAY_TAGE).equals("true")).toList();}// 3.使用负载均衡算法选择上一步列表中的某一个节点int pos = this.position.incrementAndGet() & Integer.MAX_VALUE;ServiceInstance instance = (ServiceInstance)instances.get(pos % instances.size());return new DefaultResponse(instance);}}
}

3、封装负载均衡器

负载均衡器修改之后,我们需要使用修改后的负载均衡器

public class GrayLoadBalancerConfig {@Beanpublic ReactorLoadBalancer<ServiceInstance> GrayLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) {String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);return new GrayLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);}
}

4、网关模块

网关是能收到灰度发布标识,但是调用的服务是不能获得Header中的灰度标签,需要在网关这里传递给调用的服务

@Component // 实现全局过滤器 进行过滤设置
public class LoadBalancerFilter implements GlobalFilter {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 事件处理 exchange 获取请求头ServerHttpRequest request=exchange.getRequest();// 事件处理 exchange 获取响应头ServerHttpResponse response = exchange.getResponse();// 请求头参数 获取的参数 获取 key 对应的 value值if(request.getQueryParams().getFirst(GlobalVariable.GRAY_TAGE)!=null){//获取响应请求头 设置灰度标签的参数 为 trueresponse.getHeaders().set(GlobalVariable.GRAY_TAGE,"true");}// 返回 一个调用链 过滤条件的return chain.filter(exchange);}
}

5、服务模块

5.1、注册为灰度服务实例

在负载均衡器上获得了metaData数据,这个数据就是从灰色服务实例中获取,数据存储在nacos中

spring:application:name: user-service-graycloud:nacos:discovery:server-addr: localhost:8848username: nacospassword: nacosmetadata: {"gray-tag":"true"}  #metadata可以自定义一些元数据
server:port: 0

5.2、设置负载均衡器

在服务启动类设置负载均衡器和开启OpenFeign服务:

defaultConfiguration = GrayLoadBalancerConfig.class全局负载均衡器的配置

@SpringBootApplication
@EnableFeignClients  //启用Fegin客户端使用
//这里需要调用我们写的负载均衡器,我们自定义的负载均衡器主要就是为了检测gray参数
@LoadBalancerClients(defaultConfiguration = GrayLoadBalancerConfig.class)  
public class NewUserServiceApplication {public static void main(String[] args) {SpringApplication.run(NewUserServiceApplication.class, args);}}

5.3、传递灰度标签

针对其他服务实例需要处理请求头信息

RequestInterceptor是一个Spring Cloud Feign中的接口,它用于在发起Feign请求前和请求后执行一些自定义的操作,例如添加请求头信息、记录请求日志、实现认证授权等

RequestInterceptor接口中包含一个方法:

apply方法:在发送请求之前执行的操作,比如添加请求头、修改请求路径或请求参数等

@Component
public class FeignRequestInterceptor implements RequestInterceptor {//相当于是一个前置操作 处理请求头信息,记录请求日志、实现认证授权@Overridepublic void apply(RequestTemplate requestTemplate) {//获取请求参数ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();//拿到请求  HttpServletRequest request = attributes.getRequest();//获取请求头参数  当然调用上面这条代码的 request是一样的Enumeration<String> headerNames = attributes.getRequest().getHeaderNames();//将获取的请求中的所有参数while(headerNames.hasMoreElements()){//将key先获取String key=headerNames.nextElement();//通过key 获得 valueString value=request.getHeader(key);//将获取的参数 放到header头中采用键值 key:value 放到请求模板中requestTemplate.header(key,value);}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/620703.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

利用Monte Carlo进行数值积分(二)

进步空间很大的算法版本 话说去年6月的一个周六&#xff0c;我很无聊地发了一个帖子&#xff0c;写了一个自己感觉有点无聊的帖子。 Matlab多重积分的两种实现【从六重积分到一百重积分】https://withstand.blog.csdn.net/article/details/127564478 这个帖子居然成了我这种懒…

求解建公路问题

课程设计题目 求解建公路问题 课程设计目的 深入掌握 Prim 和 Kruskal算法在求解实际问题中的应用 问题描述 假设有 n 个村庄,编号从到,现在修建一些道路使任意两个村庄之间可以互相连通。所谓两个村庄 A 和B是连通的,指当且仅当A 和 B之间有一条道路或者存在一个村庄 C 使得…

QT通过QPdfWriter类实现pdf文件生成与输出

一.QPdfWriter类介绍 本文代码工程下载地址&#xff1a; https://download.csdn.net/download/xieliru/88736664?spm1001.2014.3001.5503 QPdfWrite是一个用于创建PDF文件的类&#xff0c;它是Qt库的一部分。它提供了一些方法和功能&#xff0c;使您能够创建和写入PDF文件。…

#Prompt##提示词工程##AIGC##LLM#使用大型预训练语言模型的关键考量

如果有不清楚的地方可以评论区留言&#xff0c;我会给大家补上的&#xff01; 本文包括&#xff1a; Prompt 的一些行业术语介绍 Prompt 写好提示词的方法经验介绍&#xff08;附示例教程&#xff09; LLM自身存在的问题&#xff08;可以用Prompt解决的以及无法用Prompt解决的&…

u盘监控系统—公司电脑如何监控U盘使用?【详解】

在当今的办公环境中&#xff0c;U盘等移动存储设备已成为数据传输和存储的重要工具。 然而&#xff0c;随着U盘的广泛使用&#xff0c;也带来了潜在的安全风险&#xff0c;如数据泄露、病毒传播等。 因此&#xff0c;对于随时会有数据泄露风险的企业而言&#xff0c;U盘的使用…

DrissionPage获取浏览器Network数据包

DrissionPage是什么&#xff1f; GitHub - g1879/DrissionPage: 基于python的网页自动化工具。既能控制浏览器&#xff0c;也能收发数据包。可兼顾浏览器自动化的便利性和requests的高效率。功能强大&#xff0c;内置无数人性化设计和便捷功能。语法简洁而优雅&#xff0c;代码…

深度学习基本介绍-李沐

目录 AI分类&#xff1a;模型分类&#xff1a;广告案例&#xff1a; bilibili视频链接&#xff1a;https://www.bilibili.com/video/BV1J54y187f9/?p2&spm_id_frompageDriver&vd_sourcee6a6e7fec41c59c846c142eb5ef1da0b AI分类&#xff1a; 模型分类&#xff1a; 图…

【每日一题】删除排序链表中的重复元素

文章目录 Tag题目来源解题思路方法一&#xff1a;比较相邻两节点 写在最后 Tag 【遍历】【链表】【2024-01-14】 题目来源 83. 删除排序链表中的重复元素 解题思路 方法一&#xff1a;比较相邻两节点 思路 比较两个相邻的节点&#xff0c;如果下一个节点值和当前节点值一样…

简单高效 LaTeX 科学排版 第004集 命令与环境

这是《简单高效LaTeX》的第四个视频&#xff0c;主要演示讨论基本命令与排版环境&#xff0c;还有保留字符。 视频地址&#xff1a;https://www.ixigua.com/7298100920137548288?id7298102807985390120&logTagf853f23a668f8a2ee405

IPv6组播技术--MLDv2

MPLDv1工作机制 IPv6组播网络中RouterA和RouterB连接主机网段,在主机网段上有HostA、HostB、HostC三个接收者。假设HostA和HostB想要接收发往组播组G1的数据,HostC想要接收发往组播组G2的数据。 查询器选举机制 当一个网段内有多台IPv6组播路由器时,由于它们都可以接收到…

初识XSS漏洞

目录 一、XSS的原理和分类 二、Xss漏洞分类 1. 反射性xss 简单的演示&#xff1a; 2.基于DOM的XSS 简单的演示&#xff1a; 3.存储型XSS ​编辑简单的演示 4、self xss 三、XSS漏洞的危害 四、XSS漏洞的验证 五、XSS漏洞的黑盒测试 六、XSS漏洞的白盒测试 七、XS…

html+JavaScript的媒体元素

<video src"conference.mpg" id"myVideo">Video player not available.</video> <!-- 嵌入音频 --> <audio src"song.mp3" id"myAudio">Audio player not available.</audio> - 属性 每个元素至少…

JavaScript深拷贝与浅拷贝的全面解析

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;《爱蹦跶的大A阿》 &#x1f525;当前正在更新专栏&#xff1a;《VUE》 、《JavaScript保姆级教程》、《krpano》 ​ ​ 目录 ✨ 前言 ✨ 正文 浅拷贝 对象的浅拷贝 数组的浅拷贝 浅拷贝的问题 深拷贝 什么是深拷贝…

如何激活数据要素价值

文章目录 前言一、数据作为生产要素的背景二、数据作为新型生产要素&#xff0c;是价值创造的重要源泉&#xff08;一&#xff09;生产要素是经济活动中的基本要素&#xff08;二&#xff09;激活数据要素价值&#xff0c;要从理论上认识数据要素的基本特征&#xff08;三&…

CMU15-445-Spring-2023-Project #2 - B+Tree

前置知识&#xff1a;参考上一篇博文 CMU15-445-Spring-2023-Project #2 - 前置知识&#xff08;lec07-010&#xff09; CHECKPOINT #1 Task #1 - BTree Pages 实现三个page class来存储B树的数据。 BTree Page internal page和leaf page继承的基类&#xff0c;只包含两个…

C语言辨析——深入理解字符常量与表达式

1. 问题 今天看到一个题目&#xff0c;截图如下。 从答题情况来看&#xff0c;本题的答案是B&#xff0c;那么就意味着A、C、D是错的。但我认为这4个选项都是对的。当然&#xff0c;如果要从4个选项中挑选一个的话&#xff0c;那还是选择B妥当一些。 2. 分析 字符常量的定义…

【漏洞复现】优卡特脸爱云一脸通智慧管理平台权限绕过漏洞CVE-2023-6099(1day)

漏洞描述 脸爱云一脸通智慧管理平台1.0.55.0.0.1及其以下版本SystemMng.ashx接口处存在权限绕过漏洞,通过输入00操纵参数operatorRole,导致特权管理不当,未经身份认证的攻击者可以通过此漏洞创建超级管理员账户。 免责声明 技术文章仅供参考,任何个人和组织使用网络应当…

CAN总线报文格式———扩展数据帧

扩展数据帧由帧起始、仲裁段、控制段、数据段、CRC段、ACK段、帧结束等组成。 一、总线空闲&#xff08;Bus Idle&#xff09; CAN总线空闲时&#xff0c;总线上会输出持续的高电平“1”。当总线空闲时任何连接的单元都可以开始发送新的报文。 二、帧起始&#xff08;Start o…

鱼哥赠书活动第⑤期:《ATTCK视角下的红蓝对抗实战指南》《智能汽车网络安全权威指南》上下册 《构建新型网络形态下的网络空间安全体系》《Kali Linux高级渗透测试》

鱼哥赠书活动第⑤期&#xff1a; 《ATT&CK视角下的红蓝对抗实战指南》1.1介绍&#xff1a; 《智能汽车网络安全权威指南》上册1.1介绍&#xff1a; 《智能汽车网络安全权威指南》下册1.1介绍&#xff1a; 《构建新型网络形态下的网络空间安全体系》1.1介绍&#xff1a; 《K…

遭受慢速连接攻击怎么办?怎么预防

慢速连接攻击是一种常见的网络攻击方式&#xff0c;其原理是利用HTTP协议的特性&#xff0c;在建立了与Http服务器的连接后&#xff0c;尽量长时间保持该连接&#xff0c;不释放&#xff0c;达到对Http服务器的攻击。 慢速连接攻击的危害包括以下几个方面&#xff1a; 1.资源…