ToB企服应用市场:ToB评测及商务社交产业平台

标题: Sentinel [打印本页]

作者: 科技颠覆者    时间: 2024-10-16 12:33
标题: Sentinel
概述

Sentinel 是面向分布式、多语言异构化服务架构的流量管理组件,紧张以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自顺应过载保护、热点流量防护等多个维度来资助开发者保障微服务的稳定性。
官网:https://github.com/alibaba/sentinel
https://sentinelguard.io/zh-cn/docs/introduction.html
Sentinel 紧张特性:
快速开始

下载安装

下载地址:Release v1.8.6 · alibaba/Sentinel · GitHub
Sentinal 组件由两部分构成:

启动命令:
  1. java -jar sentinel-dashboard-1.8.6.jar
复制代码
Sentinal 背景管理界面
用户名和密码都是:sentinal
上线服务

**注意:**Sentinel 必要 JDK 1.8 或更高版本。
  1. <dependency>
  2.     <groupId>com.alibaba.csp</groupId>
  3.     <artifactId>sentinel-core</artifactId>
  4.     <version>1.8.6</version>
  5. </dependency>
复制代码
添加 yaml 文件
  1. server:
  2.   port: 8401
  3. spring:
  4.   application:
  5.     name: cloudalibaba-sentinel-service
  6.   cloud:
  7.     nacos:
  8.       discovery:
  9.         # Nacos服务注册中心地址
  10.         server-addr: 127.0.0.1:8848
  11.     sentinel:
  12.       transport:
  13.         #配置Sentinel dashboard地址
  14.         dashboard: 127.0.0.1:8080
  15.         #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
  16.         port: 8719
  17. management:
  18.   endpoints:
  19.     web:
  20.       exposure:
  21.         include: '*'
复制代码
启动类
  1. @EnableDiscoveryClient
  2. @SpringBootApplication
  3. public class MainApp8401 {
  4.     public static void main(String[] args) {
  5.         SpringApplication.run(MainApp8401.class, args);
  6.     }
  7. }
复制代码
业务类
  1. @RestController
  2. public class FlowLimitController {
  3.     @GetMapping("/testA")
  4.     public String testA() {
  5.         return "testA";
  6.     }
  7.     @GetMapping("/testB")
  8.     public String testB() {
  9.         return "testB";
  10.     }
  11. }
复制代码
启动服务后,调用接口,在 sentienl 控制台中就有了接口流量监控。
至此 sentienl 已经监控到了 8401 的微服务了。
流控规则

任何系一个系统的运算、存储、网络资源都不是无穷的,当系统资源不足不足以支持外部超过预期的突发流量时,便应该有所取舍,建立面对超额流量自我保护的机制,这个机制就是微服务中常说的“限流”。

直接

针对 testA 接口新增流控规则(系统默认:QPS、直接、快速失败)。
如果 testA 调用 QPS 大于 1,就会快速失败。
注意:QPS 与 并发线程数的区别。
QPS 是站在请求端来看的,每秒的请求数目。
并发线程数是服务端并发使用线程数。如果处理很快,QPS 大于 1,但是使用同一个线程。
关联

当关联的资源达到阈值时,就限流自己。比如:A 是下单接口,B 是付出接口。当付出接口(B)达到阈值时(压力大了),限流下单接口(A)。
如图配置:当 testB 接口的 QPS 达到了 1,限流 testA 接口。
使用 Postman 模拟并发调用 testB 接口,让后看 testA 接口的限流情况。
在 Postman 执行期间,testA 接口被限流了。当 Postman 执行完毕后,testA 接口规复正常。限流策略见效。
链路

Warm up(预热)

