基于重写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负载实现灰度发布
项目结构如下 代码如下: 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:schemaLocat…...
无端科技一面(生死狙击项目组 战斗客户端 40min)
自我介绍 实习经历询问 项目询问 TCP和UDP的区别 什么情况会用到UDP 大小端 寻路算法了解多少 A*算法 场景题:扫雷如何随机分地雷,怎么安排数字显示 怎么判断一个物体在三角锥内 动作游戏中打击效果怎么处理穿模问题 八叉树了解过吗 骨骼动画…...

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

linux之文件系统、inode和动静态库制作和发布
一、背景 1.没有被打开的文件都在磁盘上 --- 磁盘级文件 2.对磁盘级别的文件,我们的侧重点 单个文件角度 -- 这个文件在哪里,有多大,其他属性是什么? 站在系统角度 -- 一共有多少文件?各自属性在哪里?…...
C++IO类,输入输出缓冲区,流状态
我们的程序已经使用了很多IO库设施: istream(输入流)类型,提供输入操作。ostream(输出流)类型,提供输出操作。cin,一个istream对象,从标准输入读取数据。写入到标准错误。cout,一个ostream对象,…...

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

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

Jetson nano部署Yolov8 安装Archiconda3+创建pytorch环境(详细教程+错误解决)
由于jetson nano 是aarch64架构,Anaconda官方不支持aarch64架构,所以有了一个叫“Archiconda”,其目的就是将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库,它可以限制同时进行的请求数量,以避免过多的请求导致服务器压力过大。使用Promise-Pool可以方便地实现对多个异步操作的并…...

【C++】红黑树讲解及实现
前言: AVL树与红黑树相似,都是一种平衡二叉搜索树,但是AVL树的平衡要求太严格,如果要对AVL树做一些结构修改的操作性能会非常低下,比如:插入时要维护其绝对平衡,旋转的次数比较多,更…...
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的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili Inventory.cs using Newtonsoft.Json.Linq; using System.Collections; us…...

【智能排班系统】雪花算法生成分布式ID
文章目录 雪花算法介绍起源与命名基本原理与结构优势与特点应用场景 代码实现代码结构自定义机器标识RandomWorkIdChooseLocalRedisWorkIdChooselua脚本 实体类SnowflakeIdInfoWorkCenterInfo 雪花算法类配置类雪花算法工具类 说明 雪花算法介绍 在复杂而庞大的分布式系统中&a…...
sass中的导入与部分导入
文章目录 sass中的导入与部分导入1. import:传统的导入方式2. use:现代化的模块化导入 sass中的导入与部分导入 在大型前端项目中,CSS代码量往往十分庞大,为了保持其可读性、可维护性以及便于团队协作,模块化开发成为…...

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

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

基于单片机电子密码锁系统设计
**单片机设计介绍,基于单片机电子密码锁系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机电子密码锁系统设计概要主要包括以下几个方面: 一、系统概述 基于单片机电子密码锁系统是一个…...
点云从入门到精通技术详解100篇-基于点云与图像纹理的 道路识别(续)
目录 3.1.2 图像滤波去噪 3.2 道路纹理特征提取 3.3 基于超像素分割的图像特征表达...
《机器学习在量化投资中的应用研究》目录
机器学习在量化投资中的应用研究 获取链接:机器学习在量化投资中的应用研究_汤凌冰著_北京:电子工业出版社 更多技术书籍:技术书籍分享,前端、后端、大数据、AI、人工智能... 内容简介 《机器学习在量化投资中的应用研究…...

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

C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...

android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文通过代码驱动的方式,系统讲解PyTorch核心概念和实战技巧,涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...
uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)
UniApp 集成腾讯云 IM 富媒体消息全攻略(地理位置/文件) 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型,核心实现方式: 标准消息类型:直接使用 SDK 内置类型(文件、图片等)自…...

第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10pip3.10) 一:前言二:安装编译依赖二:安装Python3.10三:安装PIP3.10四:安装Paddlepaddle基础框架4.1…...