sentinel 官方文档_如何基于 Nacos 和 Sentinel ,实现灰度路由和流量防护一体化
发布日期:2021-09-13 06:38:57 浏览次数:2 分类:技术文章

本文共 8124 字,大约阅读时间需要 27 分钟。

基于Alibaba Nacos和Sentinel,实现灰度路由和流量防护一体化的解决方案,发布在最新的 Nepxion Discovery 5.4.0 版,具体参考:

源码主页,请访问 源码主页
指南主页,请访问 指南主页
文档主页,请访问 文档主页

Nepxion Discovery框架在实现灰度发布和路由功能前提下,结合Nacos和Sentinel,对流量再实施一层防护措施,更能达到企业级的流量安全控制的目的。它的功能包括:

  • 封装远程配置中心和本地规则文件的读取逻辑,即优先读取远程配置,如果不存在或者规则错误,则读取本地规则文件。动态实现远程配置中心对于规则的热刷新
  • 封装NacosDataSource和ApolloDataSource,支持Nacos和Apollo两个远程配置中心,零代码实现Sentinel功能。更多的远程配置中心,请参照Sentinel官方的DataSource并自行集成
  • 支持原生的流控规则、降级规则、授权规则、系统规则、热点参数流控规则
  • 支持扩展LimitApp的机制,通过动态的Http Header方式实现组合式防护机制,包括基于服务名、基于灰度组、基于灰度版本、基于灰度区域、基于机器地址和端口等防护机制,支持自定义任意的业务参数组合实现该功能,例如,根据传入的微服务灰度版本号+用户名,组合在一起进行熔断
  • 支持微服务侧Actuator、Swagger和Rest三种方式的规则写入
  • 支持控制台侧基于微服务名的Actuator、Swagger和Rest三种方式的批量规则写入
  • 支持开关关闭上述功能spring.application.strategy.sentinel.enabled=true,默认是关闭的

[Nacos] 阿里巴巴中间件部门开发的新一代集服务注册发现中心和配置中心为一体的中间件。它是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施,支持几乎所有主流类型的“服务”的发现、配置和管理,更敏捷和容易地构建、交付和管理微服务平台

[Sentinel] 阿里巴巴中间件部门开发的新一代以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性的分布式系统的流量防卫兵。它承接了阿里巴巴近10年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等

环境搭建及依赖引入

服务端在Discovery框架原有依赖的基础上,再引入如下依赖

     
      
com.nepxion
discovery-plugin-strategy-starter-service-sentinel
${discovery.version}

com.nepxion
discovery-plugin-strategy-sentinel-starter-nacos

${discovery.version}

原生Sentinel注解

参照下面代码,为接口方法增加@SentinelResource注解,value为sentinel-resource,blockHandler和fallback是防护其作用后需要执行的方法

@RestController@ConditionalOnProperty(name = DiscoveryConstant.SPRING_APPLICATION_NAME, havingValue = "discovery-guide-service-b")public class BFeignImpl extends AbstractFeignImpl implements BFeign {
private static final Logger LOG = LoggerFactory.getLogger(BFeignImpl.class);
@Override
@SentinelResource(value = "sentinel-resource", blockHandler = "handleBlock", fallback = "handleFallback")
public String invoke(@PathVariable(value = "value") String value) {
value = doInvoke(value);
LOG.info("调用路径:{}", value);
return value;
}
public String handleBlock(String value, BlockException e) {
return value + "-> B server sentinel block, cause=" + e.getClass().getName() + ", rule=" + e.getRule() + ", limitApp=" + e.getRuleLimitApp();
}
public String handleFallback(String value) {
return value + "-> B server sentinel fallback";
}}

原生Sentinel规则

Sentinel在配置中心订阅的Key格式,如下:

1. Nacos的Key格式:Group为元数据中配置的[组名],Data Id为[服务名]-[规则类型]2. Apollo的Key格式:[组名]-[服务名]-[规则类型]

Sentinel规则的用法,请参照Sentinel官方文档

流控规则

增加服务discovery-guide-service-b的规则,Group为discovery-guide-group,Data Id为discovery-guide-service-b-sentinel-flow,规则内容如下:

[
{
"resource": "sentinel-resource",
"limitApp": "default",
"grade": 1,
"count": 1,
"strategy": 0,
"refResource": null,
"controlBehavior": 0,
"warmUpPeriodSec": 10,
"maxQueueingTimeMs": 500,
"clusterMode": false,
"clusterConfig": null
}]

如图所示

e7802c80fdfe69a37b60f65547470ca6.png

降级规则

增加服务discovery-guide-service-b的规则,Group为discovery-guide-group,Data Id为discovery-guide-service-b-sentinel-degrade,规则内容如下:

[
{
"resource": "sentinel-resource",
"limitApp": "default",
"count": 2,
"timeWindow": 10,
"grade": 0,
"passCount": 0
}]

如图所示

1b4c178766a1ea2c208ab92273845bbc.png

授权规则

增加服务discovery-guide-service-b的规则,Group为discovery-guide-group,Data Id为discovery-guide-service-b-sentinel-authority,规则内容如下:

