Java之 Spring Cloud 微服务搭建Sentinel (第二个阶段)【三】【SpringBoot项目实现商品服务器端是调用】

x33g5p2x  于2021-11-29 转载在 Java  
字(10.3k)|赞(0)|评价(0)|浏览(411)

一、服务熔断Hystrix的替换方案

18年底Netflix官方宣布Hystrix 已经足够稳定,不再积极开发 Hystrix,该项目将处于维护模式。就目前来看Hystrix是比较稳定的,并且Hystrix只是停止开发新的版本,并不是完全停止维护,Bug什么的依然会维护的。因此短期内,Hystrix依然是继续使用的。但从长远来看,Hystrix总会达到它的生命周期,那么Spring Cloud生态中是否有替代产品呢?

1、替换方案介绍

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)进行整合。

2、 Sentinel概述

(1) Sentinel简介

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

Sentinel 具有以下特征:

  • 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
  • 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
  • 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入Sentinel。
  • 完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

Sentinel 的主要特性:

(2) Sentinel与Hystrix的区别

(3) 迁移方案

Sentinel官方提供了详细的由Hystrix 迁移到Sentinel 的方法

(4) 名词解释

Sentinel 可以简单的分为 Sentinel 核心库和 Dashboard。核心库不依赖 Dashboard,但是结合Dashboard 可以取得最好的效果。
使用 Sentinel 来进行熔断保护,主要分为几个步骤:

  1. 定义资源
  2. 定义规则
  3. 检验规则是否生效

资源:可以是任何东西,一个服务,服务里的方法,甚至是一段代码。

规则:Sentinel 支持以下几种规则:流量控制规则、熔断降级规则、系统保护规则、来源访问控制规则和 热点参数规则。

Sentinel 的所有规则都可以在内存态中动态地查询及修改,修改之后立即生效先把可能需要保护的资源定义好,之后再配置规则。

也可以理解为,只要有了资源,我们就可以在任何时候灵活地定义各种流量控制规则。在编码的时候,只需要考虑这个代码是否需要保护,如果需要保护,就将之定义为一个资源。

3、Sentinel中的管理控制台

(1)下载启动控制台

1)获取 Sentinel 控制台

您可以从官方网站中下载最新版本的控制台 jar 包,下载地址如下:
https://github.com/alibaba/Sentinel/releases/download/1.6.3/sentinel-dashboard-1.6.3.jar

2)启动

使用如下命令启动控制台: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 。可以参考 鉴权模块文档 配置用户名和密码。

  1. 启动 Sentinel 控制台需要 JDK 版本为 1.8 及以上版本。

访问:
http://localhost:8080/#/login

4 、基于Sentinel的服务保护

(1)客户端能接入控制台(将所有的服务交给控制台管理)

控制台启动后,客户端需要按照以下步骤接入到控制台。

1)创建案例

之前都已经创建过这里直接导入代码学习即可
代码下载地址
https://download.csdn.net/download/qq_44757034/49774279

启动所有项目

2)引入依赖

需要注意SpringCloud-Alibaba与SpringCloud的版本关系

父工程引入alibaba实现的SpringCloud

  1. <dependency>
  2. <groupId>com.alibaba.cloud</groupId>
  3. <artifactId>spring-cloud-alibaba-dependencies</artifactId>
  4. <version>2.1.0.RELEASE</version>
  5. <type>pom</type>
  6. <scope>import</scope>
  7. </dependency>

子工程中引入sentinel

  • order_service_feign

  • order_service_rest

  1. <dependency>
  2. <groupId>com.alibaba.cloud</groupId>
  3. <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
  4. </dependency>
3)配置参数
  • 在order_service_rest当中的application.yml

  1. cloud:
  2. sentinel:
  3. transport:
  4. dashboard: localhost:8080 #sentinel控制台的请求地址
  • order_service_feign当中的application.yml

  1. cloud:
  2. sentinel:
  3. transport:
  4. dashboard: localhost:8080 #sentinel控制台的请求地址
4)启动运行测试

访问:http://localhost:9003/order/buy/1

http://localhost:9004/order/buy/1

访问:http://localhost:8080/#/login

(2)通用的资源保护