预热冷启动方式。当系统恒久处于低水位的情况下,流量突增,直接会将系统拉升到高水位,大概刹时把系统压垮。通过“预热”,让流量缓慢增加,在一定的时间内逐渐增加到阈值上限,给冷系同一个预热的时间。根据 codeFactor(冷加载因子,默认 3)的值,从阈值/ codeFactor,经过预热时长,才达到设置的 QPS 阈值。
如下图:接口 testA 的 QPS 大于 100 会触发限流。接口 testA 是新接口上线,刚开始 QPS 达到 100/3 就开始限流,在 5 秒内逐步从 100 /3 提升至 100 的 QPS。
排队等待

匀速排队,让请求以匀速通过,阈值范例必须设置为 QPS,否则无效。
这种方式严格控制了请求通过的间隔时间,也便是让请求以均匀的速率通过,对应的是漏桶算法。
这种方式紧张用于处理间隔性突发的流量,例如消息队列。想象一下如许的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们渴望系统可以或许在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。
下图设置含义:接口 testA 每秒处理 100 次请求,QPS 超过 100 就排队等待,等待的超时时间为 500 ms。
熔断规则

容错性设计(Design for Failure)是微服务的一个核心原则。由于某一个服务的崩溃,导致所有用到这个服务的其他服务都无法正常工作,一个点的错误经过层层通报,最终波及调用链上与此相关的所有服务,这便是雪崩效应。怎样防止雪崩效应便是微服务架构容错性设计原则的具体实现。
要落实容错性设计这条原则,除了从思想观念上转变过来,正视程序必然是会出错的,并对它进行有筹划的防御之外,还必须了解一些常用的容错策略和容错设计模式,作为具体设计与编码实践的指导。这里的容错策略指的是“面对故障,我们该做什么”。Sentinel 提供以下几种熔断策略。

注意:

慢调用比例
异常比例
异常数
热点参数限流

作甚热点?热点即经常访问的数据。许多时候我们渴望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限定。比如:

热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包罗热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包罗热点参数的资源调用见效。
Sentinel 利用 LRU 策略统计最近最常访问的热点参数,联合令牌桶算法来进行参数级别的流控。
实例

新增带参数据的方法
  1.     @GetMapping("/testHotKey")
  2.                 // 热点参数限流,必须使用 SentinelResource,资源名必须是 value
  3.     @SentinelResource(value = "testHotKey")
  4.     public String testHotKey(@RequestParam(value = "p1", required = false) String p1,
  5.                              @RequestParam(value = "p2", required = false) String p2) {
  6.         return "testHotKey";
  7.     }
复制代码
新增热点规则:testHotKey 接口:

如果不设置限量后的效果就会抛异常,异常打到前台用户界面,不友好。
自定义限流后的处理效果。
  1.     @GetMapping("/testHotKey")
  2.     @SentinelResource(value = "testHotKey", blockHandler = "deal_testHotKey")
  3.     public String testHotKey(@RequestParam(value = "p1", required = false) String p1,
  4.                              @RequestParam(value = "p2", required = false) String p2) {
  5.         return "testHotKey";
  6.     }
  7.     public String deal_testHotKey(String p1, String p2, BlockException ex) {
  8.         return "deal_testHotKey";
  9.     }
复制代码
参数例外项

参数例外项:可以针对指定的参数值单独设置限流阈值,不受前面 count 阈值的限定。仅支持基本范例和字符串范例
如下图:

系统自顺应保护

Sentinel 系统自顺应保护从团体维度对应用入口流量进行控制,联合应用的 Load、总体平均 RT、入口 QPS 和线程数等几个维度的监控指标,让系统的入口流量和系统的负载达到一个平衡,让系统尽大概跑在最大吞吐量的同时保证系统团体的稳定性。

@SentinelResource

@SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。 @SentinelResource 注解包罗以部属性:

实例

