写在前面

用XMind画了一张导图记录Spring Cloud Alibaba的学习笔记(源文件对部分节点有详细备注和参考资料,由于太大就没展示全部,欢迎关注我的公众号:阿风的架构笔记 后台发送【导图】拿下载链接, 已经完善更新):

前言

思考这个问题:

Sentinel的降级熔断的配置,生产环境使用的时候,一般会在控制台管理,持久化到Nacos;微服务监听Nacos的配置变化,从而实现服务调用的降级熔断策略。

现在就会遇到这样的问题,如果有很多Feign接口,如上图服务A、服务B都有一些Feign接口的远程调用,都需要我们进行一一配置。而且配置的一些参数绝大多数都一样的。如:

1、对Feign远程调用的慢响应策略的配置降级策略

2、对Feign远程调用的异常数的配置降级策略

3、对Feign远程调用的异常比例数的配置降级策略

针对上面的配置1-2个服务方法还好;但是现在公司的生产环境都有100~200个微服务,服务之间的调用方法就更多了;那针对普通标准的降级熔断的配置都需要人工一个个配置,那是不是太麻烦了。

本文就来解决这个问题,跟着继续往下看。

源码分析

我们先来看看Sentinel是怎么设置熔断策略的,在上图中我们知道是通过Sentinel控制台进行配置,然后微服务都可以订阅这些配置;我们看一下源码。

这个是监听nacos配置的相关的代码

上图代码核心就是发现配置有变化,就updateValue规则;我们继续跟踪代码发现一个DegradeRuleManager降级规则的管理类,里面有2个核心的变量ruleMap、circuitBreakers;我们可以猜出就是降级规则集合以及熔断规则集合。

在继续往下看,我们发现有个RulePropertyListener中reloadFrom方法****,即重新加载规则;方法里面有个buildCircuitBreakers方法,一看方法名就知道是构建熔断策略。

在看一下buildCircuitBreakers方法,我们看到本质就是遍历DegradeRule集合,然后在初始化熔断对象CircuitBreaker。

这里我们知道熔断是怎么产生的了;本质就是通过DegradeRule产生的。

解决方案

上面我们知道了一些熔断对象产生的原理,我们只要可以自定义DegradeRule对象就可以产生。我们在学习Sentinel的时候,他有个Api方式去定义降级规则,大家可以去看一下之前的文章,详细介绍了Api定义规则的方式。我们看一下案例

我们可以看到DegradeRule对象的定义,以及DegradeRuleManager对象;上面的代码就能给资源名api定义了慢响应的降级策略了

讲到这里聪明的小伙伴们有没有想到一些思路呢?往下看。

方案思路

先给出整体的解决思路

上图中介绍的流程

1、启动服务时扫描jar,获取@FeignClient注解的接口(技术难点一:扫描哪些jar包)
2、获得Feign接口中的调用方法
3、服务本地创建DegradeRule对象。(技术难点二:Sentinel的资源名支持动态配置)
4、把设置的默认的降级熔断规则同步到Nacos

根据上面的流程,我们就可以看到,一旦微服务启动了,就会自动把Feign接口配置默认的降级熔断规则,以及同步到Nacos中;再结合之前文章中介绍的Sentinel控制台改造,就立刻在控制台显示这些降级规则了,而不需要认为配置了。

注意:上面只是介绍了整体流程,在编写代码的时候,我们需要考虑到很多场景,如:

一)服务第二次启动的时候,nacos中已经有了相关的配置,是否还要修改nacos的配置。

二)以及有些特殊业务在Sentinel控制台进行了降级配置,那默认的全局配置如何兼容人工的配置。

这些就不在这里讲了,本文只介绍核心方案思路,核心代码

其他的有兴趣的小伙伴们,可以跟要源码

技术难点

难点一

我们扫码jar包,而且是要扫码包含@FeignClient注解接口的jar。我们知道在使用Feign功能的时候,需要在SpringBootApplication启动类中加上@EnableFeignClients;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ApplicationA {
public static void main(String[] args) {
SpringApplication.run(ApplicationA.class, args);
}
}

有的时候Feign包会用第三方jar的形式存在,那代码就有会变成

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients(basePackages = {"com.rainbow.demo1.feign","com.rainbow.demo2.feign"})
public class ApplicationA {
public static void main(String[] args) {
SpringApplication.run(ApplicationA.class, args);
}
}

里面的@EnableFeignClients注解的属性basePackages中显式的指向了Feign包的位置了,这个比较好弄,直接用用ClassScan工具类扫就行了。

ClassScan工具类是支持子包扫描的

那没有显式的定义basePackages,那怎么获取到jar包路径呢?

