目录
2. Spring Cloud Alibaba Nacos(服务注册与发现)
3. Spring Cloud Alibaba Nacos Config(分布式配置)
4.Spring Cloud Ailibaba Sentinel(限流)
5. Spring Cloud Ailibaba Sentinel支持OpenFeign、RestTemplate(远程调用)及动态数据源
6. Spring Cloud Ailibaba Geteway与Zuul(服务网关)
7. Spring Cloud Ailibaba Seata(分布式事务)
9. Spring Cloud Ailibaba RocketMQ(分布式消息系统)
Spring Cloud Ailibaba Sentinel(限流)
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基本使用
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:标识资源是否被限流、降级
@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 |