随着微服务的普及,服务调用的稳定性变得越来越重要。Sentinel以“流量”为切入点,在流量控制、断路、负载保护等多个领域开展业务,保障业务可靠性。
哨兵具有以下特点:
如果您想在项目中使用 Sentinel,请使用组 ID 为com.alibaba.cloud
和工件 ID 为的启动器spring-cloud-starter-alibaba-sentinel
。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
以下是如何使用 Sentinel 的简单示例:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(ServiceApplication.class, args);
}
}
@RestController
public class TestController {
@GetMapping(value = "/hello")
@SentinelResource("hello")
public String hello() {
return "Hello Sentinel";
}
}
@SentinelResource 注释用于识别资源是速率限制还是降级。在上面的示例中,注解的 ‘hello’ 属性指的是资源名称。
@SentinelResource还提供了属性,例如blockHandler
,blockHandlerClass
,和fallback
,以确定速率限制或降解操作。有关更多详细信息,请参阅 Sentinel 注释支持。
上面的例子都是在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仪表板是一个轻量级控制台,提供机器发现、单机资源监控、集群资源数据概览、规则管理等功能。要使用这些功能,您只需完成几个步骤。
注意:集群的统计概览仅支持节点数少于 500 的集群,延迟大约为 1 到 2 秒。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NGKANDS2-1644989237558)(https://github.com/alibaba/Sentinel/wiki/image/dashboard.png)]
图 3. Sentinel 仪表板
要使用 Sentinel 仪表板,只需完成以下 3 个步骤。
您可以从Release Page下载最新的仪表板 JAR 文件。
您还可以获得最新的源代码来构建自己的 Sentinel 仪表板:
mvn clean package
Sentinel 仪表板是一个标准的 SpringBoot 应用程序,您可以在 Spring Boot 模式下运行 JAR 文件。
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
如果与 8080 端口有冲突,可以使用-Dserver.port=new port
定义一个新的端口。
应用程序.yml
spring:
cloud:
sentinel:
transport:
port: 8719
dashboard: localhost:8080
中指定的端口号spring.cloud.sentinel.transport.port
将在应用程序的相应服务器上启动一个 HTTP Server,该服务器将与 Sentinel 仪表板交互。例如,如果在 Sentinel 仪表板中添加了限速规则,则规则数据将被 HTTP 服务器推送和接收,然后将规则注册到 Sentinel。
有关 Sentinel 仪表板的更多信息,请参阅Sentinel 仪表板。
Sentinel 与OpenFeign组件兼容。要使用它,除了引入sentinel-starter
依赖外,还要完成以下2个步骤:
feign.sentinel.enabled=true
openfeign starter
依赖以触发和启用sentinel starter
:<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
这是一个简单的用法FeignClient
:
@FeignClient(name = "service-provider", fallback = EchoServiceFallback.class, configuration = FeignConfiguration.class)
public interface EchoService {
@GetMapping(value = "/echo/{str}")
String echo(@PathVariable("str") String str);
}
class FeignConfiguration {
@Bean
public EchoServiceFallback echoServiceFallback() {
return new EchoServiceFallback();
}
}
class EchoServiceFallback implements EchoService {
@Override
public String echo(@PathVariable("str") String str) {
return "echo fallback";
}
}
接口中echo
方法对应的资源名称EchoService
为GET:http://service-provider/echo/{str}
.
Spring Cloud Alibaba Sentinel 支持使用 Sentinel 保护RestTemplate
服务调用。为此,您需要在构造bean@SentinelRestTemplate
时添加注解。RestTemplate
@Bean
@SentinelRestTemplate(blockHandler = "handleException", blockHandlerClass = ExceptionUtil.class)
public RestTemplate restTemplate() {
return new RestTemplate();
}
@SentinelRestTemplate
注解的属性支持流控( blockHandler
, blockHandlerClass
)和断路(fallback
, fallbackClass
)。
blockHandler
orfallback
是 or 的blockHandlerClass
静态方法fallbackClass
。
方法 in 的参数和返回值与@SentinelRestTemplate
相同org.springframework.http.client.ClientHttpRequestInterceptor#interceptor
,但多了一个参数BlockException
,用于 Sentinel 捕获异常。
上面的方法签名应该handleException
是ExceptionUtil
这样的:
public class ExceptionUtil {
public static ClientHttpResponse handleException(HttpRequest request, byte[] body, ClientHttpRequestExecution execution, BlockException exception) {
...
}
}
@SentinelRestTemplate
注释的属性是可选的。
RestTemplate request block by sentinel
当您使用RestTemplate
被 Sentinel 阻止时,它将返回。你可以用你自己的逻辑覆盖它。我们提供SentinelClientHttpResponse
处理响应。
Sentinel RestTemplate 为资源速率限制提供了两种粒度:
httpmethod:schema://host:port/path
: 协议、主机、端口和路径httpmethod:schema://host:port
: 协议、主机和端口SentinelProperties
提供datasource
属性来配置数据源。
例如配置4个数据源:
spring.cloud.sentinel.datasource.ds1.file.file=classpath: degraderule.json
spring.cloud.sentinel.datasource.ds1.file.rule-type=flow
#spring.cloud.sentinel.datasource.ds1.file.file=classpath: flowrule.json
#spring.cloud.sentinel.datasource.ds1.file.data-type=custom
#spring.cloud.sentinel.datasource.ds1.file.converter-class=JsonFlowRuleListConverter
#spring.cloud.sentinel.datasource.ds1.file.rule-type=flow
spring.cloud.sentinel.datasource.ds2.nacos.server-addr=localhost:8848
spring.cloud.sentinel.datasource.ds2.nacos.data-id=sentinel
spring.cloud.sentinel.datasource.ds2.nacos.group-id=DEFAULT_GROUP
spring.cloud.sentinel.datasource.ds2.nacos.data-type=json
spring.cloud.sentinel.datasource.ds2.nacos.rule-type=degrade
spring.cloud.sentinel.datasource.ds3.zk.path = /Sentinel-Demo/SYSTEM-CODE-DEMO-FLOW
spring.cloud.sentinel.datasource.ds3.zk.server-addr = localhost:2181
spring.cloud.sentinel.datasource.ds3.zk.rule-type=authority
spring.cloud.sentinel.datasource.ds4.apollo.namespace-name = application
spring.cloud.sentinel.datasource.ds4.apollo.flow-rules-key = sentinel
spring.cloud.sentinel.datasource.ds4.apollo.default-flow-rule-value = test
spring.cloud.sentinel.datasource.ds4.apollo.rule-type=param-flow
该方法遵循 Spring Cloud Stream Binder 的配置。TreeMap
用于内部存储,比较器为String.CASE_INSENSITIVE_ORDER
.
d1, ds2, ds3, ds4 是 的名称ReadableDataSource
,可以任意编码。, file
, zk
,指的是具体的数据源nacos
。apollo
后面的配置分别是这些数据源的具体配置。
每个数据源都有 3 个常见的配置项data-type
:converter-class
和rule-type
。
data-type
指Converter
. Spring Cloud Alibaba Sentinel 默认提供了两个嵌入值:json
和xml
(不指定默认为 json)。如果不想使用内嵌json
或者xml
Converter
,也可以填写,custom
表示自己定义Converter
,然后配置converter-class
。您需要为此配置指定类的完整路径。
rule-type
指数据源中的规则类型( flow
,degrade
,authority
,system
, param-flow
, gw-flow
, gw-api-group
)。
默认情况下不支持 XML 格式。要使其生效,您需要添加 jackson-dataformat-xml
依赖项。
要了解有关 Sentinel 中动态数据源如何工作的更多信息,请参阅动态规则扩展。
参考API 网关流控
如果要在 Zuul 中使用 Sentinel Starter,需要添加spring-cloud-alibaba-sentinel-gateway
依赖,并且需要添加spring-cloud-starter-netflix-zuul
依赖才能让网关模块中的 Zuul AutoConfiguration 类生效:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
参考API 网关流控
如果要在 Spring Cloud Gateway 中使用 Sentinel Starter,需要添加spring-cloud-alibaba-sentinel-gateway
依赖,添加spring-cloud-starter-gateway
依赖才能让模块中的 Spring Cloud Gateway AutoConfiguration 类生效:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
要为所有断路器提供默认配置,请创建一个Customizer
传递 SentinelCircuitBreakerFactory
或ReactiveSentinelCircuitBreakerFactory
. 该configureDefault
方法可用于提供默认配置。
@Bean
public Customizer<SentinelCircuitBreakerFactory> defaultCustomizer() {
return factory -> factory.configureDefault(id -> new SentinelConfigBuilder(id)
.build());
}
您可以选择通过 提供默认熔断规则SentinelConfigBuilder#rules(rules)
。您还可以选择稍后使用DegradeRuleManager.loadRules(rules)
Sentinel 的 API 或通过 Sentinel 仪表板在其他地方加载断路规则 。
@Bean
public Customizer<ReactiveSentinelCircuitBreakerFactory> defaultCustomizer() {
return factory -> factory.configureDefault(id -> new SentinelConfigBuilder(id)
.build());
}
与提供默认配置类似,您可以创建一个Customizer
传递给 SentinelCircuitBreakerFactory
.
@Bean
public Customizer<SentinelCircuitBreakerFactory> slowCustomizer() {
String slowId = "slow";
List<DegradeRule> rules = Collections.singletonList(
new DegradeRule(slowId).setGrade(RuleConstant.DEGRADE_GRADE_RT)
.setCount(100)
.setTimeWindow(10)
);
return factory -> factory.configure(builder -> builder.rules(rules), slowId);
}
@Bean
public Customizer<ReactiveSentinelCircuitBreakerFactory> customizer() {
List<DegradeRule> rules = Collections.singletonList(
new DegradeRule().setGrade(RuleConstant.DEGRADE_GRADE_RT)
.setCount(100)
.setTimeWindow(10)
);
return factory -> factory.configure(builder -> builder.rules(rules), "foo", "bar");
}
Sentinel 在内部提供一个 Endpoint,其对应的端点 id 为sentinel
.
端点暴露的 json 包含多个属性:
以下显示了服务实例如何访问 Endpoint:
{
"blockPage": null,
"appName": "sentinel-example",
"consoleServer": "localhost:8080",
"coldFactor": "3",
"rules": {
"flowRules": [{
"resource": "GET:http://www.taobao.com",
"limitApp": "default",
"grade": 1,
"count": 0.0,
"strategy": 0,
"refResource": null,
"controlBehavior": 0,
"warmUpPeriodSec": 10,
"maxQueueingTimeMs": 500,
"clusterMode": false,
"clusterConfig": null
}, {
"resource": "/test",
"limitApp": "default",
"grade": 1,
"count": 0.0,
"strategy": 0,
"refResource": null,
"controlBehavior": 0,
"warmUpPeriodSec": 10,
"maxQueueingTimeMs": 500,
"clusterMode": false,
"clusterConfig": null
}, {
"resource": "/hello",
"limitApp": "default",
"grade": 1,
"count": 1.0,
"strategy": 0,
"refResource": null,
"controlBehavior": 0,
"warmUpPeriodSec": 10,
"maxQueueingTimeMs": 500,
"clusterMode": false,
"clusterConfig": null
}]
},
"metricsFileCharset": "UTF-8",
"filter": {
"order": -2147483648,
"urlPatterns": ["/*"],
"enabled": true
},
"totalMetricsFileCount": 6,
"datasource": {
"ds1": {
"file": {
"dataType": "json",
"ruleType": "FLOW",
"converterClass": null,
"file": "...",
"charset": "utf-8",
"recommendRefreshMs": 3000,
"bufSize": 1048576
},
"nacos": null,
"zk": null,
"apollo": null,
"redis": null
}
},
"clientIp": "30.5.121.91",
"clientPort": "8719",
"logUsePid": false,
"metricsFileSize": 52428800,
"logDir": "...",
"heartbeatIntervalMs": 10000
}
下表显示,当 中存在对应的 bean 类型时ApplicationContext
,会采取一些动作:
现有 Bean 类型 | 行动 | 功能 |
---|---|---|
UrlCleaner | WebCallbackManager.setUrlCleaner(urlCleaner) | 资源清理(resource(例如,将/foo/:id的所有URL归类到/foo/*资源)) |
UrlBlockHandler | WebCallbackManager.setUrlBlockHandler(urlBlockHandler) | 自定义限速逻辑 |
RequestOriginParser | WebCallbackManager.setRequestOriginParser(requestOriginParser) | 设置原点 |
Spring Cloud Alibaba Sentinel 的所有配置如下表所示:
配置 | 描述 | 默认值 |
---|---|---|
spring.application.name 或者 project.name | 哨兵项目名称 | |
spring.cloud.sentinel.enabled | Sentinel 自动配置是否生效 | 真的 |
spring.cloud.sentinel.eager | 是否提前触发 Sentinel 初始化 | 错误的 |
spring.cloud.sentinel.transport.port | 应用程序与 Sentinel 仪表板交互的端口。使用此端口的 HTTP 服务器将在应用程序中启动 | 8719 |
spring.cloud.sentinel.transport.dashboard | Sentinel 仪表板地址 | |
spring.cloud.sentinel.transport.heartbeatIntervalMs | 应用程序和 Sentinel 仪表板之间的检测信号间隔 | |
spring.cloud.sentinel.transport.client-ip | 此配置的客户端 IP 将注册到 Sentinel Server 端。 | |
spring.cloud.sentinel.filter.order | Servlet过滤器的加载顺序。过滤器将在 Starter 中构建 | 整数.MIN_VALUE |
spring.cloud.sentinel.filter.url-patterns | 数据类型为数组。指 Servlet Filter ULR 模式的集合 | /* |
spring.cloud.sentinel.filter.enabled | 启用实例 CommonFilter | 真的 |
spring.cloud.sentinel.metric.charset | 度量文件字符集 | UTF-8 |
spring.cloud.sentinel.metric.fileSingleSize | Sentinel metric 单个文件大小 | |
spring.cloud.sentinel.metric.fileTotalCount | 哨兵指标总文件数 | |
spring.cloud.sentinel.log.dir | Sentinel 日志文件目录 | |
spring.cloud.sentinel.log.switch-pid | 如果 Sentinel 日志文件名需要 PID | 错误的 |
spring.cloud.sentinel.servlet.blockPage | 自定义重定向 URL。当速率受限时,请求将被重定向到预定义的 URL | |
spring.cloud.sentinel.flow.coldFactor | 冷因子 | 3 |
spring.cloud.sentinel.zuul.order.pre | SentinelZuulPreFilter 的顺序 | 10000 |
spring.cloud.sentinel.zuul.order.post | SentinelZuulPostFilter 的顺序 | 1000 |
spring.cloud.sentinel.zuul.order.error | SentinelZuulErrorFilter 的顺序 | -1 |
spring.cloud.sentinel.scg.fallback.mode | Spring Cloud Gateway 断路后的响应方式(选择redirect 或response ) | |
spring.cloud.sentinel.scg.fallback.redirect | Spring Cloud Gateway 响应方式为 ‘redirect’ 方式对应的重定向 URL | |
spring.cloud.sentinel.scg.fallback.response-body | Spring Cloud Gateway 响应模式为响应模式对应的响应内容 | |
spring.cloud.sentinel.scg.fallback.response-status | Spring Cloud Gateway 响应模式为’response’模式对应的响应码 | 429 |
spring.cloud.sentinel.scg.fallback.content-type | Spring Cloud Gateway 响应模式是与“响应”模式对应的内容类型。 | 应用程序/json |