目录
Spring Cloud Alibaba专栏目录(点击进入…)
Spring Cloud Alibaba Nacos Config(分布式配置),对外暴露的Endpoint,使用案例?
Spring Cloud Ailibaba Sentinel(限流)
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性
(1)服务降级
当某个服务不可用或者出现错误时,能进行一个有效的返回,让请求的资源能够释放,避免服务雪崩。
(2)服务熔断
服务熔断可以理解为服务降级的升级版,在规定是时间范围内,多次调用服务失败,这个时候,就会触发服务熔断。就像生活中的电闸,漏电的时候,会触发跳闸断电。
(3)服务限流
服务限流通过字面意思我们就不难理解出,限制服务流量,说白了就是限制服务的请求速度。
Sentinel特征?
(1)丰富的应用场景
Sentinel承接了阿里巴巴近10年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、实时熔断下游不可用应用等
(2)完备的实时监控
Sentinel同时提供实时的监控功能。可以在控制台中看到接入应用的单台机器秒级数据,甚至500台以下规模的集群的汇总运行情况
(3)广泛的开源生态
Sentinel提供开箱即用的与其它开源框架/库的整合模块,例如与Spring Cloud、Dubbo、gRPC 的整合。只需要引入相应的依赖并进行简单的配置即可快速地接入Sentinel
(4)完善的SPI扩展点
Sentinel提供简单易用、完善的SPI扩展点。可以通过实现扩展点,快速的定制逻辑
例如:定制规则管理、适配数据源等
Sentinel使用步骤
在 @SentinelResource 中使用 blockHandler 进行限流、熔断等处理时,Sentinel 的具体实现逻辑分为以下几个关键步骤:
(1)流量监控
Sentinel 通过在 @SentinelResource 注解指定的资源上设置监控。每当一个方法(资源)被调用时,Sentinel 会对资源的访问情况进行统计,如 QPS(每秒查询量)、请求延迟等。这个过程主要由 Sentinel 的 Slot Chain(插槽链) 来执行,链中的各个插槽负责不同的检查和监控工作。
(2)规则配置
在服务运行时,Sentinel 会检查为每个资源配置的流控规则或熔断规则。这些规则可以通过代码、配置文件、控制台动态设置。常见规则包括:
流控规则:根据请求速率、并发量、流量来源等条件决定是否限制流量。
熔断规则:当调用错误率或响应时间超出阈值时,触发熔断,暂时停止对某个资源的调用。
限流规则的核心参数
规则 | 描述 |
---|---|
resource | 限流的资源名称,通常是方法名或接口路径。 |
grade | 限流类型,QPS(1)或并发线程数(0)。 |
count | 限流阈值,QPS 或线程数的限制。 |
controlBehavior | 限流行为模式,如预热、匀速排队。 |
limitApp | 指定限流的调用来源。 |
(3)调用链拦截
在运行时,当调用某个被 @SentinelResource 注解标记的方法时,Sentinel 的核心库会将请求通过 Slot Chain(插槽链)处理。插槽链中的每个插槽会检查当前请求是否符合限流、熔断或降级条件。
如果没有规则被触发,请求会被正常处理,调用目标业务方法;如果规则被触发,Sentinel 会抛出 BlockException,表示当前请求被阻断或降级。
Sentinel基本使用
1.导入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2.启动类
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(ServiceApplication.class, args);
}
}
3.Controller处理类
@RestController
public class TestController {
@GetMapping(value = "/hello")
@SentinelResource("hello")
public String hello() {
return "Hello Sentinel";
}
}
@SentinelResource:标识资源是否被限流、降级
用于定义资源,并提供可选的异常处理和fallback配置项。
@SentinelResource注解属性:
(1)value(必需,资源名)
资源名称,必需项(不能为空)
(2)entryType(类型)
entry类型,可选项(默认为EntryType.OUT)
(3)blockHandler/blockHandlerClass(限流函数)
blockHandler对应处理BlockException的函数名称,可选项。
blockHandler函数访问范围需要是public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为BlockException。blockHandler函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定blockHandlerClass为对应的类的Class对象。
注意:对应的函数必需为static函数,否则无法解析。
(4)fallback/fallbackClass(可选项)
fallback函数名称,可选项;用于在抛出异常的时候提供fallback处理逻辑。fallback函数可以针对所有类型的异常(除了exceptionsToIgnore里面排除掉的异常类型)进行处理
fallback函数签名和位置要求:
①返回值类型必须与原函数返回值类型一致
②方法参数列表需要和原函数一致,或者可以额外多一个Throwable类型的参数用于接收对应的异常
③fallback函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定fallbackClass为对应的类的Class对象。
注意:对应的函数必需为static函数,否则无法解析
(5)defaultFallback(since 1.6.0,可选项)
注意:1.6.0之前版本fallback函数只针对降级异常(DegradeException)进行处理,不能针对业务异常进行处理。1.8.0版本开始,defaultFallback支持在类级别进行配置。
默认的fallback函数名称,可选项。通常用于通用的fallback逻辑(即可以用于很多服务或方法)。默认fallback函数可以针对所有类型的异常(除了exceptionsToIgnore里面排除掉的异常类型)进行处理。若同时配置了fallback和defaultFallback,则只有fallback会生效
defaultFallback函数签名要求:
①返回值类型必须与原函数返回值类型一致
②方法参数列表需要为空,或者可以额外多一个Throwable类型的参数用于接收对应的异常
③defaultFallback函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定fallbackClass为对应的类的Class对象。注意:对应的函数必需为static函数,否则无法解析
(6)exceptionsToIgnore(since 1.6.0)
用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入fallback逻辑中,而是会原样抛出
注意:若blockHandler和fallback都进行了配置,则被限流降级而抛出BlockException时只会进入blockHandler处理逻辑。若未配置blockHandler、fallback和defaultFallback,则被限流降级时会将BlockException直接抛出(若方法本身未定义throws BlockException则会被JVM包装一层 UndeclaredThrowableException)。
从1.4.0版本开始,注解方式定义资源支持自动统计业务异常,无需手动调用Tracer.trace(ex)来记录业务异常。Sentinel 1.4.0以前的版本需要自行调用Tracer.trace(ex)来记录业务异常。
public class TestService {
// 原函数
@SentinelResource(value = "hello", blockHandler = "exceptionHandler", fallback = "helloFallback")
public String hello(long s) {
return String.format("Hello at %d", s);
}
// Fallback 函数,函数签名与原函数一致或加一个 Throwable 类型的参数.
public String helloFallback(long s) {
return String.format("Halooooo %d", s);
}
// Block 异常处理函数,参数最后多一个 BlockException,其余与原函数一致.
public String exceptionHandler(long s, BlockException ex) {
// Do some log here.
ex.printStackTrace();
return "Oops, error occurred at " + s;
}
// 这里单独演示 blockHandlerClass 的配置.
// 对应的 `handleException` 函数需要位于 `ExceptionUtil` 类中,并且必须为 public static 函数.
@SentinelResource(value = "test", blockHandler = "handleException", blockHandlerClass = {ExceptionUtil.class})
public void test() {
System.out.println("Test");
}
}
Sentinel提供了@SentinelResource注解用于定义资源,并提供了AspectJ的扩展用于自动定义资源、处理BlockException等。使用Sentinel Annotation AspectJ Extension的时候需要引入以下依赖:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
</dependency>
注意:注解方式不支持private私有方法
在WebServlet环境下使用
在WebServlet环境下使用Sentinel,目前已经支持WebFlux,需要配合spring-boot-starter-webflux 依赖触发sentinel-starter中WebFlux相关的自动化配置
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(ServiceApplication.class, args);
}
}
@RestController
public class TestController {
@GetMapping("/mono")
@SentinelResource("hello")
public Mono<String> mono() {
return Mono.just("simple string")
.transform(new SentinelReactorTransformer<>("otherResourceName"));
}
}
Sentinel控制台(监控)
Sentinel控制台提供一个轻量级的控制台。它提供机器发现、单机资源实时监控、集群资源汇总(单机和集群),以及规则管理的功能;供机器发现以及健康情况管理、监控,规则管理和推送的功能。只需要对应用进行简单的配置,就可以使用这些功能。
注意:集群资源汇总仅支持500台以下的应用集群,有大概1 - 2秒的延时
Sentinel控制台功能
(1)查看机器列表以及健康情况
收集Sentinel客户端发送的心跳包,用于判断机器是否在线
(2)监控(单机和集群聚合)
通过Sentinel客户端暴露的监控API,定期拉取并且聚合应用监控信息,最终可以实现秒级的实时监控
(3)规则管理和推送
统一管理推送规则
(4)鉴权
生产环境中鉴权非常重要。这里每个开发者需要根据自己的实际情况进行定制
①:从Sentinel 1.5.0开始
Sentinel控制台提供通用的鉴权接口AuthService,用户可根据需求自行实现
②:从Sentinel 1.6.0起
Sentinel控制台引入基本的登录功能,默认用户名和密码都是sentinel。该鉴权能力非常基础,生产环境使用建议根据安全需要自行改造
(1)运行命令参数进行配置
参数 | 描述 |
---|---|
-Dsentinel.dashboard.auth.username=sentinel | 用于指定控制台的登录用户名为sentinel |
-Dsentinel.dashboard.auth.password=123456 | 用于指定控制台的登录密码为123456;如果省略这两个参数,默认用户和密码均为 sentinel |
-Dserver.servlet.session.timeout=7200 | 用于指定Spring Boot服务端session的过期时间,如7200表示7200秒;60m表示60分钟,默认为30分钟 |
(2)同样也可以直接在properties/yml文件中进行配置
注意:部署多台控制台时,session默认不会在各实例之间共享,这一块需要自行改造
使用Sentinel控制台
注意:Sentinel控制台目前仅支持单机部署。Sentinel控制台项目提供Sentinel功能全集示例,不作为开箱即用的生产环境控制台,若希望在生产环境使用请根据文档自行进行定制和改造。
(1)获取控制台
①从release页面下载最新版本的控制台jar包
地址:https://github.com/alibaba/Sentinel/releases
②从最新版本的源码自行构建Sentinel控制台:
(1)下载控制台工程
(2)使用以下命令将代码打包成一个jar: mvn clean package
(2)启动控制台
Sentinel控制台是一个标准的Spring Boot应用,以Spring Boot的方式运行jar包即可
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
如若8080端口冲突,可使用“-Dserver.port=新端口”进行设置
从Sentinel 1.6.0起,Sentinel控制台引入基本的登录功能,默认用户名和密码都是sentinel
配置控制台信息
除了修改JVM参数,也可以通过配置文件取得同样的效果。
注意:若应用为Spring Boot或Spring Cloud应用,可以通过Spring配置文件来指定配置
application.yml
spring:
cloud:
sentinel:
transport:
port: 8719
dashboard: localhost:8080
这里的spring.cloud.sentinel.transport.port端口配置会在应用对应的机器上启动一个Http Server,该Server会与Sentinel控制台做交互。比如Sentinel控制台添加了1个限流规则,会把规则数据push给这个Http Server接收,Http Server再将规则注册到Sentinel中
(3)客户端接入控制台
控制台启动后,客户端需要接入到控制台
1.导入依赖
Sentinel提供对所有资源的实时监控。如果需要实时监控,客户端需要引入Transport模块来与Sentinel控制台进行通信。
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>x.y.z</version>
</dependency>
引入上述依赖后,客户端便会主动连接Sentinel控制台。通过Sentinel控制台 即可查看客户端的实时监控。
2.配置客户端启动参数
启动时加入JVM参数“-Dcsp.sentinel.dashboard.server=consoleIp:port”指定控制台地址和端口。若启动多个应用,则需要通过“-Dcsp.sentinel.api.port=xxxx”指定客户端监控API的端口(默认8719)。
从1.6.3版本开始。控制台支持网关流控规则管理。需要在接入端添加“-Dcsp.sentinel.app.type=1”启动参数以将服务标记为API Gateway,在接入控制台时服务会自动注册为网关类型,然后在控制台配置网关规则和API分组。
3.触发客户端初始化
确保客户端有访问量,Sentinel会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包。
注意:还需要根据应用类型和接入方式引入对应的适配依赖(transport),否则即使有访问量也不能被Sentinel统计。
4.查看机器列表以及健康情况
当在机器列表中看到您的机器,就代表着已经成功接入控制台;如果没有看到机器,请检查配置,并通过${user.home}/logs/csp/sentinel-record.log.xxx日志来排查原因。
注意:实时监控仅存储5分钟以内的数据,如果需要持久化,需要通过调用实时监控接口来定制。
Spring AOP
若应用使用了Spring AOP(无论是Spring Boot还是传统Spring应用),都需要通过配置的方式将SentinelResourceAspect注册为一个Spring Bean:
@Configuration
public class SentinelAspectConfiguration {
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
}
WebFlux中使用Sentinel
Sentinel目前已经支持WebFlux,需要配合spring-boot-starter-webflux依赖触发sentinel-starter中WebFlux相关的自动化配置。
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(ServiceApplication.class, args);
}
}
@RestController
public class TestController {
@GetMapping("/mono")
@SentinelResource("hello")
public Mono<String> mono() {
return Mono.just("simple string")
.transform(new SentinelReactorTransformer<>("otherResourceName"));
}
}
Sentinel控制台配置项
控制台的一些特性可以通过配置项来进行配置,配置项主要有两个来源:System.getProperty()和System.getenv(),同时存在时后者(环境变量)可以覆盖前者(Java方式)
通过环境变量进行配置时,因为不支持“.”所以需要将其更换为“_”
配置项 | 描述 |
---|---|
auth.enabled | 是否开启登录鉴权,仅用于日常测试,生产上不建议关闭。默认值true |
前缀“sentinel.dashboard.”
配置项 | 描述 |
---|---|
auth.username | 登录控制台的用户名。默认为sentinel |
auth.password | 录控制台的密码。默认为sentinel |
app.hideAppNoMachineMillis | 是否隐藏无健康节点的应用,距离最近一次主机心跳时间的毫秒数,默认关闭(0),最小值(60000) |
removeAppNoMachineMillis | 是否自动删除无健康节点的应用,距离最近一次其下节点的心跳时间毫秒数,默认关闭(0),最小值(120000) |
unhealthyMachineMillis | 主机失联判定,不可关闭。默认值(60000),最小值(30000) |
autoRemoveMachineMillis | 距离最近心跳时间超过指定时间是否自动删除失联节点,默认关闭(0),最小值(300000) |
配置项 | 描述 |
---|---|
server.servlet.session.cookie.name | 控制台应用的cookie名称,可单独设置避免同一域名下cookie名冲突。默认值(entinel_dashboard_cookies) |
使用配置示例:
#命令行方式
java -Dsentinel.dashboard.app.hideAppNoMachineMillis=60000
#Java方式
System.setProperty("sentinel.dashboard.app.hideAppNoMachineMillis", "60000");
#环境变量方式
sentinel_dashboard_app_hideAppNoMachineMillis=60000
Sentinel对外暴露的Endpoint
Sentinel内部提供了一个Endpoint(端点),对应的endpoint id为sentinel
Endpoint暴露的json中包含了多种属性:
属性 | 描述 |
---|---|
appName | 应用名 |
logDir | 日志所在目录 |
logUsePid | 日志文件名是否带上进程id |
blockPage | 限流block之后跳转的页面 |
metricsFileSize | metrics文件的大小 |
metricsFileCharset | metrics文件对应的字符集 |
totalMetricsFileCount | metrics最多保留的文件数 |
consoleServer | sentinel dashboard地址 |
clientIp | 客户端IP |
heartbeatIntervalMs | 客户端跟dashboard的心跳间隔时间 |
clientPort | 客户端需要暴露的端口跟dashboard进行交互 |
coldFactor | 冷启动因子 |
filter | CommonFilter相关的属性。比如order、urlPatterns以及enable |
datasource | 客户端配置的数据源信息 |
rules | 客户端生效的规则,内部含有flowRules、degradeRules、systemRules、authorityRule、paramFlowRule |