1)修改order_service_rest当中的OrderController

  1. package cn.itbluebox.order.controller;
  2. import cn.itbluebox.order.entity.Product;
  3. import com.alibaba.csp.sentinel.annotation.SentinelResource;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.web.bind.annotation.PathVariable;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RequestMethod;
  8. import org.springframework.web.bind.annotation.RestController;
  9. import org.springframework.web.client.RestTemplate;
  10. @RestController
  11. @RequestMapping("/order")
  12. public class OrderController {
  13. @Autowired
  14. private RestTemplate restTemplate;
  15. /** * @SentinelResource * blockHandler : 声明熔断时调用的降级方法 * fallback : 抛出异常执行的降级方法 * value : 自定义的资源名称 * * 不设置:当前全类名.方法名 */
  16. @SentinelResource(value="orderFindById",blockHandler = "orderBlockHandler",fallback = "orderFallback")
  17. @RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
  18. public Product findById(@PathVariable Long id) {
  19. if(id != 1) {
  20. throw new RuntimeException("错误");
  21. }
  22. return restTemplate.getForObject("http://service-product/product/1",Product.class);
  23. }
  24. /** * 定义降级逻辑 * hystrix和sentinel * 熔断执行的降级方法 * 抛出异常执行的降级方法 */
  25. public Product orderBlockHandler(Long id) {
  26. Product product = new Product();
  27. product.setProductName("触发熔断的降级方法");
  28. return product;
  29. }
  30. public Product orderFallback(Long id) {
  31. Product product = new Product();
  32. product.setProductName("抛出异常执行的降级方法");
  33. return product;
  34. }
  35. }

在需要被保护的方法上使用@SentinelResource注解进行熔断配置。与Hystrix不同的是,Sentinel对抛
出异常和熔断降级做了更加细致的区分,通过 blockHandler 指定熔断降级方法,通过 fallback 指定
触发异常执行的降级方法。

2)运行测试

访问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
恢复正常状态,退出降级方法

3)对于@SentinelResource的其他配置如下表:

注:1.6.0 之前的版本 fallback 函数只针对降级异常( DegradeException )进行处理,不能针对业务异常进行处理。

特别地,若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。

若未配置 blockHandler 、 fallback 和 defaultFallback ,则被限流降级时会BlockException 直接抛出。

5 、加载本地配置

一条限流规则主要由下面几个因素组成:

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

1)修改order_service_rest当中的application.yml

  1. ds1:
  2. file:
  3. file: classpath:flowrule.json
  4. data-type: json
  5. rule-type: flow
  6. eager: true #立即加载

2)创建flowrule.json

  1. [
  2. {
  3. "resource": "orderFindById",
  4. "controlBehavior": 0,
  5. "count": 1,
  6. "grade": 1,
  7. "limitApp": "default",
  8. "strategy": 0
  9. }
  10. ]

3)运行测试

访问:http://localhost:9004/order/buy/1

访问:http://localhost:8080/#/dashboard/identity/service-order-rest

6 、RestTemplate的资源保护

(1)修改order_service_rest当中的OrderController

去除之前配置的关于熔断的方法

  1. package cn.itbluebox.order.controller;
  2. import cn.itbluebox.order.entity.Product;
  3. import com.alibaba.csp.sentinel.annotation.SentinelResource;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.web.bind.annotation.PathVariable;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RequestMethod;
  8. import org.springframework.web.bind.annotation.RestController;
  9. import org.springframework.web.client.RestTemplate;
  10. @RestController
  11. @RequestMapping("/order")
  12. public class OrderController {
  13. @Autowired
  14. private RestTemplate restTemplate;
  15. /** * @SentinelResource * blockHandler : 声明熔断时调用的降级方法 * fallback : 抛出异常执行的降级方法 * value : 自定义的资源名称 * * 不设置:当前全类名.方法名 */
  16. @RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
  17. public Product findById(@PathVariable Long id) {
  18. if(id != 1) {
  19. throw new RuntimeException("错误");
  20. }
  21. return restTemplate.getForObject("http://service-product/product/1",Product.class);
  22. }
  23. }

(2)在order_service_rest当中的RestOrderApplication上测试