我们可以参考SpringCloud的源码实现的方法,看代码。

上面是根据启动服务时,堆栈信息获取main方法的启动类对象。

根据启动类对象,获取到EnableFeignClients对象,如果没有basePackages,那就是以启动类的包为扫描的入口。

这样我们就解决了扫描jar入口的问题。

难点二

常规方式

资源名的获取,举个例子

@FeignClient(name = "service-provider")
public interface ProviderServiceFeign {
@GetMapping("/transferHeaders")
public BaseRestResponse<String> transferHeaders();
}

根据微服务的Sentinel资源名定义,@FeignClient(name = "service-provider"),微服务名是service-provider;那针对transferHeaders()方法的降级策略资源名即为

lb://service-provider/transferHeaders

这个实现比较简单就是获取@FeignClient的name的值,以及方法@GetMapping里面的值就可以拼接出资源名。

指定Url地址

@FeignClient(name = "service-provider",url = "http://xxxxx")
public interface ProviderServiceFeign {
@GetMapping("/transferHeaders")
public BaseRestResponse<String> transferHeaders();
}

指定url的目的其实就是指定请求的方式,这种情况的Sentinel的资源名即为

http://xxxxx/transferHeaders

这个技术实现也比较简单,只需要考虑到这个场景,就可以了。

动态配置Url

还有一种情况即对接第三方平台时,我们一般不会写死Url,而是通过配置的方式,如

@FeignClient(name = "service-provider",url = "${reqUrl}")
public interface ProviderServiceFeign {
@GetMapping("/transferHeaders")
public BaseRestResponse<String> transferHeaders();
}

上面的${reqUrl}是通过配置的,那Sentinel的资源名是什么样的呢?本质上面资源名也是Url+具体的请求地址,即

http://${reqUrl}/transferHeaders

但是这样设置资源名肯定是不正确的,需要把具体的配置值拿过来拼接。那我们就需要在程序中获取${reqUrl}的值,讲到这里小伙伴们知道怎么实现了吗?其实就是用到

Environment environment ;//环境变量对象
this.environment.resolvePlaceholders(url);//获取变量的值

核心代码

上面的技术难点解决掉之后,我们就放开双手撸代码了,这里贴上核心的代码;小伙伴们。

public class DegradeRuleInitializer implements ApplicationRunner, EnvironmentAware

实现ApplicationRunner, EnvironmentAware就能够实现启动时,去扫描了,入口就在ApplicationRunner中的run方法。

扫描类

扫描FeignClient

初始化默认规则

设置了默认降级规则,把配置信息发布到nacos

效果

一旦微服务启动了,nacos配置就有了

我们会把默认的值发布到nacos里面,小伙伴们可以具体看一些资源名,里面就会有很多降级规则。

我们再来看看Sentinel控制台,里面就显示了降级规则列表;设计的是针对同一个资源名做异常数、异常比例、慢响应三种类型的降级熔断策略。

全局默认的值,到底是多少阀值,是可以通过配置的方式的,这些就不介绍了。比较简单。

到这里就全部实现了微服务中Feign接口的降级熔断策略的默认化配置,不需要人工去添加了;当然是支持人工去修改的,如果需要修改阀值,可以人工修改。

总结

本文介绍了Sentinel的全局Feign默认熔断的技术实现方案,整体思路原理不是太复杂,就是利用其本身的功能,做了一些扩展;这样更方便用户的使用。

看完三件事️



如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:

  1. 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  2. 关注公众号 『 阿风的架构笔记 』,不定期分享原创知识。
  3. 同时可以期待后续文章ing
  4. 关注后回复【666】扫码即可获取架构进阶学习资料包

