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

x33g5p2x  于2021-12-30 转载在 Java  
字(12.1k)|赞(0)|评价(0)|浏览(284)
SpringCloud学习目录点击跳转对应的文章
Java之 Spring Cloud 微服务搭建(第一个阶段)【一】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务 Eureka (第一个阶段)【二】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务搭建Ribbon(第一个阶段)【三】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务搭建 Consul(第一个阶段)【四】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务搭建 Feign组件(第二个阶段)【一】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务搭建 Hystrix (第二个阶段)【二】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务搭建Sentinel (第二个阶段)【三】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务搭建网关 nginx,Zuul(第三个阶段)【一】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务搭建网关SpringCloud Gateway微服务网关GateWay(第三个阶段)【二】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务的链路追踪 Sleuth 和 Zipkin(第三个阶段)【三】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务的 Spring Cloud Stream(第四个阶段)【一】【SpringBoot项目实现商品服务器端调用】
Java之 Spring Cloud 微服务的 SpringCloud Config 配置中心(第四个阶段)【二】【SpringBoot项目实现商品服务器端调用】
Java之 Spring Cloud 微服务的开源配置中心Apollo(第四个阶段)【三】【SpringBoot项目实现商品服务器端调用】

一、服务熔断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 。可以参考 鉴权模块文档 配置用户名和密码。

启动 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

<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

  • order_service_feign

  • order_service_rest

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

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

cloud:
    sentinel:
      transport:
        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

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 指定
触发异常执行的降级方法。

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

ds1:
          file:
            file: classpath:flowrule.json
            data-type: json
            rule-type: flow
      eager: true #立即加载

2)创建flowrule.json

[
  {
    "resource": "orderFindById",
    "controlBehavior": 0,
    "count": 1,
    "grade": 1,
    "limitApp": "default",
    "strategy": 0
  }
]

3)运行测试

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

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

6 、RestTemplate的资源保护

(1)修改order_service_rest当中的OrderController

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

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);
	}

}

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

1)创建ExceptionUtils

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));
    }
}
2)完善RestOrderApplication

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);
	}
}
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)引入依赖

<!-- 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>

(2) 开启sentinel 支持

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

# 激活sentinel的支持
feign:
  sentinel:
    enabled: true

(3)配置FeignClient

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

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

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

触发熔断

SpringCloud学习目录点击跳转对应的文章
Java之 Spring Cloud 微服务搭建(第一个阶段)【一】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务 Eureka (第一个阶段)【二】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务搭建Ribbon(第一个阶段)【三】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务搭建 Consul(第一个阶段)【四】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务搭建 Feign组件(第二个阶段)【一】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务搭建 Hystrix (第二个阶段)【二】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务搭建Sentinel (第二个阶段)【三】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务搭建网关 nginx,Zuul(第三个阶段)【一】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务搭建网关SpringCloud Gateway微服务网关GateWay(第三个阶段)【二】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务的链路追踪 Sleuth 和 Zipkin(第三个阶段)【三】【SpringBoot项目实现商品服务器端是调用】
Java之 Spring Cloud 微服务的 Spring Cloud Stream(第四个阶段)【一】【SpringBoot项目实现商品服务器端调用】
Java之 Spring Cloud 微服务的 SpringCloud Config 配置中心(第四个阶段)【二】【SpringBoot项目实现商品服务器端调用】
Java之 Spring Cloud 微服务的开源配置中心Apollo(第四个阶段)【三】【SpringBoot项目实现商品服务器端调用】

相关文章

微信公众号

最新文章

更多