当前位置: 首页 > news >正文

基于重写ribbon负载实现灰度发布

项目结构如下

代码如下:

pom:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>sca.pro</groupId><artifactId>sca-parent</artifactId><version>1.0.1</version></parent><groupId>sca.gary.publish</groupId><artifactId>gray-spring-boot-starter</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!-- Compile dependencies --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><dependency><groupId>com.netflix.ribbon</groupId><artifactId>ribbon-loadbalancer</artifactId><scope>provided</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>transmittable-thread-local</artifactId><version>2.14.2</version></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>io.github.openfeign</groupId><artifactId>feign-core</artifactId><scope>provided</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><scope>provided</scope></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target><encoding>${project.build.sourceEncoding}</encoding></configuration></plugin></plugins></build></project>

spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
sca.gary.publish.graypublish.config.GrayConfig,\
sca.gary.publish.graypublish.feignInterceptor.FeignRequestInterceptor

 GrayConfig:可以在对应服务启动类添加如下,可写多个服务

@RibbonClients(value = {@RibbonClient(value = "nacos中的服务名称",configuration = GrayConfig.class)
})
package sca.gary.publish.graypublish.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import sca.gary.publish.graypublish.GrayRule;//@Configuration
之前理解有误,这里千万不能加它,否则服务调用会混乱
public class GrayConfig {@Beanpublic GrayRule grayRule(){return new GrayRule();}
}
ContantsString:版本号请求头key
package sca.gary.publish.graypublish.contans;public class ContantsString {public static final String GRAY_KEY="version";}
FeignRequestInterceptor:feign拦截器,当远程调用时,将版本号保存到ttl中,供给服务负载使用,并把当前请求头中的版本号放在远程调用的请求头中,防止它仍需要远程调用
package sca.gary.publish.graypublish.feignInterceptor;import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import sca.gary.publish.graypublish.contans.ContantsString;
import sca.gary.publish.graypublish.ttl.ThreadLocalUtils;import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;@Component
public class FeignRequestInterceptor  implements RequestInterceptor {@Overridepublic void apply(RequestTemplate template) {ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = sra.getRequest();Map<String, String> headers = getHeaders(request);for (Map.Entry<String, String> entry : headers.entrySet()) {//② 设置请求头到新的Request中template.header(entry.getKey(), entry.getValue());}}/*** 获取原请求头*/private Map<String, String> getHeaders(HttpServletRequest request) {Map<String, String> map = new LinkedHashMap<>();Enumeration<String> enumeration = request.getHeaderNames();if (enumeration != null) {while (enumeration.hasMoreElements()) {String key = enumeration.nextElement();String value = request.getHeader(key);//将灰度标记的请求头透传给下个服务if (ContantsString.GRAY_KEY.equals(key)){//① 保存灰度发布的标记ThreadLocalUtils.set(ContantsString.GRAY_KEY,value);map.put(key, value);}}}return map;}
}
ThreadLocalUtils:用于存储网关传递过来的版本号,实现当前服务的负载选择
package sca.gary.publish.graypublish.ttl;import com.alibaba.ttl.TransmittableThreadLocal;
import java.util.HashMap;
import java.util.Map;public class ThreadLocalUtils {private static TransmittableThreadLocal<Map<String, Object>> cache = new TransmittableThreadLocal<>();/*** 设置对象到本地变量** @param object*/public static void set(String key, Object object) {if (!isCaheIsNull()) {cache.get().put(key, object);} else {Map<String, Object> map = new HashMap<>();map.put(key, object);cache.set(map);}}/*** 从本地变量中获取变量** @return*/public static Object get(String key) {if (!isCaheIsNull()) {return cache.get().get(key);} else {return null;}}/*** 根据KEY移除缓存里的数据** @param key*/public static void remove(String key) {if (isCaheIsNull()) {return;} else {cache.get().remove(key);}}/*** 释放本地线程资源*/public static void clear() {cache.remove();}/*** 是否存在本地变量** @return*/private static boolean isCaheIsNull() {return cache.get() == null;}}
GrayRule:

最重要的就是这个类,重写了ribbon的负载策略,通过从网关传递过来的版本号,和每个服务中的元数据版本号进行对比,如果相同则调用它们的版本,如果没有找到对应版本的服务,则将获取到的所有服务按照原规则进行负载

package sca.gary.publish.graypublish;import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.google.common.base.Optional;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ZoneAvoidanceRule;
import org.springframework.util.ObjectUtils;
import sca.gary.publish.graypublish.contans.ContantsString;
import sca.gary.publish.graypublish.ttl.ThreadLocalUtils;import java.util.ArrayList;
import java.util.List;public class GrayRule extends ZoneAvoidanceRule {@Overridepublic void initWithNiwsConfig(IClientConfig clientConfig) {}@Overridepublic Server choose(Object key) {try {//从ThreadLocal中获取灰度标记Object version = ThreadLocalUtils.get(ContantsString.GRAY_KEY);//获取所有可用服务List<Server> serverList = this.getLoadBalancer().getReachableServers();//灰度发布的服务List<Server> grayServerList = new ArrayList<>();if (ObjectUtils.isEmpty(version)){return originChoose(serverList,key);}for(Server server : serverList) {NacosServer nacosServer = (NacosServer) server;//从nacos中获取元素剧进行匹配if(nacosServer.getMetadata().containsKey(ContantsString.GRAY_KEY)&& nacosServer.getMetadata().get(ContantsString.GRAY_KEY).equals(version.toString()) ){grayServerList.add(server);}}if (!ObjectUtils.isEmpty(grayServerList)){return originChoose(grayServerList,key);}return originChoose(serverList,key);} finally {//清除灰度标记ThreadLocalUtils.clear();}}private Server originChoose(List<Server> noMetaServerList, Object key) {Optional<Server> serverOptional = getPredicate().chooseRoundRobinAfterFiltering(noMetaServerList, key);if (serverOptional.isPresent()) {return serverOptional.get();} else {return null;}}}

使用方式:

1.首先保证每个服务都有feign的依赖

2.添加依赖如下

<dependency><groupId>sca.gary.publish</groupId><artifactId>gray-spring-boot-starter</artifactId><version>1.0.1</version><exclusions><exclusion><groupId>io.github.openfeign</groupId><artifactId>feign-core</artifactId></exclusion></exclusions>
</dependency>

3.yaml添加配置

spring:

  cloud:

    nacos:

      discovery:

         metadata:

            version: 2.0

3.在启动类上添加下边的,需要远程调用哪个服务,就加哪几个

@RibbonClients(value = {@RibbonClient(value = "服务名",configuration = GrayConfig.class)
})

相关文章:

基于重写ribbon负载实现灰度发布

项目结构如下 代码如下&#xff1a; pom&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocat…...

无端科技一面(生死狙击项目组 战斗客户端 40min)

自我介绍 实习经历询问 项目询问 TCP和UDP的区别 什么情况会用到UDP 大小端 寻路算法了解多少 A*算法 场景题&#xff1a;扫雷如何随机分地雷&#xff0c;怎么安排数字显示 怎么判断一个物体在三角锥内 动作游戏中打击效果怎么处理穿模问题 八叉树了解过吗 骨骼动画…...

idea开发 java web 高校学籍管理系统bootstrap框架web结构java编程计算机网页

一、源码特点 java 高校学籍管理系统是一套完善的完整信息系统&#xff0c;结合java web开发和bootstrap UI框架完成本系统 &#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 前段主要技术 css jq…...

linux之文件系统、inode和动静态库制作和发布

一、背景 1.没有被打开的文件都在磁盘上 --- 磁盘级文件 2.对磁盘级别的文件&#xff0c;我们的侧重点 单个文件角度 -- 这个文件在哪里&#xff0c;有多大&#xff0c;其他属性是什么&#xff1f; 站在系统角度 -- 一共有多少文件&#xff1f;各自属性在哪里&#xff1f…...

C++IO类,输入输出缓冲区,流状态

我们的程序已经使用了很多IO库设施&#xff1a; istream(输入流)类型&#xff0c;提供输入操作。ostream(输出流)类型&#xff0c;提供输出操作。cin&#xff0c;一个istream对象&#xff0c;从标准输入读取数据。写入到标准错误。cout&#xff0c;一个ostream对象&#xff0c…...

机器学习笔记 - 文字转语音技术路线简述以及相关工具不完全清单

一、TTS技术简述 今天的文本到语音转换技术(TTS)的目标已经不仅仅是让机器说话,而是让它们听起来像不同年龄和性别的人类。通常,TTS 系统合成器的质量是从不同方面进行评估的,包括合成语音的清晰度、自然度和偏好,以及人类感知因素,例如可理解性。 1、技术路线 (1)基…...

阿里云4核8G服务器ECS通用算力型u1实例优惠价格

阿里云4核8G服务器优惠价格955元一年&#xff0c;配置为ECS通用算力型u1实例&#xff08;ecs.u1-c1m2.xlarge&#xff09;4核8G配置、1M到3M带宽可选、ESSD Entry系统盘20G到40G可选&#xff0c;CPU采用Intel(R) Xeon(R) Platinum处理器&#xff0c;阿里云活动链接 aliyunfuwuq…...

Jetson nano部署Yolov8 安装Archiconda3+创建pytorch环境(详细教程+错误解决)

由于jetson nano 是aarch64架构&#xff0c;Anaconda官方不支持aarch64架构&#xff0c;所以有了一个叫“Archiconda”&#xff0c;其目的就是将conda移植到aarch64平台上 一. 下载地址Releases Archiconda/build-tools GitHub 然后安装archiconda bash Archiconda3-0.2.3…...

Node.JS多线程PromisePool之promise-pool库实现

什么是Promise Pool Map-like, concurrent promise processing for Node.js. Promise-Pool是一个用于管理并发请求的JavaScript库&#xff0c;它可以限制同时进行的请求数量&#xff0c;以避免过多的请求导致服务器压力过大。使用Promise-Pool可以方便地实现对多个异步操作的并…...

【C++】红黑树讲解及实现

前言&#xff1a; AVL树与红黑树相似&#xff0c;都是一种平衡二叉搜索树&#xff0c;但是AVL树的平衡要求太严格&#xff0c;如果要对AVL树做一些结构修改的操作性能会非常低下&#xff0c;比如&#xff1a;插入时要维护其绝对平衡&#xff0c;旋转的次数比较多&#xff0c;更…...

security如何不拦截websocket

只要添加一个关键配置就行 //忽略websocket拦截Overridepublic void configure(WebSecurity webSecurity){webSecurity.ignoring().antMatchers("/**");} 全部代码我放着了 package com.oddfar.campus.framework.config;import com.oddfar.campus.framework.secur…...

Unity类银河恶魔城学习记录12-3 p125 Limit Inventory Slots源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili Inventory.cs using Newtonsoft.Json.Linq; using System.Collections; us…...

【智能排班系统】雪花算法生成分布式ID

文章目录 雪花算法介绍起源与命名基本原理与结构优势与特点应用场景 代码实现代码结构自定义机器标识RandomWorkIdChooseLocalRedisWorkIdChooselua脚本 实体类SnowflakeIdInfoWorkCenterInfo 雪花算法类配置类雪花算法工具类 说明 雪花算法介绍 在复杂而庞大的分布式系统中&a…...

sass中的导入与部分导入

文章目录 sass中的导入与部分导入1. import&#xff1a;传统的导入方式2. use&#xff1a;现代化的模块化导入 sass中的导入与部分导入 在大型前端项目中&#xff0c;CSS代码量往往十分庞大&#xff0c;为了保持其可读性、可维护性以及便于团队协作&#xff0c;模块化开发成为…...

工业组态 物联网组态 组态编辑器 web组态 组态插件 编辑器

体验地址&#xff1a;by组态[web组态插件] BY组态是一款非常优秀的纯前端的【web组态插件工具】&#xff0c;可无缝嵌入到vue项目&#xff0c;react项目等&#xff0c;由于是原生js开发&#xff0c;对于前端的集成没有框架的限制。同时由于BY组态只是一个插件&#xff0c;不能独…...

git可视化工具

Gitkraken GitKraken 是一款专门用于管理和协作Git仓库的图形化界面工具。它拥有友好直观的界面&#xff0c;使得Git的操作变得更加简单易用&#xff0c;尤其适合那些不熟悉Git命令行的开发者。GitKraken提供了丰富的功能&#xff0c;如代码审查、分支管理、仓库克隆、提交、推…...

基于单片机电子密码锁系统设计

**单片机设计介绍&#xff0c;基于单片机电子密码锁系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机电子密码锁系统设计概要主要包括以下几个方面&#xff1a; 一、系统概述 基于单片机电子密码锁系统是一个…...

点云从入门到精通技术详解100篇-基于点云与图像纹理的 道路识别(续)

目录 3.1.2 图像滤波去噪 3.2 道路纹理特征提取 3.3 基于超像素分割的图像特征表达...

《机器学习在量化投资中的应用研究》目录

机器学习在量化投资中的应用研究 获取链接&#xff1a;机器学习在量化投资中的应用研究_汤凌冰著_北京&#xff1a;电子工业出版社 更多技术书籍&#xff1a;技术书籍分享&#xff0c;前端、后端、大数据、AI、人工智能... 内容简介 《机器学习在量化投资中的应用研究…...

Spring拓展点之SmartLifecycle如何感知容器启动和关闭

Spring为我们提供了拓展点感知容器的启动与关闭&#xff0c;从而使我们可以在容器启动或者关闭之时进行定制的操作。Spring提供了Lifecycle上层接口&#xff0c;这个接口只有两个方法start和stop两个方法&#xff0c;但是这个接口并不是直接提供给开发者做拓展点&#xff0c;而…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

莫兰迪高级灰总结计划简约商务通用PPT模版

莫兰迪高级灰总结计划简约商务通用PPT模版&#xff0c;莫兰迪调色板清新简约工作汇报PPT模版&#xff0c;莫兰迪时尚风极简设计PPT模版&#xff0c;大学生毕业论文答辩PPT模版&#xff0c;莫兰迪配色总结计划简约商务通用PPT模版&#xff0c;莫兰迪商务汇报PPT模版&#xff0c;…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG

TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码&#xff1a;HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...

如何配置一个sql server使得其它用户可以通过excel odbc获取数据

要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据&#xff0c;你需要完成以下配置步骤&#xff1a; ✅ 一、在 SQL Server 端配置&#xff08;服务器设置&#xff09; 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到&#xff1a;SQL Server 网络配…...

高考志愿填报管理系统---开发介绍

高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发&#xff0c;采用现代化的Web技术&#xff0c;为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## &#x1f4cb; 系统概述 ### &#x1f3af; 系统定…...