创建 CustomerBlockHandler 类用于自定义限流处理逻辑。项目中所有的限流兜底逻辑都写在这个类里。
  1. public class CustomerBlockHandler {
  2.     public static CommonResult hanlderException(BlockException exception) {
  3.         return new CommonResult<>(444, "自定义错误信息 global handlerException", "1");
  4.     }
  5.     public static CommonResult hanlderException2(BlockException exception) {
  6.         return new CommonResult<>(444, "自定义错误信息 global handlerException", "2");
  7.     }
  8. }
  9. import lombok.Data;
  10. @Data
  11. public class CommonResult<T> {
  12.     private int code;
  13.     private String message;
  14.     private T data;
  15.     public CommonResult(int code, String message, T data) {
  16.         this.code = code;
  17.         this.message = message;
  18.         this.data = data;
  19.     }
  20. }
复制代码
通过:blockHandlerClass 参数找到限流兜底的类
通过:blockHandler 参数找到限流兜底的类中的方法。
  1.     @GetMapping("/testCustomer")
  2.     @SentinelResource(value = "testCustomer",
  3.             blockHandlerClass = CustomerBlockHandler.class,
  4.             blockHandler = "hanlderException2")
  5.     public CommonResult<String> deal_testHotKey(String p1, String p2, BlockException ex) {
  6.         return new CommonResult<>(200, "testCustomer success", "0");
  7.     }
复制代码
恒久化

一旦重启应用,sentienl 规则就丢失了,生产环境必要将配置进行恒久化。
方案:将限流规则恒久化到 Nacos 中。

新增 mvn 依赖
  1.         <!--SpringCloud ailibaba sentinel-datasource-nacos 后续做持久化用到-->
  2.         <dependency>
  3.             <groupId>com.alibaba.csp</groupId>
  4.             <artifactId>sentinel-datasource-nacos</artifactId>
  5.         </dependency>
复制代码
新增 yml 配置
  1. server:
  2.   port: 8401
  3. spring:
  4.   application:
  5.     name: cloudalibaba-sentinel-service
  6.   cloud:
  7.     nacos:
  8.       discovery:
  9.         #Nacos服务注册中心地址
  10.         server-addr: 127.0.0.1:8848
  11.     sentinel:
  12.       transport:
  13.         #配置Sentinel dashboard地址
  14.         dashboard: 127.0.0.1:8080
  15.         #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
  16.         port: 8719
  17.       datasource:
  18.         ds1:
  19.           nacos:
  20.             server-addr: 127.0.0.1:8848
  21.             dataId: cloudalibaba-sentinel-service
  22.             groupId: DEFAULT_GROUP
  23.             data-type: json
  24.             rule-type: flow
  25. management:
  26.   endpoints:
  27.     web:
  28.       exposure:
  29.         include: '*'
复制代码
手动在 Nacos 中添加接口限流信息
流量控制规则:

熔断降级规则:

之后再重启服务:流控规则中已经用了 Nacos 中添加的流控规则。
注意:此时数据只能从 Nacos 单向 Sentinel 推送,不能从 Sentinel 向 Nacos 推送。
热点规则
  1. [
  2.   {
  3.           // 资源名
  4.     "resource": "/test1",
  5.     // 限流模式(QPS 模式,不可更改)
  6.     "grade": 1,
  7.     // 参数索引
  8.     "paramIdx": 0,
  9.     // 单机阈值
  10.     "count": 13,
  11.     // 统计窗口时长
  12.     "durationInSec": 6,
  13.     // 是否集群 默认false
  14.     "clusterMode": 默认false,
  15.     //
  16.     "burstCount": 0,
  17.     // 集群模式配置
  18.     "clusterConfig": {
  19.       //
  20.       "fallbackToLocalWhenFail": true,
  21.              //
  22.       "flowId": 2,
  23.       //
  24.       "sampleCount": 10,
  25.       //
  26.       "thresholdType": 0,
  27.       //
  28.       "windowIntervalMs": 1000
  29.     },
  30.     // 流控效果(支持快速失败和匀速排队模式)
  31.     "controlBehavior": 0,
  32.     //
  33.     "limitApp": "default",
  34.     //
  35.     "maxQueueingTimeMs": 0,
  36.     // 高级选项
  37.     "paramFlowItemList": [
  38.       {
  39.               // 参数类型
  40.         "classType": "int",
  41.               // 限流阈值
  42.         "count": 222,
  43.               // 参数值
  44.         "object": "2"
  45.       }
  46.     ]
  47.   }
  48. ]