Sentinel全局Feign默认熔断设计实现的更多相关文章

  1. Spring Cloud Alibaba Sentinel 整合 Feign 的设计实现

    作者 | Spring Cloud Alibaba 高级开发工程师洛夜 来自公众号阿里巴巴中间件投稿 前段时间 Hystrix 宣布不再维护之后(Hystrix 停止开发...Spring Cloud ...

  2. Spring Cloud Alibaba Sentinel对Feign的支持

    Spring Cloud Alibaba Sentinel 除了对 RestTemplate 做了支持,同样对于 Feign 也做了支持,如果我们要从 Hystrix 切换到 Sentinel 是非常 ...

  3. SpringCloud Gateway高阶之Sentinel限流、熔断

    前言 为什么需要服务熔断和降级?微服务是当前业界的一大趋势,原理就是将单一职责的功能模块独立化为子服务,降低服务间的耦合,服务间互相调用.但是这样也会出现一些问题: 上图中大量微服务互相调用,存在大量 ...

  4. Sentinel流控与熔断

    参考: https://thinkwon.blog.csdn.net/article/details/103770879 项目结构 com.guo     ├── guo-sentinel       ...

  5. 全局axios默认值 和 自定义实例默认值

    首先说了一下情况, 登录后成功返回token 然后在带着token去继续下面的请求, 奇怪的是都是当前页面起作用,刷新和跳转之后就token 就消失了. 查了 axios文档发现 被自己坑了 我设置了 ...

  6. 一个名叫Sentinel-Rules-SDK的组件,使得Sentinel的流控&熔断规则的配置更加方便

    原文链接:一个名叫Sentinel-Rules-SDK的组件,使得Sentinel的流控&熔断规则的配置更加方便 1 Sentinel 是什么? 随着微服务的流行,服务和服务之间的稳定性变得越 ...

  7. SpringCloud:feign默认jackson解析'yyyy-MM-ddTHH:mm:ssZ'时间格式报错

    Feign默认的使用jackson解析,所以时间传值时会报错,时间格式错误 解决办法: 修改feign解析方式为fastjson方式: @Configuration public class CxfC ...

  8. Spring Cloud中Hystrix、Ribbon及Feign的熔断关系是什么?

    导读 今天和大家聊一聊在Spring Cloud微服务框架实践中,比较核心但是又很容易把人搞得稀里糊涂的一个问题,那就是在Spring Cloud中Hystrix.Ribbon以及Feign它们三者之 ...

  9. Sentinel与OpenFeign 服务熔断那些事

    点赞再看,养成习惯,微信搜索[牧小农]关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友. 项目源码地址:公众号回复 sentinel,即可免费获取源码 在上一篇中,我们讲解了 Senti ...

随机推荐

  1. windows driver 简单的驱动和通信

    sysmain.c #pragma once #pragma warning(disable: 4100) #include <ntifs.h> #include <ntddk.h& ...

  2. APC推出鞋底缓震科技 两款中高端跑鞋将陆续上市

    近日,英国知名运动品牌APC(公司编号:08703733)推出了全新的鞋底缓震科技 NOVR,该项技术将首先应用于两款跑步鞋上,随后陆续应用到其他重点鞋类产品. 是对于各大运动品牌来说,鞋底研发一直是 ...

  3. NGK Global技术开源,开启跨链全生态

    消息显示,新兴公链项目NGK Global已经完成了自己的开源计划,基于自己创新性的跨链通讯交互方案,开源后的NGK Global将面向全生态节点,提供高效.自由.无边界的公链生态系统. 目前,大家对 ...

  4. std::vector与std::list效能对比(基于c++11)

    测试对象类型不同,数量级不同时,表现具有差异: 测试数据对象为std::function时: test: times(1000)vector push_back time 469 usvector e ...

  5. SSL/TLS协议详解(中)——证书颁发机构

    本文转载自SSL/TLS协议详解(中)--证书颁发机构 导语 上一篇中,我们讨论了关于Diffie Hellman算法的SSL/TLS密钥交换.我们最终认为需要第三方来验证服务器的真实性,并提出了证书 ...

  6. (嘎吧)--微软的 C# , IL,CLR, Cup 之间关系以及扩展联想

    还是啰嗦下:文章短并不代表文章质量不高.我最喜欢用干货性的以及总结性的语言 让大家明白文章要表达的内容.这一切,都是来自多年对.NET 的一些领悟以及一些理解. 不长篇大论,一本人也没时间,二本人也不 ...

  7. Prism -- 简介

    Prism是一个开源框架,用于在WPF.Xamarin Forms.Uno/Win UI等应用中创建松耦合.可维护.可测试的XAML应用程序.Prism提供了一组设计模式的实现,这些设计模式有助于编写 ...

  8. 《C++ Primer》笔记 第6章 函数

    任意两个形参都不能同名,而且函数最外层作用域中的局部变量也不能使用与函数形参一样的名字(形参就相当于该函数的局部变量). 形参名是可选的,但是由于我们无法使用未命名的形参,所以形参一般都应该有个名字. ...

  9. CCF(数据中心):最小生成树+kruskal算法

    数据中心 201812-4 这里就是最小生成树的应用 #include<iostream> #include<cstdio> #include<algorithm> ...

  10. 【pytest官方文档】解读fixtures - 7. Teardown处理,yield和addfinalizer

    当我们运行测试函数时,我们希望确保测试函数在运行结束后,可以自己清理掉对环境的影响. 这样的话,它们就不会干扰任何其他的测试函数,更不会日积月累的留下越来越多的测试数据. 用过unittest的朋友相 ...