A. 关于sentinel 介绍
https://yq.aliyun.com/articles/622405?spm=a2c4e.11155435.0.0.10e43312oGe2of
B. 功能
限流:
当我们设计了一个函数,准备上线,这时候这个函数会消耗一些资源,处理上限是1秒服务3000个QPS,但如果实际情况遇到高于3000的QPS该如何解决呢?Sentinel提供了两种流量统计方式,一种是统计并发线程数,另外一种则是统计 QPS,当并发线程数超出某个设定的阀值,新的请求会被立即拒绝,当QPS超出某个设定的阀值,系统可以通过直接拒绝、冷启动、匀速器三种方式来应对,从而起流量控制的作用。
熔断降级:
接触过Spring Cloud、Service Mesh的同学,都知道熔断降级的概念。服务之间会有相互依赖关系,例如服务A做到了1秒上万个QPS,但这时候服务B并无法满足1秒上万个QPS,那么如何保证服务A在高频调用服务B时,服务B仍能正常工作呢?一种比较常见的情况是,服务A调用服务B时,服务B因无法满足高频调用出现响应时间过长的情况,导致服务A也出现响应过长的情况,进而产生连锁反应影响整个依赖链上的所有应用,这时候就需要熔断和降级的方法。Sentinel通过并发线程数进行限制和响应时间对资源进行降级两种手段来对服务进行熔断或降级。
塑性:
通常我们遇到的流量具有随机性、不规则、不受控的特点,但系统的处理能力往往是有限的,我们需要根据系统的处理能力对流量进行塑形,即规则化,从而根据我们的需要来处理流量。Sentinel通过资源的调用关系、运行指标、控制的效果三个维度来对流量进行控制,开发者可以自行灵活组合,从而达到理想的效果。
系统负载保护:
平时系统运行都没问题,但遇到大促的时候,发现机器的load非常高,这时候对系统的负载保护就显得非常重要,以防止雪崩。Sentinel 提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围之内处理最多的请求。需要注意的是,Sentinel在系统负载保护方面的判断机制是根据系统能够处理的请求,和允许进来的请求,来做平衡,而不是根据一个间接的指标(系统load)来做限流。因为我们最终追求的目标是在系统不被拖垮的情况下,提高系统的吞吐率,而不是load一定要到低于某个阀值。
名词解释
什么是资源?
只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。
大部分情况下,可以使用方法签名、URL,甚至服务名称作为资源名称来标识资源。资源可以是 Java 应用程序中的任何内容,例如应用程序提供的 Dubbo 服务 或 HTTP API,或应用程序调用的其它应用提供的服务,甚至可以是一段代码。
示例:
通过 Sentinel API 定义了资源:
Entry entry = null;
try {
entry = SphU.entry("HelloWorld");
// 正常的业务逻辑
System.out.println("hello world");
} catch (BlockException e1) {
// 处理资源被限制的情况
System.out.println("block!");
} finally {
if (entry != null) {
entry.exit();
}
}
然后调用此资源,那么在 AHAS 控制台就可以看到 HelloWorld
这个资源了。
什么是规则?
在 AHAS 中围绕应用或应用资源的实时状态来设定规则,包括流控规则、降级规则和系统保护规则。
所有规则都会推送至该应用或应用资源所在的每台机器上,并针对单台机器生效。您可以通过控制台动态实时调整规则。
什么是流控(或称限流)?
流控,即流量控制,是 AHAS 提供的一种应用高可用防护能力。流量控制包括限流、冷启动、削峰填谷等各种流量塑形手段。限流是根据流量,当达到您指定的阈值时立即拦截流量,进行限流,以避免被瞬时的流量高峰冲垮,从而保障您的应用高可用性。
什么是熔断降级?
熔断降级是分布式服务中不可缺少的一种防护手段。其原理是当应用不稳定时,通常表现为响应时间或异常比例升高,则将不稳定应用降级甚至熔断,防止关联应用被不稳定的应用拖垮。
什么是系统防护?
系统防护是从系统表现,例如 Load、RT、QPS 和线程数四个维度出发,对应用的入口流量进行控制,让系统尽可能跑在最大吞吐量的同时保证系统稳定性。
实践:
1. 创建Module
maven 还需引入
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>0.2.1.RELEASE</version>
</dependency>
完整版pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.jhr</groupId>
<artifactId>product-alibaba-sentinel</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>product-alibaba-sentinel</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR3</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- springcloud Alibaba -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>0.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2. 注册中心及其他配置
具体查看前期博客:
注册中心Eureka:https://blog.csdn.net/lettuce_/article/details/102459507
feign:https://blog.csdn.net/lettuce_/article/details/102475469
3. 配置文件
server:
port: 8054
management:
endpoints:
web:
exposure:
include: "*"
cors:
allowed-origins: "*"
allowed-methods: "*"
spring:
application:
name: product-alibaba-sentinel
thymeleaf:
cache: false
prefix: classpath:/templates/
suffix: .html
encoding: UTF-8
mode: HTML5
servlet:
content-type: text/html
#开启 sentinel 对 feign 的支持
feign:
sentinel:
enabled: true
# eureka 信息
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
注意:不添加此配置,fallbback 不起作用
feign:
sentinel:
enabled: true
4. 添加Feign 的fallback
Feign 调用接口
@FeignClient(value = "PRODUCT-DATA-SERVICE", fallback = ProductClientFeignFallback.class)// 被调用的模块名
public interface ProductClientFeign {
@GetMapping(value = "/products") //被调用的模块的接口
public List<Product> listProdcuts();
}
熔断后的fallback 实现类(出错后,返给前端的信息)
@Component
public class ProductClientFeignFallback implements ProductClientFeign {
@Override
public List<Product> listProdcuts() {
Product product=new Product();
product.setId(0);
product.setName("熔断出错:Feign调用ProductData出错");
List<Product> list=new ArrayList<>();
list.add(product);
return list;
}
}
5. 启动项目
1. 启动 EurekaService
2. 启动 ProductData(服务提供者)
3. 启动本Module(服务消费者)
正常访问页面
关闭 ProductData 后,访问页面
关于降级的文档