SpringCloud组件Ribbon的IRule的问题排查

最近很久没有写文章啦,刚好遇到了一个问题,其实问题也挺简单,但是还是得对源码有一定了解才能够发现。

最近在实现一个根据请求流量的标签,将请求转发到对应的节点,其实和俗称的灰度请求有点相似,

实现思路如下:

  • 首先为特定节点打上标签
  • 通过截取请求中的header的标签key,然后存入上下文中
  • 在服务转发时(Feign),在负载均衡步骤前将节点的标签和请求标签相匹配,筛选出标签节点。
  • 将标签节点进行策略选择一个合适的节点然后转发。

场景定义

实现伪代码:

  1. 定义策略
public class MyRule extends AbstractLoadBalancerRule {@Overridepublic void initWithNiwsConfig(IClientConfig iClientConfig) {}@Overridepublic Server choose(Object o) {return this.choose(this.getLoadBalancer(),o);}public Server choose(ILoadBalancer lb, Object key) {// 标签匹配// 节点选择// 策略选举return server;}}
}
  1. 注入容器
@Configuration
public class MyRuleConfig {@Beanpublic IRule ribbonRule(){return new MyRule();}
}

好,一切准备就绪。

在应用当中很快就遇到了问题,在选择过程中,节点地址出现错乱。

明明请求的是A服务节点,结果转发的是B节点

通过调试发现ILoadBalancer对象有问题,比如A服务节点持有的节点列表竟然是B的节点列表。

ILoadBalancer: 每个服务都独立持有一个独属于该服务负载列表。比如A服务持有的就是A服务列表,B就是B的.但此时却出现了归属于A的ILoadBalancer中节点列表竟然都是B的。

原因梳理

最终排查发现就是注入的方式问题,为什么这么说呢?

由于服务节点在初始化的过程中,都是以服务名作为一个独立配置存在于容器中的:(如下图)
服务节点加载图

用户服务单独有一套负载均衡规则(IRule),同理order订单服务也是单独一套负载均衡规则,双方各自持有了各自的服务列表(ILoadBalancer)。

但是由于我们要改写IRule的实现,同时注入到容器中,让服务能够获取到我改写的实现,我们直接@Bean给加入了。

此时在初始化这个IRule的时候就会出现问题,因为IRule内部是持有ILoadBalancer的,但是ILoadBalancer针对每个服务都是不一样的。

我们看一下IRule是怎么被加载到用户服务上下文的:
com.netflix.loadbalancer.BaseLoadBalancer#setRule

public void setRule(IRule rule) {if (rule != null) { // 此时我们是从容器获取到的,默认是个单例this.rule = rule;} else {/* default rule */this.rule = new RoundRobinRule();}if (this.rule.getLoadBalancer() != this) { // 肯定满足// 将自身交给rulethis.rule.setLoadBalancer(this);}
}

别忘了,我们通过@Bean加入到容器中时,是单例的。问题也出在这!
就意味着,每次初始化的时候,在设置setLoadBalancer时,就是在单例的IRule基础上,从后往前覆盖,最终IRule持有的永远都是最后一个服务的服务列表。

大意图就是这个样子:
在这里插入图片描述

问题解决

那么我们如何解决这个问题呢?
我们知道了原因是由于单例导致的,那么我们就可以将自定义的策略改成多实例的注入。

@Configuration
public class MyRuleConfig {@Bean@Scope("prototype") // 将单例变为原型public IRule ribbonRule(){return new MyRule();}
}

此时每次获取都是一个新的对象,相互不在影响。同理你如果需要覆盖RibbonClientConfiguration配置类中的对象时,也需要避免使用单例模式去定义它!

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

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

相关文章

IDEA 2023.2.2图文安装教程及下载

IDE 系列的第二个年度更新现已发布,涵盖 IntelliJ IDEA、WebStorm、PyCharm、DataGrip、GoLand、DataSpell 以及 All Products Pack 订阅中包含的其他工具。该版本还包括多项用户体验增强功能,例如 Search Everywhere(随处搜索)中…

Spring Boot项目在Windows上的自启动策略与Windows自动登录配置

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…

淘宝天猫商品评论数据接口,淘宝天猫商品评论API接口,淘宝API

淘宝商品评论数据接口可以通过淘宝开放平台API获取。 通过构建合理的请求URL,可以向淘宝服务器发起HTTP请求,获取商品评论数据。接口返回的数据一般为JSON格式,包含了商品的各种评价信息。获取到商品评论数据后,可以对其进行处理…

【计算机网络笔记】计算机网络的结构

系列文章目录 什么是计算机网络? 什么是网络协议? 文章目录 系列文章目录网络边缘接入网络数字用户线路 (DSL)电缆网络典型家庭网络的接入机构(企业)接入网络 (Ethernet)无线接入网络 网络核心Internet结构最后 计算机网络的结构…

[安洵杯 2019]easy_web - RCE(关键字绕过)+md5强碰撞+逆向思维

[安洵杯 2019]easy_web 1 解题流程1.1 阶段一1.2 阶段二2 思考总结1 解题流程 1.1 阶段一 1、F12发现提示md5 is funny ~;还有img标签中,有伪协议和base64编码 2、url地址是index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=   这就有意思了,这里的img明显是编码后的…

React 组件传 children 的各种方案

自定义组件的时候往往需要传 children,由于写法比较多样,我就总结了一下。 方案列表 1. 类组件1.1 类组件,不使用解构1.2 类组件,使用解构 2. 函数组件2.1 函数组件,不使用解构2.2 函数组件,外部解构2.3 函…

GNOME 45 动态三层缓存补丁更新

导读GNOME 45 "Rīga" 上周已正式发布,此版本虽然有许多针对桌面环境的改进,但上游缺少的一个功能是 Canonical 主导的 Mutter 动态三层缓存。 动态三层缓存用于在需要时提升性能,并且已被证明有助于提高桌面渲染性能,…

基于Docker来部署Nacos的注册中心

基于Docker来部署Nacos的注册中心 准备MySQL数据库表nacos.sql,用来存储Nacos的数据。 最终表结构如下: 在本地nacos/custom.env文件中,有一个MYSQL_SERVICE_HOST也就是mysql地址,需要修改为你自己的虚拟机IP地址: …

Spring之IoC

Spring的设计理念和整体架构 一句话概括就是:Spring是一个轻量级的、非侵入式的控制反转(IOC)和面向切面(AOP)的框架。 设计理念: 松散耦合: Spring鼓励开发者编写松散耦合的代码,通过依赖注入和接口抽象等方式来减少组件之间的…

Maven Eclipse

Eclipse 提供了一个很好的插件 m2eclipse ,该插件能将 Maven 和 Eclipse 集成在一起。 在最新的 Eclipse 中自带了 Maven,我们打开,Windows->Preferences,如果会出现下面的画面: 下面列出 m2eclipse 的一些特点&a…

景联文科技:3D点云标注应用场景和专业平台

3D点云技术之所以得到广泛发展和应用,主要是因为它能够以一种直观、真实和全面的方式来表示和获取现实世界中的三维信息。 3D点云的优势: 真实感和立体感:3D点云数据能够呈现物体的真实感和立体感,使观察者能够更直观地理解物体的…

[SRT]1.协议简介

1.简介 ​ 安全可靠传输协议(Secure Reliable Transport)简称SRT,是一种基于UDT协议的开源互联网传输协议,Haivision和Wowza合作成立SRT联盟,管理和支持SRT协议开源应用的组织,这个组织致力于促进视频流解决方案的互通性&a…

淘宝天猫店铺所有商品数据接口,淘宝API接口

获取淘宝店铺所有商品数据接口的步骤如下: 获取授权:使用 OAuth 2.0 协议对应用进行授权,以便能够访问店铺的商品信息。获取店铺信息:使用淘宝 API 的 taobao.shop.get 接口,传入店铺的 user_id 参数,获取…

工矿企业电力运维云平台:提升效率与降低成本的关键

针对工矿企业用户,聚焦供配电领系统“安全监控、能耗管理、智能运维” 的三大需求,研发推出了“电易云”--智慧电力物联网,为工矿企业用户提供智慧电力数字化解决方案及数据服务,实现供配电系统的数字化、云端化、智能化、绿色化&…

el-select的el-option添加操作按钮插槽后实现勾选与按钮操作分离

这里我在el-option的选项文字后面添加了两个svg按钮(编辑和删除):如图 当我们点击el-option时无法区分是勾选el-option还是点击了el-option选项文字后面的按钮,其实只要在后面的编辑和删除的操作按钮的click事件上面添加.native.…

多列等高实现

预期效果 多列等高,左右两列高度自适应且一样,分别设置不同背景色效果预览: 分别由6种方法实现 1、使用padding + margin + overflow 实现多列等高效果,具有良好的兼容性; 2、border实现多列等高,左边框宽度为200px,左列浮动,伪元素清除浮动; 3、父元素线性渐变背景色…

Redis - php通过ssh方式连接到redis服务器

1.应用场景 主要用于使用php通过ssh方式连接到redis服务器,进行一些操作. 2.学习/操作 1.文档阅读 chatgpt & 其他资料 SSH - 学习与实践探究_ssh应用场景 2.整理输出 2.1 是什么 TBD 2.2 为什么需要「应用场景」 TBD 2.3 什么时候出现「历史发展」 TBD 2.4 …

排序算法-快速排序法(QuickSort)

排序算法-快速排序法(QuickSort) 1、说明 快速排序法是由C.A.R.Hoare提出来的。快速排序法又称分割交换排序法,是目前公认的最佳排序法,也是使用分而治之(Divide and Conquer)的方式,会先在数…

Java架构师概要设计

目录 1 导学2 概要设计之任务和方法2.1 继续架构设计2.2 继续技术选型2.3 确定技术栈2.4 架构原型实现与验证2.5 技术预研2.6 分服务分模块2.7 初步设计应用基础框架2.8 定义基本API2.9 定义实体对象2.10 定义数据库表结构3 构建项目工程和环境4 代码组件的关系5 总结1 导学 本…

042:mapboxGL点击某feature点,使其为中心点

第042个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中通过鼠标点击某feature点,让其成为中心点。这里用到了click事件和flyTo的方法。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共113行)相关API参…