18年底Netflix官方宣布Hystrix 已经足够稳定,不再积极开发 Hystrix,该项目将处于维护模式。就目前来看Hystrix是比较稳定的,并且Hystrix只是停止开发新的版本,并不是完全停止维护,Bug什么的依然会维护的。因此短期内,Hystrix依然是继续使用的。但从长远来看,Hystrix总会达到它的生命周期,那么Spring Cloud生态中是否有替代产品呢?
Alibaba Sentinel
Sentinel 是阿里巴巴开源的一款断路器实现,目前在Spring Cloud的孵化器项目Spring Cloud Alibaba中的一员Sentinel本身在阿里内部已经被大规模采用,非常稳定。因此可以作为一个较好的替代品。
Resilience4J
Resilicence4J 一款非常轻量、简单,并且文档非常清晰、丰富的熔断工具,这也是Hystrix官方推荐的替代产品。
不仅如此,Resilicence4j还原生支持Spring Boot 1.x/2.x,而且监控也不像Hystrix一样弄Dashboard/Hystrix等一堆轮子,而是支持和Micrometer(Pivotal开源的监控门面,Spring Boot 2.x中的Actuator就是基于Micrometer的)、prometheus(开源监控系统,来自谷歌的论文)、以及Dropwizard metrics(Spring Boot曾经的模仿对象,类似于Spring Boot)进行整合。
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
Sentinel 具有以下特征:
Sentinel 的主要特性:
Sentinel官方提供了详细的由Hystrix 迁移到Sentinel 的方法
Sentinel 可以简单的分为 Sentinel 核心库和 Dashboard。核心库不依赖 Dashboard,但是结合Dashboard 可以取得最好的效果。
使用 Sentinel 来进行熔断保护,主要分为几个步骤:
资源:可以是任何东西,一个服务,服务里的方法,甚至是一段代码。
规则:Sentinel 支持以下几种规则:流量控制规则、熔断降级规则、系统保护规则、来源访问控制规则和 热点参数规则。
Sentinel 的所有规则都可以在内存态中动态地查询及修改,修改之后立即生效先把可能需要保护的资源定义好,之后再配置规则。
也可以理解为,只要有了资源,我们就可以在任何时候灵活地定义各种流量控制规则。在编码的时候,只需要考虑这个代码是否需要保护,如果需要保护,就将之定义为一个资源。
您可以从官方网站中下载最新版本的控制台 jar 包,下载地址如下:
https://github.com/alibaba/Sentinel/releases/download/1.6.3/sentinel-dashboard-1.6.3.jar
使用如下命令启动控制台:java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.6.3.jar
其中 -Dserver.port=8080
用于指定 Sentinel
控制台端口为 8080
。
从 Sentinel 1.6.0
起,Sentinel
控制台引入基本的登录功能,默认用户名和密码都是 sentinel
。可以参考 鉴权模块文档 配置用户名和密码。
启动 Sentinel 控制台需要 JDK 版本为 1.8 及以上版本。
访问:
http://localhost:8080/#/login
控制台启动后,客户端需要按照以下步骤接入到控制台。
之前都已经创建过这里直接导入代码学习即可
代码下载地址
https://download.csdn.net/download/qq_44757034/49774279
启动所有项目
需要注意SpringCloud-Alibaba与SpringCloud的版本关系
父工程引入alibaba实现的SpringCloud
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
子工程中引入sentinel
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
cloud:
sentinel:
transport:
dashboard: localhost:8080 #sentinel控制台的请求地址
cloud:
sentinel:
transport:
dashboard: localhost:8080 #sentinel控制台的请求地址
访问:http://localhost:9003/order/buy/1
http://localhost:9004/order/buy/1
访问:http://localhost:8080/#/login
package cn.itbluebox.order.controller;
import cn.itbluebox.order.entity.Product;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
/** * @SentinelResource * blockHandler : 声明熔断时调用的降级方法 * fallback : 抛出异常执行的降级方法 * value : 自定义的资源名称 * * 不设置:当前全类名.方法名 */
@SentinelResource(value="orderFindById",blockHandler = "orderBlockHandler",fallback = "orderFallback")
@RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
public Product findById(@PathVariable Long id) {
if(id != 1) {
throw new RuntimeException("错误");
}
return restTemplate.getForObject("http://service-product/product/1",Product.class);
}
/** * 定义降级逻辑 * hystrix和sentinel * 熔断执行的降级方法 * 抛出异常执行的降级方法 */
public Product orderBlockHandler(Long id) {
Product product = new Product();
product.setProductName("触发熔断的降级方法");
return product;
}
public Product orderFallback(Long id) {
Product product = new Product();
product.setProductName("抛出异常执行的降级方法");
return product;
}
}
在需要被保护的方法上使用@SentinelResource注解进行熔断配置。与Hystrix不同的是,Sentinel对抛
出异常和熔断降级做了更加细致的区分,通过 blockHandler 指定熔断降级方法,通过 fallback 指定
触发异常执行的降级方法。
访问http://localhost:9004/order/buy/1
访问http://localhost:8080/#/dashboard/metric/service-order-rest
访问测试:http://localhost:9004/order/buy/2进入降级方法
多刷新上述访问我们再次访问http://localhost:9004/order/buy/1也进入降级方法
等待5s以后再次访问http://localhost:9004/order/buy/1
恢复正常状态,退出降级方法
注:1.6.0 之前的版本 fallback 函数只针对降级异常( DegradeException )进行处理,不能针对业务异常进行处理。
特别地,若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。
若未配置 blockHandler 、 fallback 和 defaultFallback ,则被限流降级时会BlockException 直接抛出。
一条限流规则主要由下面几个因素组成:
resource:资源名,即限流规则的作用对象
count: 限流阈值
grade: 限流阈值类型(QPS 或并发线程数)
limitApp: 流控针对的调用来源,若为 default 则不区分调用来源
strategy: 调用关系限流策略
controlBehavior: 流量控制效果(直接拒绝、Warm Up、匀速排队)
java代码 RuleConstant
配置文件添加如下配置
#通过文件读取限流规则
spring.cloud.sentinel.datasource.ds1.file.file=classpath: flowrule.json
spring.cloud.sentinel.datasource.ds1.file.data-type=json
spring.cloud.sentinel.datasource.ds1.file.rule-type=flow
ds1:
file:
file: classpath:flowrule.json
data-type: json
rule-type: flow
eager: true #立即加载
[
{
"resource": "orderFindById",
"controlBehavior": 0,
"count": 1,
"grade": 1,
"limitApp": "default",
"strategy": 0
}
]
访问:http://localhost:9004/order/buy/1
访问:http://localhost:8080/#/dashboard/identity/service-order-rest
去除之前配置的关于熔断的方法
package cn.itbluebox.order.controller;
import cn.itbluebox.order.entity.Product;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
/** * @SentinelResource * blockHandler : 声明熔断时调用的降级方法 * fallback : 抛出异常执行的降级方法 * value : 自定义的资源名称 * * 不设置:当前全类名.方法名 */
@RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
public Product findById(@PathVariable Long id) {
if(id != 1) {
throw new RuntimeException("错误");
}
return restTemplate.getForObject("http://service-product/product/1",Product.class);
}
}
package cn.itbluebox.order.exception;
import cn.itbluebox.order.entity.Product;
import com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.JSON;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
public class ExceptionUtils {
/** * 静态方法 * 返回值: SentinelClientHttpResponse * 参数 : request , byte[] , clientRquestExcetion , blockException */
//限流熔断业务逻辑
public static SentinelClientHttpResponse handleBlock(HttpRequest request, byte[] body,
ClientHttpRequestExecution execution,
BlockException ex) {
Product product = new Product();
product.setProductName("限流熔断降级");
return new SentinelClientHttpResponse(JSON.toJSONString(product));
}
//异常降级业务逻辑
public static SentinelClientHttpResponse handleFallback(HttpRequest request, byte[] body,
ClientHttpRequestExecution execution,
BlockException ex) {
Product product = new Product();
product.setProductName("异常熔断降级");
return new SentinelClientHttpResponse(JSON.toJSONString(product));
}
}
package cn.itbluebox.order;
import cn.itbluebox.order.exception.ExceptionUtils;
import com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EntityScan("cn.itbluebox.order.entity")
public class RestOrderApplication {
/** * sentinel支持对restTemplate的服务调用使用sentinel方法.在构造 * RestTemplate对象的时候,只需要加载@SentinelRestTemplate即可 * 资源名: * httpmethod:schema://host:port/path :协议、主机、端口和路径 * httpmethod:schema://host:port :协议、主机和端口 * @SentinelRestTemplate: * 异常降级 * fallback : 降级方法 * fallbackClass : 降级配置类 * 限流熔断 * blockHandler * blockHandlerClass */
@LoadBalanced
@Bean
@SentinelRestTemplate(fallbackClass = ExceptionUtils.class,fallback = "handleFallback",
blockHandler = "handleBlock",blockHandlerClass = ExceptionUtils.class)
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(RestOrderApplication.class,args);
}
}
访问:http://localhost:9004/order/buy/1
访问:http://localhost:9004/order/buy/2
访问管理控制台:http://localhost:8080/#/dashboard/degrade/service-order-rest
访问测试:慢一些访问:http://localhost:9004/order/buy/1
快速多次访问
Sentinel 适配了 Feign 组件。如果想使用,除了引入 sentinel-starter 的依赖外还需要 2 个步骤:
在order_service_feign当中的
<!-- feign对Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
在工程的application.yml中添加sentinel 对 feign 的支持
# 激活sentinel的支持
feign:
sentinel:
enabled: true
在之前我们已经设置好了熔断了直接启动运行即可
访问:http://localhost:9003/order/buy/1
访问:http://localhost:8080/#/dashboard/identity/service-order-feign
多次访问:http://localhost:9003/order/buy/1
触发熔断
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/qq_44757034/article/details/121610520
内容来源于网络,如有侵权,请联系作者删除!