Alibaba Sentinel知识图谱
2021-06-23 17:24:11 6 举报AI智能生成
阿里巴巴Sentinel知识图谱
知识图谱
思维导图
模版推荐
作者其他创作
大纲/内容
快速使用
使用介绍<br>
Sentinel 可以简单的分为 Sentinel 核心库和 Dashboard。核心库不依赖 Dashboard,但是结合 Dashboard 可以取得最好的效果。
资源可以是任何东西,服务,服务里的方法,甚至是一段代码。使用 Sentinel 来进行资源保护,主要分为几个步骤:<br><ol><li>定义资源</li><li>定义规则</li><li>检验规则是否生效</li></ol>
先把可能需要保护的资源定义好,之后再配置规则。也可以理解为,只要有了资源,我们就可以在任何时候灵活地定义各种流量控制规则。在编码的时候,只需要考虑这个代码是否需要保护,如果需要保护,就将之定义为一个资源。
引入依赖<br>
<dependency><br> <groupId>com.alibaba.csp</groupId><br> <artifactId>sentinel-core</artifactId><br> <version>1.8.1</version><br></dependency><br>
定义资源
代码方式
把需要控制流量的代码用 Sentinel API SphU.entry("HelloWorld") 和 entry.exit() 包围起来即可。在下面的例子中,我们将 System.out.println("hello world"); 作为资源(被保护的逻辑),用 API 包装起来。参考代码如下:
public static void main(String[] args) {<br> // 配置规则.<br> initFlowRules();<br> while (true) {<br> // 1.5.0 版本开始可以直接利用 try-with-resources 特性<br> try (Entry entry = SphU.entry("HelloWorld")) {<br> // 被保护的逻辑<br> System.out.println("hello world");<br> } catch (BlockException ex) {<br> // 处理被流控的逻辑<br> System.out.println("blocked!");<br> }<br> }<br>}<br>
注解方式
Sentinel 提供了 @SentinelResource 注解用于定义资源,并提供了 AspectJ 的扩展用于自动定义资源、处理 BlockException 等。使用 Sentinel Annotation AspectJ Extension 的时候需要引入以下依赖:<br><dependency><br> <groupId>com.alibaba.csp</groupId><br> <artifactId>sentinel-annotation-aspectj</artifactId><br> <version>x.y.z</version><br></dependency><br><br>
@SentinelResource("HelloWorld")<br>public void helloWorld() {<br> // 资源中的逻辑<br> System.out.println("hello world");<br>}
注解支持模块需要配合 Spring AOP 或者 AspectJ 一起使用。
注解方式埋点不支持 private 方法。
@SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。 @SentinelResource 注解包含以下属性:<br><br><ul><li>value:资源名称,必需项(不能为空)</li><li>entryType:entry 类型,可选项(默认为 EntryType.OUT)</li><li>blockHandler / blockHandlerClass: blockHandler 对应处理 BlockException 的函数名称,可选项。blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。</li><li><span style="font-size: inherit;">fallback / fallbackClass:fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:</span></li></ul><span style="font-size: inherit;"> 1. 返回值类型必须与原函数返回值类型一致;</span><br><span style="font-size: inherit;"> 2. 方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。</span><br><span style="font-size: inherit;"> 3. fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。</span><br><ul><li><span style="font-size: inherit;">defaultFallback(since 1.6.0):默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。defaultFallback 函数签名要求:</span></li></ul><span style="font-size: inherit;"> 1. 返回值类型必须与原函数返回值类型一致;</span><br><span style="font-size: inherit;"> 2. 方法参数列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。</span><br><span style="font-size: inherit;"> 3. defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。</span><br><ul><li>exceptionsToIgnore(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。</li></ul><br>
主流框架的默认适配
Spring Cloud Alibaba Sentinel
使用 group ID 为 com.alibaba.cloud 和 artifact ID 为 spring-cloud-starter-alibaba-sentinel 的 starter。<br><dependency><br> <groupId>com.alibaba.cloud</groupId><br> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId><br></dependency><br>
demo示例
@SentinelResource 注解用来标识资源是否被限流、降级。上述例子上该注解的属性 sayHello 表示资源名。<br><br>@SentinelResource 还提供了其它额外的属性如 blockHandler,blockHandlerClass,fallback 用于表示限流或降级的操作(注意有方法签名要求),更多内容可以参考 Sentinel 注解支持文档(https://github.com/alibaba/Sentinel/wiki/%E6%B3%A8%E8%A7%A3%E6%94%AF%E6%8C%81)。若不配置 blockHandler、fallback 等函数,则被流控降级时方法会直接抛出对应的 BlockException;若方法未定义 throws BlockException 则会被 JVM 包装一层 <br>UndeclaredThrowableException。<br><br><b><font color="#d32f2f">注:</font></b>一般推荐将 @SentinelResource 注解加到服务实现上,而在 Web 层直接使用 Spring Cloud Alibaba 自带的 Web 埋点适配。Sentinel Web 适配同样支持配置自定义流控处理逻辑<br>
Sentinel 目前已经支持 Spring WebFlux,需要配合 spring-boot-starter-webflux 依赖触发 sentinel-starter 中 WebFlux 相关的自动化配置。
webflux demo示例
当 Spring WebFlux 应用接入 Sentinel starter 后,所有的 URL 就自动成为 Sentinel 中的埋点资源,可以针对某个 URL 进行流控
feign
Sentinel 适配了 Feign 组件。如果想使用,除了引入 spring-cloud-starter-alibaba-sentinel 的依赖外还需要 2 个步骤:<br><br><ul><li>配置文件打开 Sentinel 对 Feign 的支持:feign.sentinel.enabled=true</li><li>加入 spring-cloud-starter-openfeign 依赖使 Sentinel starter 中的自动化配置类生效:<br><dependency><br> <groupId>org.springframework.cloud</groupId><br> <artifactId>spring-cloud-starter-openfeign</artifactId><br></dependency><br></li></ul><br>
@FeignClient(name = "service-provider", fallback = EchoServiceFallback.class, configuration = FeignConfiguration.class)<br>public interface EchoService {<br> @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)<br> String echo(@PathVariable("str") String str);<br>}<br><br>class FeignConfiguration {<br> @Bean<br> public EchoServiceFallback echoServiceFallback() {<br> return new EchoServiceFallback();<br> }<br>}<br><br>class EchoServiceFallback implements EchoService {<br> @Override<br> public String echo(@PathVariable("str") String str) {<br> return "echo fallback";<br> }<br>}<br>
Note<br>Feign 对应的接口中的资源名策略定义:httpmethod:protocol://requesturl。@FeignClient 注解中的所有属性,Sentinel 都做了兼容。<br>EchoService 接口中方法 echo 对应的资源名为 GET:http://service-provider/echo/{str}。<br>
RestTemplate
Spring Cloud Alibaba Sentinel 支持对 RestTemplate 的服务调用使用 Sentinel 进行保护,在构造 RestTemplate bean的时候需要加上 @SentinelRestTemplate 注解。
@Bean<br>@SentinelRestTemplate(blockHandler = "handleException", blockHandlerClass = ExceptionUtil.class)<br>public RestTemplate restTemplate() {<br> return new RestTemplate();<br>}
@SentinelRestTemplate 注解的属性支持限流(blockHandler, blockHandlerClass)和降级(fallback, fallbackClass)的处理。<br><br>其中 blockHandler 或 fallback 属性对应的方法必须是对应 blockHandlerClass 或 fallbackClass 属性中的静态方法。<br><br>该方法的参数跟返回值跟 org.springframework.http.client.ClientHttpRequestInterceptor#interceptor 方法一致,其中参数多出了一个 BlockException 参数用于获取 Sentinel 捕获的异常。
比如上述 @SentinelRestTemplate 注解中 ExceptionUtil 的 handleException 属性对应的方法声明如下:<br>public class ExceptionUtil {<br> public static ClientHttpResponse handleException(HttpRequest request, byte[] body, ClientHttpRequestExecution e xecution, BlockException <br> exception) {<br> ...<br> }<br>}<br>
应用启动的时候会检查 @SentinelRestTemplate 注解对应的限流或降级方法是否存在,如不存在会抛出异常
@SentinelRestTemplate 注解的限流(blockHandler, blockHandlerClass)和降级(fallback, fallbackClass)属性不强制填写。<br><br>当使用 RestTemplate 调用被 Sentinel 熔断后,会返回 RestTemplate request block by sentinel 信息,或者也可以编写对应的方法自行处理返回信息。这里提供了 SentinelClientHttpResponse 用于构造返回信息。<br><br>Sentinel RestTemplate 限流的资源规则提供两种粒度:<br><ul><li>httpmethod:schema://host:port/path:协议、主机、端口和路径</li><li>httpmethod:schema://host:port:协议、主机和端口</li></ul>
Endpoint
在使用 Endpoint 特性之前需要在 Maven 中添加 spring-boot-starter-actuator 依赖,并在配置中允许 Endpoints 的访问。<br><ul><li>Spring Boot 1.x 中添加配置 management.security.enabled=false。暴露的 endpoint 路径为 /sentinel</li><li>Spring Boot 2.x 中添加配置 management.endpoints.web.exposure.include=*。暴露的 endpoint 路径为 /actuator/sentinel</li></ul><br>Sentinel Endpoint 里暴露的信息非常有用。包括当前应用的所有规则信息、日志目录、当前实例的 IP,Sentinel Dashboard 地址,Block Page,应用与 Sentinel Dashboard 的心跳频率等等信息。<br>
配置
下表显示当应用的 ApplicationContext 中存在对应的Bean的类型时,会进行自动化设置:
Spring Cloud Alibaba Sentinel 提供了这些配置选项:
<br>
<b><font color="#d32f2f">官方文档地址: <br><ul><li><b><font color="#d32f2f">https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel</font></b></li><li><b><font color="#d32f2f">https://sentinelguard.io/zh-cn/docs/open-source-framework-integrations.html</font></b></li></ul></font></b>
API Gateway 适配
Spring Cloud Gateway
从 1.6.0 版本开始,Sentinel 提供了 Spring Cloud Gateway 的适配模块,可以提供两种资源维度的限流:<br><ul><li>route 维度:即在 Spring 配置文件中配置的路由条目,资源名为对应的 routeId</li><li>自定义 API 维度:用户可以利用 Sentinel 提供的 API 来自定义一些 API 分组</li></ul>
<dependency><br> <groupId>com.alibaba.csp</groupId><br> <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId><br> <version>x.y.z</version><br></dependency>
使用时只需注入对应的 SentinelGatewayFilter 实例以及 SentinelGatewayBlockExceptionHandler 实例即可。比如:
@Configuration<br>public class GatewayConfiguration {<br><br> private final List<ViewResolver> viewResolvers;<br> private final ServerCodecConfigurer serverCodecConfigurer;<br><br> public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,<br> ServerCodecConfigurer serverCodecConfigurer) {<br> this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);<br> this.serverCodecConfigurer = serverCodecConfigurer;<br> }<br><br> @Bean<br> @Order(Ordered.HIGHEST_PRECEDENCE)<br> public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {<br> // Register the block exception handler for Spring Cloud Gateway.<br> return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);<br> }<br><br> @Bean<br> @Order(-1)<br> public GlobalFilter sentinelGatewayFilter() {<br> return new SentinelGatewayFilter();<br> }<br>}
server:<br> port: 8090<br>spring:<br> application:<br> name: spring-cloud-gateway<br> cloud:<br> gateway:<br> enabled: true<br> discovery:<br> locator:<br> lower-case-service-id: true<br> routes:<br> # Add your routes here.<br> - id: product_route<br> uri: lb://product<br> predicates:<br> - Path=/product/**<br> - id: httpbin_route<br> uri: https://httpbin.org<br> predicates:<br> - Path=/httpbin/**<br> filters:<br> - RewritePath=/httpbin/(?<segment>.*), /$\{segment}<br>
自定义了一些 API 分组:<br>private void initCustomizedApis() {<br> Set<ApiDefinition> definitions = new HashSet<>();<br> ApiDefinition api1 = new ApiDefinition("some_customized_api")<br> .setPredicateItems(new HashSet<ApiPredicateItem>() {{<br> add(new ApiPathPredicateItem().setPattern("/product/baz"));<br> add(new ApiPathPredicateItem().setPattern("/product/foo/**")<br> .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));<br> }});<br> ApiDefinition api2 = new ApiDefinition("another_customized_api")<br> .setPredicateItems(new HashSet<ApiPredicateItem>() {{<br> add(new ApiPathPredicateItem().setPattern("/ahas"));<br> }});<br> definitions.add(api1);<br> definitions.add(api2);<br> GatewayApiDefinitionManager.loadApiDefinitions(definitions);<br>}<br>
那么这里面的 route ID(如 product_route)和 API name(如 some_customized_api)都会被标识为 Sentinel 的资源。比如访问网关的 URL 为 http://localhost:8090/product/foo/22 的时候,对应的统计会加到 product_route 和 some_customized_api 这两个资源上面,而 http://localhost:8090/httpbin/json 只会对应到 httpbin_route 资源上面。<br><br>您可以在 GatewayCallbackManager 注册回调进行定制:<br><br>setBlockHandler:注册函数用于实现自定义的逻辑处理被限流的请求,对应接口为 BlockRequestHandler。默认实现为 DefaultBlockRequestHandler,当被限流时会返回类似于下面的错误信息:Blocked by Sentinel: FlowException。
官方demo地址:https://github.com/alibaba/Sentinel/tree/master/sentinel-demo/sentinel-demo-spring-cloud-gateway
Spring Cloud Alibaba Sentinel 使用
若想跟 Sentinel Starter 配合使用,需要加上 spring-cloud-alibaba-sentinel-gateway 依赖,同时需要添加 spring-cloud-starter-gateway 依赖来让 spring-cloud-alibaba-sentinel-gateway 模块里的 Spring Cloud Gateway 自动化配置类生效:
<dependency><br> <groupId>com.alibaba.cloud</groupId><br> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId><br></dependency><br><br><dependency><br> <groupId>com.alibaba.cloud</groupId><br> <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId><br></dependency><br><br><dependency><br> <groupId>org.springframework.cloud</groupId><br> <artifactId>spring-cloud-starter-gateway</artifactId><br></dependency>
同时请将 spring.cloud.sentinel.filter.enabled 配置项置为 false(若在网关流控控制台上看到了 URL 资源,就是此配置项没有置为 false)。<br><br><b><font color="#d32f2f">*注意:</font></b>网关流控规则数据源类型是 gw-flow,若将网关流控规则数据源指定为 flow 则不生效。
Zuul 1.x
Sentinel 提供了 Zuul 1.x 的适配模块,可以为 Zuul Gateway 提供两种资源维度的限流:<br><ul><li>route 维度:即在 Spring 配置文件中配置的路由条目,资源名为对应的 route ID(对应 RequestContext 中的 proxy 字段)</li><li>自定义 API 维度:用户可以利用 Sentinel 提供的 API 来自定义一些 API 分组</li></ul>
<dependency><br> <groupId>com.alibaba.csp</groupId><br> <artifactId>sentinel-zuul-adapter</artifactId><br> <version>x.y.z</version><br></dependency>
如果您正在使用 Spring Cloud Zuul Starter,那么可以通过引入 spring-cloud-alibaba-sentinel-zuul 来更方便地整合 Sentinel。
Zuul 2.x
从 1.7.2 版本开始支持,需要 Java 8 及以上版本
Sentinel 提供了 Zuul 2.x 的适配模块,可以为 Zuul Gateway 提供两种资源维度的限流:<br><ul><li>route 维度:对应 SessionContext 中的 routeVIP</li><li>自定义 API 维度:用户可以利用 Sentinel 提供的 API 来自定义一些 API 分组</li></ul>
<dependency><br> <groupId>com.alibaba.csp</groupId><br> <artifactId>sentinel-zuul2-adapter</artifactId><br> <version>x.y.z</version><br></dependency>
官方文档地址:https://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81#zuul-2x
网关流控实现原理<br>
当通过 GatewayRuleManager 加载网关流控规则(GatewayFlowRule)时,无论是否针对请求属性进行限流,Sentinel 底层都会将网关流控规则转化为热点参数规则(ParamFlowRule),存储在 GatewayRuleManager 中,与正常的热点参数规则相隔离。转换时 Sentinel 会根据请求属性配置,为网关流控规则设置参数索引(idx),并同步到生成的热点参数规则中。
外部请求进入 API Gateway 时会经过 Sentinel 实现的 filter,其中会依次进行 路由/API 分组匹配、请求属性解析和参数组装。Sentinel 会根据配置的网关流控规则来解析请求属性,并依照参数索引顺序组装参数数组,最终传入 SphU.entry(res, args) 中。Sentinel API Gateway Adapter Common 模块向 Slot Chain 中添加了一个 GatewayFlowSlot,专门用来做网关规则的检查。GatewayFlowSlot 会从 GatewayRuleManager 中提取生成的热点参数规则,根据传入的参数依次进行规则检查。若某条规则不针对请求属性,则会在参数最后一个位置置入预设的常量,达到普通流控的效果。
Spring WebFlux
Sentinel 提供与 Spring WebFlux 的整合模块,从而 Reactive Web 应用也可以利用 Sentinel 的流控降级来保障稳定性。该整合模块基于 Sentinel Reactor Adapter 实现。
<dependency><br> <groupId>com.alibaba.csp</groupId><br> <artifactId>sentinel-spring-webflux-adapter</artifactId><br> <version>x.y.z</version><br></dependency>
使用时只需注入对应的 SentinelWebFluxFilter 实例以及 SentinelBlockExceptionHandler 实例即可。<br><br>@Configuration<br>public class WebFluxConfig {<br><br> private final List<ViewResolver> viewResolvers;<br> private final ServerCodecConfigurer serverCodecConfigurer;<br><br> public WebFluxConfig(ObjectProvider<List<ViewResolver>> viewResolversProvider,<br> ServerCodecConfigurer serverCodecConfigurer) {<br> this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);<br> this.serverCodecConfigurer = serverCodecConfigurer;<br> }<br><br> @Bean<br> @Order(-1)<br> public SentinelBlockExceptionHandler sentinelBlockExceptionHandler() {<br> // Register the block exception handler for Spring WebFlux.<br> return new SentinelBlockExceptionHandler(viewResolvers, serverCodecConfigurer);<br> }<br><br> @Bean<br> @Order(-1)<br> public SentinelWebFluxFilter sentinelWebFluxFilter() {<br> // Register the Sentinel WebFlux filter.<br> return new SentinelWebFluxFilter();<br> }<br>}<br>
可以在 WebFluxCallbackManager 注册回调进行定制:<br><br><ul><li>setBlockHandler:注册函数用于实现自定义的逻辑处理被限流的请求,对应接口为 BlockRequestHandler。默认实现为 DefaultBlockRequestHandler,当被限流时会返回类似于下面的错误信息:Blocked by Sentinel: FlowException。</li><li>setUrlCleaner:注册函数用于 Web 资源名的归一化。函数类型为 (ServerWebExchange, String) → String,对应含义为 (webExchange, originalUrl) → finalUrl。</li><li>setRequestOriginParser:注册函数用于从请求中解析请求来源。函数类型为 ServerWebExchange → String。</li></ul>
官方demo地址: https://github.com/alibaba/Sentinel/tree/master/sentinel-demo/sentinel-demo-spring-webflux
Dubbo
Sentinel 提供 Dubbo 的相关适配 Sentinel Dubbo Adapter,主要包括针对 Service Provider 和 Service Consumer 实现的 Filter。相关模块:<br><br><ul><li>sentinel-apache-dubbo-adapter(兼容 Apache Dubbo 2.7.x 及以上版本,自 Sentinel 1.5.1 开始支持)</li><li>sentinel-dubbo-adapter(兼容 Dubbo 2.6.x 版本)</li></ul>
<font color="#d32f2f">Apache Dubbo 2.7.x 及以上版本:</font><br><dependency><br> <groupId>com.alibaba.csp</groupId><br> <artifactId>sentinel-apache-dubbo-adapter</artifactId><br> <version>x.y.z</version><br></dependency><br><br><font color="#d32f2f">Dubbo 2.6.x 及以下版本:</font><br><dependency><br> <groupId>com.alibaba.csp</groupId><br> <artifactId>sentinel-dubbo-adapter</artifactId><br> <version>x.y.z</version><br></dependency>|<br><br>引入此依赖后,Dubbo 的服务接口和方法(包括调用端和服务端)就会成为 Sentinel 中的资源,在配置了规则后就可以自动享受到 Sentinel 的防护能力。<br>
<b><font color="#d32f2f">注:</font></b>若希望接入 Dashboard,请参考 接入控制台的步骤。只引入 Sentinel Dubbo Adapter 无法接入控制台!<br>若不希望开启 Sentinel Dubbo Adapter 中的某个 Filter,可以手动关闭对应的 Filter,比如:<br><!-- 关闭 Sentinel 对应的 Service Consumer Filter --><br><dubbo:consumer filter="-sentinel.dubbo.consumer.filter"/><br>
限流粒度可以是服务接口和服务方法两种粒度:<br><ul><li>服务接口:resourceName 为 接口全限定名,如 com.alibaba.csp.sentinel.demo.dubbo.FooService</li><li>服务方法:resourceName 为 接口全限定名:方法签名,如 com.alibaba.csp.sentinel.demo.dubbo.FooService:sayHello(java.lang.String)<br></li></ul>
Sentinel Dubbo Adapter 还支持配置全局的 fallback 函数,可以在 Dubbo 服务被限流/降级/负载保护的时候进行相应的 fallback 处理。用户只需要实现自定义的 DubboFallback 接口,并通过 DubboFallbackRegistry 注册即可。默认情况会直接将 BlockException 包装后抛出。同时,我们还可以配合 Dubbo 的 fallback 机制 来为降级的服务提供替代的实现。
官方demo地址: https://github.com/alibaba/Sentinel/tree/master/sentinel-demo/sentinel-demo-dubbo<br>
gRPC<br>
Sentinel 提供与 gRPC Java 的整合,以 gRPC ServerInterceptor 和 ClientInterceptor 的形式保护 gRPC 服务资源
<dependency><br> <groupId>com.alibaba.csp</groupId><br> <artifactId>sentinel-grpc-adapter</artifactId><br> <version>x.y.z</version><br></dependency>
在使用 Sentinel gRPC Adapter 时,只需要将对应的 Interceptor 注册至对应的客户端或服务端中。其中客户端的示例如下: <br><br>public class ServiceClient {<br><br> private final ManagedChannel channel;<br><br> ServiceClient(String host, int port) {<br> this.channel = ManagedChannelBuilder.forAddress(host, port)<br> .intercept(new SentinelGrpcClientInterceptor()) // 在此处注册拦截器<br> .build();<br> // 在此处初始化客户端 stub 类<br> }<br>}<br>
服务端的示例如下:<br>import io.grpc.Server;<br><br>Server server = ServerBuilder.forPort(port)<br> .addService(new MyServiceImpl()) // 添加自己的服务实现<br> .intercept(new SentinelGrpcServerInterceptor()) // 在此处注册拦截器<br> .build();<br>
Sentinel gRPC Adapter 目前只支持 unary call
HTTP Client 适配
Apache HttpClient
Sentinel 提供 Apache HttpClient 的适配模块 sentinel-apache-httpclient-adapter,可以针对 HTTP client 请求进行流控和熔断
<dependency><br> <groupId>com.alibaba.csp</groupId><br> <artifactId>sentinel-apache-httpclient-adapter</artifactId><br> <version>x.y.z</version><br></dependency>
从 Sentinel 1.8.0 版本开始支持。目前暂不支持 AsyncHttpClient<br>
OkHttp
Sentinel 提供 OkHttp 的适配模块 sentinel-okhttp-adapter,可以针对 HTTP client 请求进行流控和熔断
<dependency><br> <groupId>com.alibaba.csp</groupId><br> <artifactId>sentinel-okhttp-adapter</artifactId><br> <version>x.y.z</version><br></dependency><br>
从 Sentinel 1.8.0 版本开始支持。
Apache RocketMQ
定义规则
通过流控规则来指定允许该资源通过的请求次数,例如下面的代码定义了资源 HelloWorld 每秒最多只能通过 20 个请求。
private static void initFlowRules(){<br> List<FlowRule> rules = new ArrayList<>();<br> FlowRule rule = new FlowRule();<br> rule.setResource("HelloWorld");<br> rule.setGrade(RuleConstant.FLOW_GRADE_QPS);<br> // Set limit QPS to 20.<br> rule.setCount(20);<br> rules.add(rule);<br> FlowRuleManager.loadRules(rules);<br>}
检查效果
运行之后,可以在日志 ~/logs/csp/${appName}-metrics.log.xxx 里看到的输出:<br>
启动 Sentinel 控制台
Sentinel 开源控制台支持实时监控和规则管理<br>
(1)下载控制台 jar 包并在本地启动
(2)客户端接入控制台
1. 客户端需要引入 Transport 模块来与 Sentinel 控制台进行通信。您可以通过 pom.xml 引入 JAR 包:<br><br><dependency><br> <groupId>com.alibaba.csp</groupId><br> <artifactId>sentinel-transport-simple-http</artifactId><br> <version>1.8.1</version><br></dependency><br>
2. 启动时加入 JVM 参数 -Dcsp.sentinel.dashboard.server=consoleIp:port 指定控制台地址和端口
3. 确保应用端有访问量
核心类解析<br>
ProcessorSlotChain
Sentinel 的核心骨架,将不同的 Slot 按照顺序串在一起(责任链模式),从而将不同的功能(限流、降级、系统保护)组合在一起。slot chain 其实可以分为两部分:统计数据构建部分(statistic)和判断部分(rule checking),目前的设计是 one slot chain per resource,因为某些 slot 是 per resource 的(比如 NodeSelectorSlot)。
Context<br>
Context 代表调用链路上下文,贯穿一次调用链路中的所有 Entry。Context 维持着入口节点(entranceNode)、本次调用链路的 curNode、调用来源(origin)等信息。Context 名称即为调用链路入口名称。<br><br>Context 维持的方式:通过 ThreadLocal 传递,只有在入口 enter 的时候生效。由于 Context 是通过 ThreadLocal 传递的,因此对于异步调用链路,线程切换的时候会丢掉 Context,因此需要手动通过 ContextUtil.runOnContext(context, f) 来变换 context。
Entry
每一次资源调用都会创建一个 Entry。Entry 包含了资源名、curNode(当前统计节点)、originNode(来源统计节点)等信息。<br><br>CtEntry 为普通的 Entry,在调用 SphU.entry(xxx) 的时候创建。特性:Linked entry within current context(内部维护着 parent 和 child)<br><br><font color="#e57373">需要注意的一点:</font>CtEntry 构造函数中会做<b>调用链的变换</b>,即将当前 Entry 接到传入 Context 的调用链路上(setUpEntryFor)。<br>资源调用结束时需要 entry.exit()。exit 操作会过一遍 slot chain exit,恢复调用栈,exit context 然后清空 entry 中的 context 防止重复调用。<br>
Node
Sentinel 里面的各种种类的统计节点
<ul><li>StatisticNode:最为基础的统计节点,包含秒级和分钟级两个滑动窗口结构。</li><li>DefaultNode:链路节点,用于统计调用链路上某个资源的数据,维持树状结构。</li><li>ClusterNode:簇点,用于统计每个资源全局的数据(不区分调用链路),以及存放该资源的按来源区分的调用数据(类型为 StatisticNode)。特别地,Constants.ENTRY_NODE 节点用于统计全局的入口资源数据。</li><li>EntranceNode:入口节点,特殊的链路节点,对应某个 Context 入口的所有调用数据。Constants.ROOT 节点也是入口节点。</li></ul>
构建的时机
<ul><li>EntranceNode 在 ContextUtil.enter(xxx) 的时候就创建了,然后塞到 Context 里面。</li><li>NodeSelectorSlot:根据 context 创建 DefaultNode,然后 set curNode to context。</li><li>ClusterBuilderSlot:首先根据 resourceName 创建 ClusterNode,并且 set clusterNode to defaultNode;然后再根据 origin 创建来源节点(类型为 StatisticNode),并且 set originNode to curEntry。</li></ul>
Node 的维度
<ul><li>ClusterNode 的维度是 resource</li><li>DefaultNode 的维度是 resource * context,存在每个 NodeSelectorSlot 的 map 里面</li><li>EntranceNode 的维度是 context,存在 ContextUtil 类的 contextNameNodeMap 里面</li><li>来源节点(类型为 StatisticNode)的维度是 resource * origin,存在每个 ClusterNode 的 originCountMap 里面</li></ul>
StatisticSlot
StatisticSlot 是 Sentinel 最为重要的类之一,用于根据规则判断结果进行相应的统计操作。<br><br>entry 的时候:依次执行后面的判断 slot。每个 slot 触发流控的话会抛出异常(BlockException 的子类)。若有 BlockException 抛出,则记录 block 数据;若无异常抛出则算作可通过(pass),记录 pass 数据。<br><br>exit 的时候:若无 error(无论是业务异常还是流控异常),记录 complete(success)以及 RT,线程数-1。<br><br>记录数据的维度:线程数+1、记录当前 DefaultNode 数据、记录对应的 originNode 数据(若存在 origin)、累计 IN 统计数据(若流量类型为 IN)。
Sentinel 概念<br>
什么是Sentinel:随着分布式系统变得越来越流行,服务之间的可靠性变得比以往任何时候都更加重要。Sentinel是一个强大的流控组件,以“流”为切入点,涵盖流控、并发限制、熔断、自适应系统保护等多个领域,保障微服务的可靠性<br>
关键概念
资源<br>
资源是 Sentinel 中的一个关键概念。它可以是任何东西,例如服务、方法,甚至是代码片段。<br>一旦被 Sentinel API 包裹,就被定义为资源,可以申请 Sentinel 提供的保护。
规则<br>
Sentinel 保护资源的方式由规则定义,例如流量控制、并发和熔断规则。规则可以动态更改,并实时生效。
特点和原理<br>
流量控制<br>
Sentinel 提供了根据需要根据适当的形状处理随机传入请求的能力<br>
流量控制原理<br>
流量控制基于以下统计信息:<br> 1. 资源之间的调用链;<br> 2. 运行时指标,例如 QPS、响应时间和系统负载;<br> 3. 需要采取的行动,例如立即拒绝或排队。<br>Sentinel 允许应用程序以灵活的方式组合所有这些统计信息。<br>
熔断和并发
<b>断路:</b>断路用于检测故障,封装防止故障在维护过程中不断重复发生、临时外部系统故障或意外系统困难的逻辑。<br>为了解决这个问题,Hystrix选择使用线程和线程池来实现隔离。线程池的主要好处是隔离是彻底的,但它可能会带来额外的开销并导致相关场景ThreadLocal(例如 Spring 事务)出现问题。
Sentinel 实现断路<br>
最大并发限制
Sentinel 没有使用线程池,而是通过限制并发线程的数量(即信号量隔离)来减少不稳定资源的影响。<br><br>当资源的响应时间变长时,线程就会开始被占用。当线程数累积到一定数量时,将拒绝新传入的请求。反之,当资源恢复稳定后,占用的线程也会被释放,接受新的请求。<br><br>通过限制并发线程而不是线程池,您不再需要预先分配线程池的大小,从而避免排队、调度和上下文切换等计算开销。
断路<br>
除了限制并发性,根据响应时间对不稳定资源进行降级也是保证可靠性的有效方法。当资源的响应时间过长时,在指定的时间窗口内将拒绝对该资源的所有访问。
自适应系统保护
Sentinel 可用于在系统负载或 CPU 使用率过高的情况下保护您的服务器。它可以帮助您在系统负载和传入请求之间实现良好的平衡,并且可以非常快速地恢复系统
哨兵如何工作
在 Sentinel 里面,所有的资源都对应一个资源名称以及一个 Entry。Entry 可以通过对主流框架的适配自动创建,也可以通过注解的方式或调用 API 显式创建;每一个 Entry 创建的时候,也会创建一系列槽。这些槽有不同的职责,一些用于跟踪,一些用于收集和计算运行时信息,一些用于流量控制,一些用于断路,等等。您可以通过基于以下基本槽添加槽来自定义您自己的逻辑。<br>
NodeSelectorSlot(跟踪节点并在内存中形成调用树)<br>
ContextUtil.enter("entrance1", "appA");<br>Entry nodeA = SphU.entry("nodeA");<br>if (nodeA != null) {<br> nodeA.exit();<br>}<br>ContextUtil.exit();<br><br>上面的代码将在内存中生成以下结构<br><br> machine-root<br> / <br> /<br> EntranceNode1<br> /<br> / <br> DefaultNode(nodeA)<br>
每个DefaultNode都由上下文和资源名称标识。换句话说,一个资源 id 可能有多个DefaultNode由 中声明的条目名称区分的ContextUtil.enter(contextName)。
ContextUtil.enter("entrance1", "appA");<br> Entry nodeA = SphU.entry("nodeA");<br> if (nodeA != null) {<br> nodeA.exit();<br> }<br> ContextUtil.exit();<br> ContextUtil.enter("entrance2", "appA");<br> nodeA = SphU.entry("nodeA");<br> if (nodeA != null) {<br> nodeA.exit();<br> }<br> ContextUtil.exit();<br><br>上面的代码将在内存中生成以下结构:<br><br> machine-root<br> / \<br> / \<br> EntranceNode1 EntranceNode2<br> / \<br> / \<br> DefaultNode(nodeA) DefaultNode(nodeA)<br>
负责收集资源的路径,并将这些资源的调用路径,以树状结构存储起来,用于根据调用路径来限流降级 curl http://localhost:8719/tree?type=root。
ClusterNodeBuilderSlot(构建以资源命名的集群节点)<br>
则用于存储资源的统计信息以及调用者信息,例如该资源的 RT, QPS, thread count 等等,这些信息将用作为多维度限流,降级的依据。原始呼叫者的姓名由originin标记ContextUtil.enter(contextName, origin)。
可以通过调用以下 HTTP API 来显示信息: http://localhost:8719/origin?id=xxxx
StatisticSlot(收集运行时统计信息)<br>
1. ClusterNode(ResourceNode):一个资源的总统计; <br>2. 源节点:来自不同调用者的一个 ClusterNode 的统计信息; <br>3. DefaultNode:节点的条目,由上下文条目名称和资源ID标记;<br>4. 传入入口的总和统计。<br>
StatisticNode 由滑动窗口数据结构 (LeapArray) 支持:<br>
FlowSlot <br>
则用于根据预设的限流规则以及前面 slot 统计的状态,来进行流量控制;
这个 slot 主要根据预设的资源的统计信息,按照固定的次序,依次生效。如果一个资源对应两条或者多条流控规则,则会根据如下次序依次检验,直到全部通过或者有一个规则生效为止:<br><br><ol><li>指定应用生效的规则,即针对调用方限流的;</li><li>调用方为 other 的规则;</li><li>调用方为 default 的规则。</li></ol>
AuthoritySlot<br>
则根据配置的黑白名单和调用来源信息,来做黑白名单控制
DegradeSlot
则通过统计信息以及预设的规则,来做熔断降级;
这个 slot 主要针对资源的平均响应时间(RT)以及异常比率,来决定资源是否在接下来的时间被自动熔断掉。
SystemSlot<br>
则通过系统的状态,例如 load1 等,来控制总的入口流量
这个 slot 会根据对于当前系统的整体情况,对入口资源的调用进行动态调配。其原理是让入口的流量和当前系统的预计容量达到一个动态平衡。<br><br>注意系统规则只对入口流量起作用(调用类型为 EntryType.IN),对出口流量无效。可通过 SphU.entry(res, entryType) 指定调用类型,如果不指定,默认是EntryType.OUT。
ProcessorSlot
作为 SPI 接口进行扩展(1.7.2 版本以前 SlotChainBuilder 作为 SPI),使得 Slot Chain 具备了扩展的能力。可以自行加入自定义的 slot 并编排 slot 间的顺序,从而可以给 Sentinel 添加自定义的功能。
生态系统景观<br>
<b><font color="#d32f2f">git地址: https://github.com/alibaba/Sentinel/wiki</font></b>
流量控制<br>
FlowSlot 会根据 Sentinel 中收集的实时统计数据,使用预先设定的规则来决定是否应控制传入的请求。<br>一个资源可以有多个流控制规则。该FlowSlot直到其中一个被触发或所有规则都已经过去了会遍历这些规则。<br>一个流控规则主要由以下几项组成,您可以将不同的项组合起来,满足不同的流控需求。<br><br>1. resource:资源名称<br>2. count: 门槛<br>3. grade: 指标类型(QPS 或并发)<br>4. strategy: 根据调用关系(调用链)选择流控策略<br>5. controlBehavior: 流量整形的效果
线程/QPS 流量控制<br>
指标类型<br>
您可以通过QPS和concurrency进行控制。它由 中的grade字段定义FlowRule。并发线程计数和请求计数都是在运行时收集的。
并发
这种模式通常用于防止线程池被占用。如果调用需要很长时间才能完成,则在调用上阻塞的线程将会拥塞。响应时间越长,可能占用的线程就越多。<br><br>除了并发(又名信号量隔离)之外,还有其他方法可以实现这一点:线程池隔离。<br> <b>1. 线程池隔离:</b>分配托管线程池来处理不同的调用。当池中没有更多空闲线程时,请求被拒绝而不影响其他资源。当调用超过超时时间时,调用将被削减。<br> <b>2. 信号量隔离:</b>限制调用的并发数。<br>使用线程池的好处是可以通过预分配线程池来完全隔离业务逻辑。但它也给我们带来了上下文切换和额外线程的额外成本。如果传入的请求已经在一个单独的线程中处理,例如一个 servlet 请求,如果使用线程池模式,它几乎会使线程开销增加一倍。<br><br>所以我们推荐使用并发线程计数流量控制,它代表了轻量级的信号量隔离。<br>
QPS
当 QPS 超过阈值时,我们将采取行动来控制传入的请求,这可以通过配置 中的controlBehavior字段来完成FlowRule<br>
<b>立即拒绝</b> ( RuleConstant.CONTROL_BEHAVIOR_DEFAULT) :这是默认行为。超出的请求会立即被拒绝并抛出 FlowException。<br>
<b> 热身</b>(RuleConstant.CONTROL_BEHAVIOR_WARM_UP) : 如果系统使用率低了一段时间,但突然有大量请求进来,系统可能无法一次处理所有这些请求。但是,如果我们稳步增加传入请求并让系统预热,它可能最终能够处理所有请求。<br>可以通过在 中设置warmUpPeriodSec字段来配置此预热期FlowRule。<br>
<b>速率限制器 </b>( RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER) : 该策略严格控制请求之间的间隔。换句话说,它允许请求以统一的速率通过。<br>这个策略是漏桶的一个实现。它用于以稳定的速率处理请求,通常用于处理突发请求而不是拒绝它们。例如,消息突然流入。当大量请求同时到达时,系统可以以固定速率处理所有这些传入请求<br>
呼叫路径流量控制<br>(Flow Control by Call Path)
我们使用<b>NodeSelectorSlot</b>来建立资源的调用链,并<b>ClusterBuilderSlot</b>收集调用者的运行时统计数据。
按来电者(By caller)<br>
调用时ContextUtil.enter(resourceName, origin),该参数origin指示调用者的身份(如对端的服务名)。该ClusterBuilderSlot会收集这些信息,并用它来进行流量控制。
<br>
所述origin可以通过字段来定义limitApp在FlowRule。该字段具有以下值:<br><br>1. default: 没有具体的来电者。如果此资源的总值超过此规则中定义的阈值,则传入请求将被阻止。<br>2. <<origin>>:特定呼叫者已超过规则中定义的阈值。<br>3. other:此规则适用于来自origin该资源字段中未明确定义的调用者的请求。<br>
按入口(By entrance)<br>
路径保持在NodeSelectorSlot. 例如,资源节点可以来自 entry1 或 entry2。
<br>
按相关资源(By related resource)<br>
例如,两个资源将访问相同的数据库记录。ResourceA 将从数据库中读取记录,resourceB 将记录写入数据库。ResourceA 访问数据库的频率取决于ResourceB。我们可以通过配置ResourceA的规则与价值实现这个strategy字段RuleConstant.RELATE,以及价值ref_identity为ResourceB。
断路
断路器提供稳定性并防止分布式系统中的级联故障。<br>
<br>
断路器策略<br>
<b>慢请求比率:</b>通过慢请求比率进行断路。我们需要提供“上限响应时间”,RT 超过上限 RT 的请求将被记录为慢请求。<br>
<b>错误率:</b>按错误率(错误计数/总完成计数)进行断路。
<b>错误计数:</b>按异常数量进行断路。<br>
断路器状态变化观察器
EventObserverRegistry.getInstance().addStateChangeObserver("logging",<br> (prevState, newState, rule, snapshotValue) -> {<br> if (newState == State.OPEN) {<br> System.err.println(String.format("%s -> OPEN at %d, snapshotValue=%.2f", prevState.name(),<br> TimeUtil.currentTimeMillis(), snapshotValue));<br> } else {<br> System.err.println(String.format("%s -> %s at %d", prevState.name(), newState.name(),<br> TimeUtil.currentTimeMillis()));<br> }<br> });<br>
自适应系统保护
自适应系统保护在保证系统可靠性的前提下保持较高的系统吞吐量。<br>Sentinel 对系统负载保护的做法是load1作为发起流量控制的指标,允许通过的流量由处理请求的能力决定,包括响应时间和当前 QPS。<br>
全球保护项目有以下几种:<br> 1. 系统负载 (System load / load1)<br> 2. 系统 CPU 使用率(System CPU usage)<br> 3. 全局入站 QPS(Global inbound QPS) <br> 4. 全局平均响应时间(Global average response time)<br> 5. 全局最大并发(入站流量,Global max concurrency)<br>请注意,系统规则仅对<b>inbound traffic</b>( EntryType.IN)生效。<br>
Load Protection<br>
请求将在以下条件下被阻止:<br><br>当前系统负载(load1)超过阈值(highestSystemLoad);<br>当前并发请求超过估计容量 ( thread count > minRt * maxQps)
Global Metrics Protection<br>
我们有一个ENTRY_NODE记录全局指标(例如 inbound QPS、平均 RT 和线程数)的全局统计节点。<br>
指标(Metrics)<br>
Sentinel 提供实时指标,包括资源计数、响应时间、并发等。您可以在Sentinel-Dashboard上查看这些指标,但您也可以使用指标 API 来检索数据。<br><br>HTTP API 服务器的默认端口是8719,但您可以通过csp.sentinel.api.port属性项修改它。<br>
资源指标(Metrics of Resources)<br>
获取所有资源的实时指标
应用程序接口: GET /clusterNode
[ <br> { "avgRt" : 0.0 , //每秒平均响应时间<br> "blockRequest" : 0 , //每分钟的块数<br> "blockedQps" : 0.0 , //每秒的块数<br> "curThreadNum" : 0 , //当前并发<br> " passQps" : 1.0 , // 每秒成功退出计数<br> "passReqQps" : 1.0 , //每秒通过计数<br> "resourceName" : "/registry/machine" , 资源 名称<br> "timeStamp": 1529905824134, //时间戳<br> "totalQps" : 1.0 , // 每分钟的总请求数<br> "totalRequest" : 193 } , <br> ... . <br>]
按资源名称获取实时指标
运行命令 curl http://localhost:8719/cnode?id=xxxx查询指定的资源名称。参数id对应资源名称。支持模糊查询。
显示资源的源指标
命令: curl http://localhost:8719/origin?id=xxxx
调用链<br>
应用程序接口: GET /tree
历史资源指标
指标日志
资源指标日志在目录中生成:${home}\logs\csp\${appName}-${pid}-metrics.log.${date}.xx. 例如,日志文件名将是:app-3518-metrics.log.2018-06-22.1
块日志<br>
块日志将在 dir 中生成${home}\logs\csp\sentinel-block.log。如果没有发生阻塞,则不会生成日志。
指标日志获取 API
curl http://localhost:8719/metric?startTime=XXXX&endTime=XXXX
仪表盘(Dashboard)<br>
简介
Sentinel 提供了一个简单的独立仪表板,您可以在上面监控您的应用程序,并实时配置规则。它包括以下功能:<br> 1. 机器发现<br> 2. 单机或少于500个节点的集群的资源监控<br> 3. 规则管理
启动Dashboard
下载
https://github.com/alibaba/Sentinel/releases 下载最新的 Sentinel Dashboard jar<br>
运行<br>
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar<br>
-Dserver.port=8080 是 Sentinel Dashboard 的 HTTP 端口
应用<br>
<dependency><br> <groupId>com.alibaba.csp</groupId><br> <artifactId>sentinel-transport-simple-http</artifactId><br> <version>x.y.z</version><br></dependency><br>
配置仪表盘IP地址
启动应用程序时添加仪表板 IP 地址:-Dcsp.sentinel.dashboard.server=consoleIp:port
调用资源<br>
1. “Machine Discovery(机器发现)”将显示按应用程序名称分组的机器<br>
机器列表页面
2. "Resources Tracing(资源追踪)" 将按机器显示资源
“资源链(Resource Chain)”中显示的资源存储在内存中<br>
3. "Monitoring(监控)" 将汇总同一应用程序中所有机器的资源指标<br>
“监控”只会在 5 分钟内记录指标。如果需要持久化这些数据。 如果遗漏任何信息,请检查您的配置并通过record.log和 进行故障排除metricStat.log.pid<Pid No>.<Date><br>
管理规则
规则查询<br>
Sentinel 仪表板中的规则页面
规则配置<br>
默认情况下,所有这些规则都存储在内存中<br>
动态规则配置
规则
Sentinel 的理念是开发者只需要关注资源的定义。一旦定义了资源,就可以动态添加和更新各种规则。Sentinel 提供了两种修改规则的方式:<br> 1. 通过API直接修改(loadRules的XxxRuleManager)<br> 2. 通过动态与外部存储集成 DataSource
通过 API 进行规则管理非常简单。您可以使用以下 API 修改不同的规则:<br><br> 1. 流程规则: FlowRuleManager.loadRules(List<FlowRule> rules)<br> 2. 降级规则: DegradeRuleManager.loadRules(List<DegradeRule> rules)<br> 3. 系统规则: SystemRuleManager.loadRules(List<SystemRule> rules)<br> 4. 权限规则: AuthorityRuleManager.loadRules(List<AuthorityRule> rules)<br>
动态数据源扩展<br>
loadRules()方法只接受内存中的规则。但更多情况下,规则存储在文件、数据库或配置中心中。动态DataSource接口使我们能够与任何配置源集成。建议在生产中使用动态规则数据源。
通过 Sentinel 仪表盘设置规则后将规则推送到统一规则配置中心。Sentinel 客户端实现了ReadableDataSource从配置中心实时观察变化的接口。过程如下:
<br>
数据源集成<br>
Redis数据源
Sentinel DataSource Redis 提供了与 Redis 的集成。数据源利用Redis pub-sub特性实现推送模型(listener)。<br><br>数据源使用Lettuce作为Redis客户端,需要JDK 1.8及以上版本。(不支持Redis Cluster)<br>
用法
要使用 Sentinel DataSource Redis,您应该添加以下依赖项:<br><dependency><br> <groupId>com.alibaba.csp</groupId><br> <artifactId>sentinel-datasource-redis</artifactId><br> <version>x.y.z</version><br></dependency><br>
然后您可以创建一个RedisDataSource并注册到规则管理器。例如:<br><br>ReadableDataSource<String, List<FlowRule>> redisDataSource = new RedisDataSource<List<FlowRule>>(redisConnectionConfig, ruleKey, channel, flowConfigParser);<br>FlowRuleManager.register2Property(redisDataSource.getProperty());<br><br>1. redisConnectionConfig: 使用RedisConnectionConfig类来构建你的 Redis 连接配置<br>2. ruleKey: Redis String 的规则持久化键<br>3. channel: 订阅频道<br>
创建多个数据源来订阅不同的规则类型<br><br>数据源ruleKey在初始化期间首先从 Redis 字符串(提供)加载初始规则。所以为了一致性,用户应该ruleKey像这样同时发布值和保存值(使用Redis事务):<br><br>MULTI<br>SET ruleKey value<br>PUBLISH channel value<br>EXEC<br>
Lettuce Redis 客户端<br>
public <T> void pushRules(List<T> rules, Converter<List<T>, String> encoder) {<br> StatefulRedisPubSubConnection<String, String> connection = client.connectPubSub();<br> RedisPubSubCommands<String, String> subCommands = connection.sync();<br> String value = encoder.convert(rules);<br> subCommands.multi();<br> subCommands.set(ruleKey, value);<br> subCommands.publish(ruleChannel, value);<br> subCommands.exec();<br>}
只需使用相同的密钥,就可以在 Redis 集群中处理事务
使用 Lettuce Redis Cluster 客户端
public <T> void pushRules(List<T> rules, Converter<List<T>, String> encoder) {<br> RedisAdvancedClusterCommands<String, String> subCommands = client.connect().sync();<br> int slot = SlotHash.getSlot(ruleKey);<br> NodeSelection<String, String> nodes = subCommands.nodes((n)->n.hasSlot(slot));<br> RedisCommands<String, String> commands = nodes.commands(0);<br> String value = encoder.convert(rules);<br> commands.multi();<br> commands.set(ruleKey, value);<br> commands.publish(channel, value);<br> commands.exec();<br>}
如何构建RedisConnectionConfig
使用 Redis 独立模式构建
RedisConnectionConfig config = RedisConnectionConfig.builder()<br> .withHost("localhost")<br> .withPort(6379)<br> .withPassword("pwd")<br> .withDataBase(2)<br> .build();
使用 Redis Sentinel 模式构建
RedisConnectionConfig config = RedisConnectionConfig.builder()<br> .withRedisSentinel("redisSentinelServer1",5000)<br> .withRedisSentinel("redisSentinelServer2",5001)<br> .withRedisSentinelMasterId("redisSentinelMasterId").build();
使用Redis集群模式构建
RedisConnectionConfig config = RedisConnectionConfig.builder()<br> .withRedisCluster("redisSentinelServer1",5000)<br> .withRedisCluster("redisSentinelServer2",5001).build();
Nacos数据源<br>
Sentinel 数据源 Nacos 提供了与Nacos 的集成,使 Nacos 可以作为 Sentinel 的动态规则数据源。<br><br>要使用 Sentinel DataSource Nacos,添加以下依赖项:<br><br><dependency><br> <groupId>com.alibaba.csp</groupId><br> <artifactId>sentinel-datasource-nacos</artifactId><br> <version>x.y.z</version><br></dependency><br>
创建一个NacosDataSource并注册到规则管理器
// remoteAddress is the address of Nacos<br>// groupId and dataId are concepts of Nacos<br>ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(remoteAddress, groupId, dataId,<br> source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}));<br>FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
Spring Cloud Config 数据源
Sentinel 数据源 Spring Cloud Config 提供了与 Spring Cloud Config 的集成,使 Spring Cloud Config 可以作为 Sentinel 的动态规则数据源。<br><br>要使用 Sentinel DataSource Spring Cloud Config,添加以下依赖项:<br><br><dependency><br> <groupId>com.alibaba.csp</groupId><br> <artifactId>sentinel-datasource-spring-cloud-config</artifactId><br> <version>x.y.z</version><br></dependency><br>
创建一个SpringCloudConfigDataSource并注册到规则管理器。
ReadableDataSource<String, List<FlowRule>> flowRuleDs = new SpringCloudConfigDataSource<>(ruleKey, s -> JSON.parseArray(s, FlowRule.class));<br>FlowRuleManager.register2Property(flowRuleDs.getProperty());
ZooKeeper 数据源<br>
Sentinel 数据源 ZooKeeper 提供了与 ZooKeeper 的集成,使得 ZooKeeper 可以作为 Sentinel 的动态规则数据源。数据源使用推送模型(监听器)。<br><br>要使用 Sentinel DataSource ZooKeeper,添加以下依赖项:<br><br><dependency><br> <groupId>com.alibaba.csp</groupId><br> <artifactId>sentinel-datasource-zookeeper</artifactId><br> <version>x.y.z</version><br></dependency><br>
创建一个ZookeeperDataSource并注册到规则管理器
// `path` is the data path in ZooKeeper<br>ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new ZookeeperDataSource<>(remoteAddress, path, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}));<br>FlowRuleManager.register2Property(flowRuleDataSource.getProperty());<br>
不建议在单个路径中添加大量规则(有限制,也会导致性能不佳)
动态文件数据源
apollo数据源
etcd数据源
Consul数据源
Collect
Get Started
Collect
Get Started
Collect
Get Started
Collect
Get Started
评论
0 条评论
下一页