[
{
"resource": "sentinel-resource",
"limitApp": "discovery-guide-service-a",
"strategy": 0
}]

如图所示

6df1593df5b0444c57a0ce6a9a28e4d7.png

系统规则

增加服务discovery-guide-service-b的规则,Group为discovery-guide-group,Data Id为discovery-guide-service-b-sentinel-system,规则内容如下:

[
{
"resource": null,
"limitApp": null,
"highestSystemLoad": -1.0,
"highestCpuUsage": -1.0,
"qps": 200.0,
"avgRt": -1,
"maxThread": -1
}]

如图所示

a6fcbf5daaf58b26e594a4f8f1c8cc0b.png

热点参数流控规则

增加服务discovery-guide-service-b的规则,Group为discovery-guide-group,Data Id为discovery-guide-service-b-sentinel-param-flow,规则内容如下:

[
{
"resource": "sentinel-resource",
"limitApp": "default",
"grade": 1,
"paramIdx": 0,
"count": 1,
"controlBehavior": 0,
"maxQueueingTimeMs": 0,
"burstCount": 0,
"durationInSec": 1,
"paramFlowItemList": [],
"clusterMode": false
}]

如图所示

0fb3c34bfede72b689f4a873db7f7f9a.png

基于灰度路由和Sentinel-LimitApp扩展的防护机制

该方式对于上面5种规则都有效,这里以授权规则展开阐述

授权规则中,limitApp,如果有多个,可以通过“,”分隔。"strategy": 0 表示白名单,"strategy": 1 表示黑名单

基于服务名的防护机制

修改配置项Sentinel Request Origin Key为服务名的Header名称,修改授权规则中limitApp为对应的服务名,可实现基于服务名的防护机制

配置项,该配置项默认为n-d-service-id,可以不配置

spring.application.strategy.service.sentinel.request.origin.key=n-d-service-id

增加服务discovery-guide-service-b的规则,Group为discovery-guide-group,Data Id为discovery-guide-service-b-sentinel-authority,规则内容如下,表示所有discovery-guide-service-a服务允许访问discovery-guide-service-b服务

[
{
"resource": "sentinel-resource",
"limitApp": "discovery-guide-service-a",
"strategy": 0
}]

基于灰度组的防护机制

修改配置项Sentinel Request Origin Key为灰度组的Header名称,修改授权规则中limitApp为对应的组名,可实现基于组名的防护机制

配置项

spring.application.strategy.service.sentinel.request.origin.key=n-d-service-group

增加服务discovery-guide-service-b的规则,Group为discovery-guide-group,Data Id为discovery-guide-service-b-sentinel-authority,规则内容如下,表示隶属my-group组的所有服务都允许访问服务discovery-guide-service-b

[
{
"resource": "sentinel-resource",
"limitApp": "my-group",
"strategy": 0
}]

基于灰度版本的防护机制

修改配置项Sentinel Request Origin Key为灰度版本的Header名称,修改授权规则中limitApp为对应的版本,可实现基于版本的防护机制

配置项

spring.application.strategy.service.sentinel.request.origin.key=n-d-service-version

增加服务discovery-guide-service-b的规则,Group为discovery-guide-group,Data Id为discovery-guide-service-b-sentinel-authority,规则内容如下,表示版本为1.0的所有服务都允许访问服务discovery-guide-service-b

[
{
"resource": "sentinel-resource",
"limitApp": "1.0",
"strategy": 0
}]

基于灰度区域的防护机制

修改配置项Sentinel Request Origin Key为灰度区域的Header名称,修改授权规则中limitApp为对应的区域,可实现基于区域的防护机制

配置项

spring.application.strategy.service.sentinel.request.origin.key=n-d-service-region

增加服务discovery-guide-service-b的规则,Group为discovery-guide-group,Data Id为discovery-guide-service-b-sentinel-authority,规则内容如下,表示区域为dev的所有服务都允许访问服务discovery-guide-service-b

[
{
"resource": "sentinel-resource",
"limitApp": "dev",
"strategy": 0
}]

基于机器地址和端口的防护机制

修改配置项Sentinel Request Origin Key为灰度区域的Header名称,修改授权规则中limitApp为对应的区域值,可实现基于机器地址和端口的防护机制

配置项

spring.application.strategy.service.sentinel.request.origin.key=n-d-service-address

增加服务discovery-guide-service-b的规则,Group为discovery-guide-group,Data Id为discovery-guide-service-b-sentinel-authority,规则内容如下,表示地址和端口为192.168.0.88:8081和192.168.0.88:8082的服务都允许访问服务discovery-guide-service-b

[
{
"resource": "sentinel-resource",
"limitApp": "192.168.0.88:8081,192.168.0.88:8082",
"strategy": 0
}]

自定义业务参数的组合式防护机制

通过适配类实现自定义业务参数的组合式防护机制