复制代码
系统规则
  1. [
  2.   {
  3.           // RT
  4.     "avgRt": 1,
  5.     // CPU 使用率
  6.     "highestCpuUsage": -1,
  7.     // LOAD
  8.     "highestSystemLoad": -1,
  9.     // 线程数
  10.     "maxThread": -1,
  11.     // 入口 QPS
  12.     "qps": -1
  13.   }
  14. ]
复制代码
授权规则
  1. [
  2.   {
  3.     // 资源名
  4.     "resource": "sentinel_spring_web_context",
  5.           // 流控应用
  6.     "limitApp": "/test",
  7.     // 授权类型(0代表白名单;1代表黑名单。)
  8.     "strategy": 0
  9.   }
  10. ]
复制代码
双向推送

生产环境的 Sentinel Dashboard 必要具备下面几个特性:

规则管理及推送

推送模式说明优点缺点原始模式API 将规则推送至客户端并直接更新到内存中,扩展写数据源简单,无任何依赖不保证一致性;规则保存在内存中,重启即消散。严重不发起用于生产环境Pull 模式扩展写数据源, 客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件 等简单,无任何依赖;规则恒久化不保证一致性;及时性不保证,拉取过于频繁也大概会有性能题目。Push 模式扩展读数据源,规则中心同一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。这种方式有更好的及时性和一致性保证。生产环境下一般采用 push 模式的数据源。规则恒久化;一致性;快速引入第三方依赖 原始模式

如果不做任何修改,Dashboard 的推送规则方式是通过 API 将规则推送至客户端并直接更新到内存中:
这种做法的好处是简单,无依赖;坏处是应用重启规则就会消散,仅用于简单测试,不能用于生产环境。
Pull 模式

pull 模式的数据源(如本地文件、RDBMS 等)一般是可写入的。使用时必要在客户端注册数据源:将对应的读数据源注册至对应的 RuleManager,将写数据源注册至 transport 的 WritableDataSourceRegistry 中。以本地文件数据源为例:
  1. public class FileDataSourceInit implements InitFunc {
  2.     @Override
  3.     public void init() throws Exception {
  4.         String flowRulePath = "xxx";
  5.         ReadableDataSource<String, List<FlowRule>> ds = new FileRefreshableDataSource<>(
  6.             flowRulePath, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {})
  7.         );
  8.         // 将可读数据源注册至 FlowRuleManager.
  9.         FlowRuleManager.register2Property(ds.getProperty());
  10.         WritableDataSource<List<FlowRule>> wds = new FileWritableDataSource<>(flowRulePath, this::encodeJson);
  11.         // 将可写数据源注册至 transport 模块的 WritableDataSourceRegistry 中.
  12.         // 这样收到控制台推送的规则时,Sentinel 会先更新到内存,然后将规则写入到文件中.
  13.         WritableDataSourceRegistry.registerFlowDataSource(wds);
  14.     }
  15.     private <T> String encodeJson(T t) {
  16.         return JSON.toJSONString(t);
  17.     }
  18. }
复制代码
本地文件数据源会定时轮询文件的变动,读取规则。如许我们既可以在应用本地直接修改文件来更新规则,也可以通过 Sentinel 控制台推送规则。以本地文件数据源为例,推送过程如下图所示:
首先 Sentinel 控制台通过 API 将规则推送至客户端并更新到内存中,接着注册的写数据源会将新的规则保存到本地的文件中。使用 pull 模式的数据源时一般不必要对 Sentinel 控制台进行改造。
这种实现方法好处是简单,不引入新的依赖,坏处是无法保证监控数据的一致性。
Push 模式

