如何基于 Nacos 和 Sentinel ,实现灰度路由和流量防护一体化
<dependency><groupId>com.nepxion</groupId><artifactId>discovery-plugin-strategy-starter-service-sentinel</artifactId><version>${discovery.version}</version></dependency><dependency><groupId>com.nepxion</groupId><artifactId>discovery-plugin-strategy-sentinel-starter-nacos</artifactId><!--<artifactId>discovery-plugin-strategy-sentinel-starter-apollo</artifactId>--><version>${discovery.version}</version></dependency>原生Sentinel注解参照下面代码,为接口方法增加@SentinelResource注解,value为sentinel-resource,blockHandler和fallback是防护其作用后需要执行的方法
@RestController@ConditionalOnProperty(name=DiscoveryConstant.SPRING_APPLICATION_NAME,havingValue="discovery-guide-service-b")publicclassBFeignImplextendsAbstractFeignImplimplementsBFeign{privatestaticfinalLoggerLOG=LoggerFactory.getLogger(BFeignImpl.class);@Override@SentinelResource(value="sentinel-resource",blockHandler="handleBlock",fallback="handleFallback")publicStringinvoke(@PathVariable(value="value")Stringvalue){value=doInvoke(value);LOG.info("调用路径:{}",value);returnvalue;}publicStringhandleBlock(Stringvalue,BlockExceptione){returnvalue+"->Bserversentinelblock,cause="+e.getClass().getName()+",rule="+e.getRule()+",limitApp="+e.getRuleLimitApp();}publicStringhandleFallback(Stringvalue){returnvalue+"->Bserversentinelfallback";}}原生Sentinel规则Sentinel在配置中心订阅的Key格式,如下:
1.Nacos的Key格式:Group为元数据中配置的[组名],DataId为[服务名]-[规则类型]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}]如图所示
降级规则增加服务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}]如图所示
授权规则增加服务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}]如图所示
系统规则增加服务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}]如图所示
热点参数流控规则增加服务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}]如图所示
基于灰度路由和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}]自定义业务参数的组合式防护机制通过适配类实现自定义业务参数的组合式防护机制
//版本号+用户名,实现组合式熔断publicclassMyServiceSentinelRequestOriginAdapterextendsDefaultServiceSentinelRequestOriginAdapter{@OverridepublicStringparseOrigin(HttpServletRequestrequest){Stringversion=request.getHeader(DiscoveryConstant.N_D_SERVICE_VERSION);Stringuser=request.getHeader("user");returnversion+"&"+user;}}在配置类里@Bean方式进行适配类创建
@BeanpublicServiceSentinelRequestOriginAdapterServiceSentinelRequestOriginAdapter(){returnnewMyServiceSentinelRequestOriginAdapter();}增加服务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服务,最终调用成功如图所示
当传递的Http Header中user=lisi,不满足条件,最终调用在discovery-guide-service-b服务端被拒绝掉如图所示
当传递的Http Header中user=zhangsan,满足条件之一,当全链路调用中,API网关负载均衡discovery-guide-service-a服务到1.1版本后再去调用discovery-guide-service-b服务,不满足version=1.0的条件,最终调用在discovery-guide-service-b服务端被拒绝掉如图所示
基于Swagger的Sentinel规则推送分为基于单个服务实例和基于服务名对应的多个服务实例的Sentinel规则推送基于单个服务实例的Sentinel规则推送直接访问该服务实例的Swagger主页即可如图所示
基于服务名对应的多个服务实例的Sentinel规则推送需要开启discovery-console服务,并访问其Swagger主页即可如图所示
本文作者:任浩军, 10 多年开源经历,Github ID:@HaojunRen,Nepxion 开源社区创始人,Nacos Group Member,Spring Cloud Alibaba & Nacos & Sentinel Committer ,曾就职于平安银行平台架构部,负责银行 PaaS 系统基础服务框架研发。王伟华, 10 余年 Java 开发,Github ID:@vipweihua,对微服务架构研究多年,当前更多关注于微服务中的网关、限流熔断、灰度路由等,现就职于平安银行平台架构部,从事银行 PaaS 系统基础服务框架研发。
原文链接本文为云栖社区原创内容,未经允许不得转载。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。