1)创建ExceptionUtils

  1. package cn.itbluebox.order.exception;
  2. import cn.itbluebox.order.entity.Product;
  3. import com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse;
  4. import com.alibaba.csp.sentinel.slots.block.BlockException;
  5. import com.alibaba.fastjson.JSON;
  6. import org.springframework.http.HttpRequest;
  7. import org.springframework.http.client.ClientHttpRequestExecution;
  8. public class ExceptionUtils {
  9. /** * 静态方法 * 返回值: SentinelClientHttpResponse * 参数 : request , byte[] , clientRquestExcetion , blockException */
  10. //限流熔断业务逻辑
  11. public static SentinelClientHttpResponse handleBlock(HttpRequest request, byte[] body,
  12. ClientHttpRequestExecution execution,
  13. BlockException ex) {
  14. Product product = new Product();
  15. product.setProductName("限流熔断降级");
  16. return new SentinelClientHttpResponse(JSON.toJSONString(product));
  17. }
  18. //异常降级业务逻辑
  19. public static SentinelClientHttpResponse handleFallback(HttpRequest request, byte[] body,
  20. ClientHttpRequestExecution execution,
  21. BlockException ex) {
  22. Product product = new Product();
  23. product.setProductName("异常熔断降级");
  24. return new SentinelClientHttpResponse(JSON.toJSONString(product));
  25. }
  26. }
2)完善RestOrderApplication

  1. package cn.itbluebox.order;
  2. import cn.itbluebox.order.exception.ExceptionUtils;
  3. import com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;
  4. import org.springframework.boot.SpringApplication;
  5. import org.springframework.boot.autoconfigure.SpringBootApplication;
  6. import org.springframework.boot.autoconfigure.domain.EntityScan;
  7. import org.springframework.cloud.client.loadbalancer.LoadBalanced;
  8. import org.springframework.context.annotation.Bean;
  9. import org.springframework.web.client.RestTemplate;
  10. @SpringBootApplication
  11. @EntityScan("cn.itbluebox.order.entity")
  12. public class RestOrderApplication {
  13. /** * sentinel支持对restTemplate的服务调用使用sentinel方法.在构造 * RestTemplate对象的时候,只需要加载@SentinelRestTemplate即可 * 资源名: * httpmethod:schema://host:port/path :协议、主机、端口和路径 * httpmethod:schema://host:port :协议、主机和端口 * @SentinelRestTemplate: * 异常降级 * fallback : 降级方法 * fallbackClass : 降级配置类 * 限流熔断 * blockHandler * blockHandlerClass */
  14. @LoadBalanced
  15. @Bean
  16. @SentinelRestTemplate(fallbackClass = ExceptionUtils.class,fallback = "handleFallback",
  17. blockHandler = "handleBlock",blockHandlerClass = ExceptionUtils.class)
  18. public RestTemplate restTemplate() {
  19. return new RestTemplate();
  20. }
  21. public static void main(String[] args) {
  22. SpringApplication.run(RestOrderApplication.class,args);
  23. }
  24. }
3)运行测试

访问: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

快速多次访问

7 、Feign实现熔断

Sentinel 适配了 Feign 组件。如果想使用,除了引入 sentinel-starter 的依赖外还需要 2 个步骤:

  • 配置文件打开 sentinel 对 feign 的支持: feign.sentinel.enabled=true
  • 加入 openfeign starter 依赖使 sentinel starter 中的自动化配置类生效:

在order_service_feign当中的

(1)引入依赖

  1. <!-- feign对Sentinel -->
  2. <dependency>
  3. <groupId>com.alibaba.cloud</groupId>
  4. <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.cloud</groupId>
  8. <artifactId>spring-cloud-starter-openfeign</artifactId>
  9. </dependency>

(2) 开启sentinel 支持

在工程的application.yml中添加sentinel 对 feign 的支持

  1. # 激活sentinel的支持
  2. feign:
  3. sentinel:
  4. enabled: true

(3)配置FeignClient

在之前我们已经设置好了熔断了直接启动运行即可
访问:http://localhost:9003/order/buy/1

访问:http://localhost:8080/#/dashboard/identity/service-order-feign

多次访问:http://localhost:9003/order/buy/1

触发熔断

相关文章

最新文章

更多