// 版本号+用户名,实现组合式熔断public class MyServiceSentinelRequestOriginAdapter extends DefaultServiceSentinelRequestOriginAdapter {
@Override
public String parseOrigin(HttpServletRequest request) {
String version = request.getHeader(DiscoveryConstant.N_D_SERVICE_VERSION);
String user = request.getHeader("user");
return version + "&" + user;
}}

在配置类里@Bean方式进行适配类创建

@Beanpublic ServiceSentinelRequestOriginAdapter ServiceSentinelRequestOriginAdapter() {
return new MyServiceSentinelRequestOriginAdapter();}

增加服务discovery-guide-service-b的规则,Group为discovery-guide-group,Data Id为discovery-guide-service-b-sentinel-authority,规则内容如下,表示版本为1.0且传入的Http Header的user=zhangsan,同时满足这两个条件下的所有服务都允许访问服务discovery-guide-service-b

[
{
"resource": "sentinel-resource",
"limitApp": "1.0&zhangsan",
"strategy": 0
}]

运行效果

  • 当传递的Http Header中user=zhangsan,当全链路调用中,API网关负载均衡discovery-guide-service-a服务到1.0版本后再去调用discovery-guide-service-b服务,最终调用成功

如图所示

dbacb4f83fa5b7122165035a82a76331.png
  • 当传递的Http Header中user=lisi,不满足条件,最终调用在discovery-guide-service-b服务端被拒绝掉

如图所示

29b6c0eb8e3e373819ba327faee44957.png
  • 当传递的Http Header中user=zhangsan,满足条件之一,当全链路调用中,API网关负载均衡discovery-guide-service-a服务到1.1版本后再去调用discovery-guide-service-b服务,不满足version=1.0的条件,最终调用在discovery-guide-service-b服务端被拒绝掉

如图所示

bf8e327babfddc94a22f477eb8f88129.png

基于Swagger的Sentinel规则推送

分为基于单个服务实例和基于服务名对应的多个服务实例的Sentinel规则推送

基于单个服务实例的Sentinel规则推送

直接访问该服务实例的Swagger主页即可

如图所示

0c6b4a9ee05cc836416695494371213d.png

基于服务名对应的多个服务实例的Sentinel规则推送

需要开启discovery-console服务,并访问其Swagger主页即可

如图所示

f0b6eed23f39982d09d1aeb811f5d952.png

作者介绍:

任浩军, 10 多年开源经历,Github ID:@HaojunRen,Nepxion 开源社区创始人,Nacos Group Member,Spring Cloud Alibaba & Nacos & Sentinel Committer ,曾就职于平安银行平台架构部,负责银行 PaaS 系统基础服务框架研发。

王伟华, 10 余年 Java 开发,Github ID:@vipweihua,对微服务架构研究多年,当前更多关注于微服务中的网关、限流熔断、灰度路由等,现就职于平安银行平台架构部,从事银行 PaaS 系统基础服务框架研发。

本文作者:任浩军、王伟华

原文链接

更多技术干货敬请关注云栖社区知乎机构号:阿里云云栖社区 - 知乎

本文为云栖社区原创内容,未经允许不得转载。

转载地址:https://blog.csdn.net/weixin_39767645/article/details/111003602 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:开关电源spice仿真与实用设计_十年电源研发工程师的30条开关电源设计实用经验...
下一篇:pythoncanny边缘检测自适应阈值_基于python实现自适应阈值的canny边缘检测

发表评论

最新留言

第一次来,支持一个
[***.191.171.39]2022年05月05日 15时37分35秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

最新文章

gets()scanf()有害------c++程序设计原理与实践(进阶篇) 2022-04-04
编码原则实例------c++程序设计原理与实践(进阶篇) 2022-04-04
类与类之间的两种关系------新标准c++程序设计 2022-04-04
多态的作用-游戏编程展示------新标准c++程序设计 2022-04-04
多态实现的原理------新标准c++程序设计 2022-04-04
c++小知识 2022-04-04
类型转换构造函数 及使用explicit避免类型自动转换------新标准c++程序设计 2020-01-30 06:35:44
析构函数的调用------新标准c++程序设计 2020-01-30 06:35:44
复制构造函数被调用的三种情况------新标准c++程序设计 2020-01-30 06:35:44
c++内存模型------计算机系统核心概念及软硬件实现 2020-01-30 06:35:43
封闭类------新标准c++程序设计 2020-01-30 06:35:43
类的互相包含------新标准c++程序设计 2020-01-30 06:35:44
this指针------新标准c++程序设计 2020-01-30 06:35:44
指针和动态分配内存 (不定长度数组)------新标准c++程序设计 2020-01-30 06:35:43
string类------新标准c++程序设计 2020-01-30 06:35:43
c++缓冲区------c++ Primer Plus 2020-01-30 06:35:43
stream.fail() eof() EOF 2020-01-30 06:35:42
strcmp返回值布尔类型的判断 2020-01-30 06:35:42
内联函数背景、例子、与普通函数的区别及要注意的地方 ------新标准c++程序设计 2020-01-30 06:35:42
c++ 用new后delete,而继续输出指针后果 new/new[]/delete/delete[]区别 2020-01-30 06:35:42