由于
Netflflix
中多项开源产品已进入维护阶段,不再开发新的版本,就目前来看是没有什么问题的。但是从长远角度
出发,我们还是需要考虑是否有可替代产品使用。比如本文中要介绍的
Alibaba Sentinel
就是一款高性能且轻量级
的
==
流量控制,熔断降级
==
可替换方案。
Sentinel
官网:
http://github.com/alibaba/Sentinel
HyStrix
目前状态
:
官网
:
http://github.com/Netflflix/Hystrix
1.
学习目标
2. Sentinel
是什么
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。
Sentinel
以流量为切入点,从流量控制、熔断降
级、系统负载保护等多个维度保护服务的稳定性。
Sentinel
具有以下特征
:
丰富的应用场景
:
Sentinel
承接了阿里巴巴近
10
年的双十一大促流量的核心场景,例如秒杀(即突发流量控
制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
完备的实时监控
:
Sentinel
同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数
据,甚至
500
台以下规模的集群的汇总运行情况。
广泛的开源生态
:
Sentinel
提供开箱即用的与其它开源框架
/
库的整合模块,例如与
Spring Cloud
、
Dubbo
、
gRPC
的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入
Sentinel
。
完善的
SPI
扩展点
:
Sentinel
提供简单易用、完善的
SPI
扩展接口。您可以通过实现扩展接口来快速地定制
逻辑。例如定制规则管理、适配动态数据源等。
Sentinel
的主要特性:
Sentinel
的开源生态:
2018
年
Sentinel
分为两个部分
:
核心库(
Java
客户端)不依赖任何框架
/
库,能够运行于所有
Java
运行时环境,同时对
Dubbo / Spring
Cloud
等框架也有较好的支持。【客户端】
控制台(
Dashboard
)基于
Spring Boot
开发,打包后可以直接运行,不需要额外的
Tomcat
等应用容器。
[
服务端
]
3. Sentinel
的核心
Sentinel
的使用可以分为两个部分
:
核心库(
Java
客户端
)
∶不依赖任何框架
/
库,能够运行于
Java 7
及以上的版本的运行时环境,同时对
Dubbo /
Spring Cloud
等框架也有较好的支持
(
见主流框架适配
)
。
控制台
(Dashboard) :
控制台主要负责管理推送规则、监控、集群限流分配管理、机器发现等。
4. Sentinel
的控制台
Sentinel
提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群
)
,规则管理和推送
的功能。
官方文档
:
https://github.com/alibaba/Sentinel/wiki/%E6%8E%A7%E5%88%B6%E5%8F%B0
4.1
获取控制台
您可以从
release
页面
下载最新版本的控制台
jar
包。
您也可以从最新版本的源码自行构建
Sentinel
控制台:
下载
控制台
工程
使用以下命令将代码打包成一个
fat jar:
mvn clean package
4.2
启动控制台
注意
:启动
Sentinel
控制台需要
JDK
版本为
1.8
及以上版本。
使用如下命令启动控制台:
其中
-Dserver.port=8080
用于指定
Sentinel
控制台端口为
8080
。
从
Sentinel 1.6.0
起,
Sentinel
控制台引入基本的
登录
功能,默认用户名和密码都是
sentinel
。可以参考
鉴权模块
文档
配置用户名和密码。
注:若您的应用为
Spring Boot
或
Spring Cloud
应用,您可以通过
Spring
配置文件来指定配置,详情请参
考
Spring Cloud Alibaba Sentinel
文档
。
5.
项目环境
shop-product
:
商品服务,提供了
/product/fifindById/{id}
shop-order-rest
:
订单服务,基于
Ribbon
通过
RestTemplate
调用商品服务。
shop-order-feign
:订单服务,基于
Feign
通过声明式服务调用商品服务。
6.
客户端接入控制台
控制台启动后,客户端需要按照如下步骤接入到控制台:
添加依赖
定义资源
定义规则
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar
sentinel-dashboard.jar
先把可能需要保护的资源定义好,之后再配置规则。也可以理解为,只要有了资源,我们就可以在任何时候灵活地
定义各种流量控制规则。在编码的时候,只需要考虑这个代码是否需要保护,如果需要保护,就将之定义为一个资
源
二、在根目录下开启cmd黑窗口启用jar文件
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar xxxxx.jar
加入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
配置文件
客户端需要启动
Transport
模块来与
Sentinel
控制台进行通信。
shop-order
的
application.yml
spring :cloud :sentinel :transport :port : 8719dashboard : localhost : 8080
定义资源
资源
是
Sentinel
中的核心概念之一。我们说的资源,可以是任何东西,服务,服务里的方法,甚至是一段代码。最
常用的资源是我们代码中的
Java
方法。
Sentinel
提供了
@SentinelResource
注解用于定义资源,并提供了
AspectJ
的
扩展用于自动定义资源、处理
BlockException
等。
package com.slj.order.service.Impl; import com.alibaba.csp.sentinel.annotation.SentinelResource; import com.alibaba.csp.sentinel.slots.block.BlockException; import com.slj.entry.Product; import com.slj.order.service.ProductService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; /** * @program: springcloud-parent * @description: * @author: 孙路军 * @create: 2021-07-15 10:39 **/ @Service public class ProductServiceImpl_blank implements ProductService { @Autowired private RestTemplate restTemplate; @Override @SentinelResource(value = "findByid", blockHandler = "selectByIdBlock", fallback = "selectByIdBack") public Product findByid(Integer pid) { if(pid==1){ throw new RuntimeException("pid不能为1"); } return restTemplate.getForObject("http://shop-product/product/findById?pid=" + pid, Product.class); } public Product selectByIdBlock(Integer pid,BlockException e){ Product product=new Product(); product.setPid(pid); product.setPname("熔断"); return product; } public Product selectByIdBack(Integer pid,Throwable e){ Product product=new Product(); product.setPid(pid); product.setPname("异常"); return product; } }
测试
![](https://i-blog.csdnimg.cn/blog_migrate/e3e7572e11bd513bb9a5246f5087311b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/371a95c7f3d78b440ad0719c54d3cdf8.png)
点击新增之后,继续访问页面同时点击多次就会出现熔断,这个垄断是我们在后台写的
blockHandlerMethod方法里
降级是通常是为异常设置的,设置好降级之后,一般我们要删除流控设置的东西。要不然时间间隔效果看不出来。设置id为1的时候出现异常
![](https://i-blog.csdnimg.cn/blog_migrate/e0843d53bb9dd8609bab064ae80a560f.png)
多次访问id为1就会出现下图所示
![](https://i-blog.csdnimg.cn/blog_migrate/072c5655ad05a46ad8289529caea34e4.png)
设置id为2的不是异常,没过间隔30秒访问id为2也会出现
![](https://i-blog.csdnimg.cn/blog_migrate/8f0e25dc39de06b5a4b592e3c88da9f0.png)
过了30秒之后才会成功访问
![](https://i-blog.csdnimg.cn/blog_migrate/c7d13591145981e0fe334d211b10db89.png)
动态规则扩展
SentinelProperties
内部提供了
TreeMap
类型的
datasource
属性用于配置数据源信息。支持
:·
文件配置规
Nacos
配置规则
ZooKeeper
配置规则
Apollo
配置规则
Redis
配置规则
6.3.3.1.
文件配置规则
Sentinel
支持通过本地文件加载规则配置,使用方式如下
(
限流规则作为演示
)
︰
spring :cloud :sentinel :datasource :ds1 :fifile :fifile : classpath : flflowRule.jsondata-type : jsonrule-type : flflow
flflowRule.json
对应
com.alibaba.csp .sentinel.slots.block .RuleConstant
各属性
[{"resource" : "fifindByid" ,"count" : 1 ,"grade" : 1 ,"limitApp" : "default" ,"strategy" : 0 ,"controlBehavior" : 0}]
![](https://i-blog.csdnimg.cn/blog_migrate/bffc7d3d37802759c74457b7329f74ae.png)
. RestTemplate
支持
Spring Cloud Alibaba Sentinel
支持对
RestTemplate
调用的服务进行服务保护。需要在构造
RestTemplate Bean
时
添加
SentinelRestTemplate
注解。
创建util类ExceptionUtil
package com.slj.order.util; import com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse; import com.alibaba.csp.sentinel.slots.block.BlockException; import com.alibaba.fastjson.JSON; import com.slj.entry.Product; import org.springframework.http.HttpRequest; import org.springframework.http.client.ClientHttpRequestExecution; import org.springframework.http.client.ClientHttpResponse; import org.springframework.stereotype.Component; /** * @program: springcloud-parent * @description: gongjulei * @author: 孙路军 * @create: 2021-07-15 16:44 **/ @Component public class ExceptionUtil { public static ClientHttpResponse fallback(HttpRequest request, byte[] body, ClientHttpRequestExecution execution, BlockException exception) { return new SentinelClientHttpResponse(JSON.toJSONString(new Product(1,"服务流量控制-兜底的数据",5555.0,1000))); } public static ClientHttpResponse handlerException(HttpRequest request, byte[] body, ClientHttpRequestExecution execution, BlockException exception) { return new SentinelClientHttpResponse(JSON.toJSONString(new Product(1,"服务熔断降级控制-兜底的数据",6666.0,1000))); } }
在主启动类上加上注解,方法名要和创建的 ExceptionUti的方法名字一致
![](https://i-blog.csdnimg.cn/blog_migrate/5fc1a63a49b2d1a77b74e2d9dce2dd1d.png)
openfeign的支持
在配置里多加3行代码,是openfeign让sentinel管理所需要的
添加依赖
<dependency><groupId> org.springframework.cloud </groupId><artifactId> spring-cloud-starter-openfeign </artifactId></dependency><dependency><groupId> com.alibaba.cloud </groupId><artifactId> spring-cloud-starter-alibaba-sentinel </artifactId></dependency>
开启
Sentinel
spring :cloud :sentinel :transport :dashboard : localhost : 8080feign :sentinel :enabled : true
创建一个实现类继承所需要的openfeign的方法
openfeign的接口
实现类
![](https://i-blog.csdnimg.cn/blog_migrate/6e9222664d6ead662acd25b6e5a96a03.png)
运行成功后如下图所示
![](https://i-blog.csdnimg.cn/blog_migrate/968575657b9e707a7802dd6dc129c320.png)
当设置降级或者流控之后进行操作如下图所示
![](https://i-blog.csdnimg.cn/blog_migrate/ee1d39213b4177c1334ba9c559143952.png)