生产环境下一般更常用的是 push 模式的数据源。对于 push 模式的数据源,如远程配置中心(ZooKeeper, Nacos, Apollo等等),推送的操纵不应由 Sentinel 客户端进行,而应该经控制台同一进行管理,直接进行推送,数据源仅负责获取配置中心推送的配置并更新到本地。因此推送规则正确做法应该是 配置中心控制台/Sentinel 控制台 → 配置中心 → Sentinel 数据源 → Sentinel,而不是经 Sentinel 数据源推送至配置中心。如许的流程就非常清晰了:
从 Sentinel 1.4.0 开始,Sentinel 控制台提供 DynamicRulePublisher 和 DynamicRuleProvider 接口用于实现应用维度的规则推送和拉取,并提供了相关的示例。Sentinel 提供应用维度规则推送的示例页面(/v2/flow),用户改造控制台对接配置中心后可直接通过 v2 页面推送规则至配置中心。改造详情可参考 应用维度规则推送示例。
改造 Sentinel Dashbord

  1. git clone https://github.com/alibaba/Sentinel.git
复制代码
  1. <!-- for Nacos rule publisher sample -->
  2.         <dependency>
  3.             <groupId>com.alibaba.csp</groupId>
  4.             <artifactId>sentinel-datasource-nacos</artifactId>
  5.             <!--<scope>test</scope>-->
  6.         </dependency>
复制代码
  1.   <!--<li ui-sref-active="active" ng-if="!entry.isGateway">
  2.             <a ui-sref="dashboard.flowV1({app: entry.app})">
  3.               <i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控规则</a>
  4.           </li>-->
  5.           <!-- 修改为flow,直接调用FlowControllerV2 -->
  6.           <li ui-sref-active="active" ng-if="!entry.isGateway">
  7.             <a ui-sref="dashboard.flow({app: entry.app})">
  8.               <i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控规则</a>
  9.           </li>
复制代码
如许就可以通过js跳转至FlowControllerV2了
  1.       .state('dashboard.flow', {
  2.           templateUrl: 'app/views/flow_v2.html',
  3.           url: '/v2/flow/:app',
  4.           controller: 'FlowControllerV2',
  5.           resolve: {
  6.               loadMyFiles: ['$ocLazyLoad', function ($ocLazyLoad) {
  7.                   return $ocLazyLoad.load({
  8.                       name: 'sentinelDashboardApp',
  9.                       files: [
  10.                           'app/scripts/controllers/flow_v2.js',
  11.                       ]
  12.                   });
  13.               }]
  14.           }
  15.       })
复制代码
  1. import org.springframework.boot.context.properties.ConfigurationProperties;
  2. @ConfigurationProperties(prefix = "sentinel.nacos")
  3. public class NacosPropertiesConfiguration {
  4.     private String serverAddr;
  5.     private String dataId;
  6.     private String groupId = "SENTINEL_GROUP"; // 默认分组
  7.     private String namespace;
  8.     private String username;
  9.     private String password;
  10.     // 省略 getter/setter  
  11. }
复制代码
然后配置sentinel-dashboar/resources/application.properties中配置nacos配置,以为sentinel.nacos为前缀:
  1. sentinel.nacos.serverAddr=192.168.3.104:8848
  2. sentinel.nacos.namespace=7bdf4616-b415-4221-a381-e1542e75af53
  3. sentinel.nacos.group-id=SENTINEL-GROUP
  4. sentinel.nacos.username=nacos
  5. sentinel.nacos.password=nacos
复制代码
编写 Sentinel 客户端

联调测试

在 sentinel-dashboard 上配置限量数据已经 push 到 Nacos 中了。
上线服务重启后,接口依然可以限量
注意:sentinel-dashboard 界面上有许多添加流控的入口,都必要改为调用 FlowControllerV2
参考文档:


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4