Spring Cloud Alibaba系列(六)sentinel的实际应用

简介: 上一章中我们通过Dashboard来为Sentinel客户端设置各种各样的规则,但是这些规则默认是存放在内存中,极不稳定,无法用于生成环境,所以需要将其持久化

一、sentinel的持久化配置

上一章中我们通过Dashboard来为Sentinel客户端设置各种各样的规则,但是这些规则默认是存放在内存中,极不稳定,无法用于生成环境,所以需要将其持久化。

DataSource 扩展常见的实现方式有:

  • 拉模式:客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件,甚至是 VCS 等。这样做的方式是简单,缺点是无法及时获取变更;
  • 推模式:规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。

Sentinel 目前支持以下数据源扩展:

生产环境中一般常用的就是推模式。这里我们使用Nacos存储规则。推送模式的正确做法应该是 配置中心控制台/Sentinel 控制台 → 配置中心 → Sentinel 数据源 → Sentinel

1.1 sentinel同步nacos配置

  1. 增加sentinel的依赖和nacos存储扩展依赖
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  1. 添加nacos相关配置
spring:
  cloud:
    sentinel:
      datasource:
        # 名称随意
        javatrip:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: ${spring.application.name}-rules
            groupId: SENTINEL_GROUP
            # 规则类型,取值见:
            # org.springframework.cloud.alibaba.sentinel.datasource.RuleType
            rule-type: flow
  1. 提供接口用于测试限流
@RestController
class test{

    @RequestMapping("/test")
    public String test(){
        return "Java旅途";
    }
}
  1. nacos中增加限流规则的配置

  • resource:资源名,即限流规则的作用对象
  • limitApp:流控针对的调用来源,若为 default 则不区分调用来源
  • grade:限流阈值类型(QPS 或并发线程数);0代表根据并发数量来限流,1代表根据QPS来进行流量控制
  • count:限流阈值
  • strategy:调用关系限流策略
  • controlBehavior:流量控制效果(直接拒绝、Warm Up、匀速排队)
  • clusterMode:是否为集群模式
  1. 测试,访问test接口,发现sentinel-dashboard中出现了一条流控规则

1.2 sentinel-dashboard中修改规则同步到nacos

要想实现在sentinel-dashboard中修改规则并同步到nacos,我们就需要修改sentinel服务。首先我们去官网下载Sentinel。

  1. 修改pom文件
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
    <scope>test</scope>
</dependency>

将test注释掉,因为这个是作用与test目录下的。

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
    <!--<scope>test</scope>-->
</dependency>
  1. 找到 sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/nacos目录,将整个目录拷贝到 sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/
  2. 找到 com.alibaba.csp.sentinel.dashboard.controller.v2.FlowControllerV2 ,将默认动态规则修改为nacos动态规则。
@Autowired
@Qualifier("flowRuleDefaultProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleDefaultPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;

修改为:

@Autowired
@Qualifier("flowRuleNacosProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleNacosPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
  1. 找到 sentinel-dashboard/src/main/webapp/resources/app/scripts/directives/sidebar/sidebar.html

将以下内容注释去掉

<!--<li ui-sref-active="active" ng-if="entry.appType==0">-->
    <!--<a ui-sref="dashboard.flow({app: entry.app})">-->
        <!--<i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控规则 V1</a>-->
<!--</li>-->
  1. 重新编译打包,运行打包后的sentinel-dashboard.jar。
  2. 测试,我们删除nacos中的流量规则配置
  • 在sentinel-dashboard——>流量规则V1中新增一个规则。

  • 刷新nacos,发现多了一个配置

  • 在nacos中修改这个配置,将阀值改为1

  • 刷新sentinel-dashboard,流量阀值修改为1了。

  • 重启服务,重启sentinel-dashboard,发现流控规则依然存在。

注意:以上只是演示了流控规则的持久化,sentinel还支持其他规则,如果想实现哪种规则都可以采用相同的方式实现!

二、Gateway网关限流

限流:就是请求多了,对请求进行定制的快速响应处理,应用在服务提供者本身。

从 1.6.0 版本开始,Sentinel 提供了 Spring Cloud Gateway 的适配模块,可以提供两种资源维度的限流:

  • route 维度:即在 Spring 配置文件中配置的路由条目,资源名为对应的 routeId
  • 自定义 API 维度:用户可以利用 Sentinel 提供的 API 来自定义一些 API 分组
  1. 添加依赖
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
    <version>x.y.z</version>
</dependency>
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
</dependency>
  1. 注入对应的 SentinelGatewayFilter 实例以及 SentinelGatewayBlockExceptionHandler 实例。
@Configuration
public class GatewayConfiguration {

    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;

    public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
                                ServerCodecConfigurer serverCodecConfigurer) {
        this.viewResolvers=viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        // Register the block exception handler for Spring Cloud Gateway.
        return new MySentinelGatewayBlockExceptionHandler(viewResolvers,serverCodecConfigurer);
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }
}
  1. 自定义异常处理
public class MySentinelGatewayBlockExceptionHandler extends SentinelGatewayBlockExceptionHandler {

    private List<ViewResolver> viewResolvers;
    private List<HttpMessageWriter<?>> messageWriters;
    public MySentinelGatewayBlockExceptionHandler(List<ViewResolver> viewResolvers, ServerCodecConfigurer serverCodecConfigurer) {
        super(viewResolvers,serverCodecConfigurer);
        this.viewResolvers = viewResolvers;
        this.messageWriters = serverCodecConfigurer.getWriters();
    }
    @Override
    public Mono<Void> handle(ServerWebExchange serverWebExchange, Throwable throwable) {

        if(serverWebExchange.getResponse().isCommitted()){
            return Mono.error(throwable);
        }
        if(!BlockException.isBlockException(throwable)){
            return Mono.error(throwable);
        }
        return handleBlockedRequest(serverWebExchange, throwable).flatMap(response -> writeResponse(response, serverWebExchange));
    }
    private Mono<ServerResponse> handleBlockedRequest(ServerWebExchange exchange, Throwable throwable) {
        return GatewayCallbackManager.getBlockHandler().handleRequest(exchange, throwable);
    }

    private final Supplier<ServerResponse.Context> contextSupplier = () -> new ServerResponse.Context() {
        @Override
        public List<HttpMessageWriter<?>> messageWriters() {
            return MySentinelGatewayBlockExceptionHandler.this.messageWriters;
        }

        @Override
        public List<ViewResolver> viewResolvers() {
            return MySentinelGatewayBlockExceptionHandler.this.viewResolvers;
        }
     };

    private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange) {
        ServerHttpResponse resp = exchange.getResponse();
        resp.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        String json = "{\"code\": -1, \"data\": null, \"msg\": \"访问量过大,请稍后再试\"}";
        DataBuffer buffer = resp.bufferFactory().wrap(json.getBytes(StandardCharsets.UTF_8));
        return resp.writeWith(Mono.just(buffer));
    }
}
  1. 配置路由
server:
  port: 7003
spring:
  application:
    name: alibaba-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      enabled: true
      discovery:
        locator:
          enabled: true # 开启从注册中心动态创建路由的功能,利用微服务名称进行路由
      routes:
      - id: sentinel-nacos # 路由id,建议配合服务名
        uri: lb://sentinel-nacos #匹配路由名
        predicates:
          - Path=/sentinel/** # 断言,路径相匹配的进行路由
        filters:
          - StripPrefix=1
  1. 添加启动参数
-Dcsp.sentinel.app.type=1 -Dcsp.sentinel.dashboard.server=localhost:8081 -Dproject.name=alibaba-gateway

  1. 访问接口,查看效果

三、feign调用实现熔断降级

降级:就是服务崩溃了,所以降级逻辑应该应用在消费者(调用者)那里,加在服务提供者本身是毫无意义的,因为服务已经断开了。

我们根据实际需求在sentinel-dashboard中配置降级规则,然后编写代码。

  1. 定义接口
@RequestMapping("/test")
public String test(){
    return "Java旅途";
}
  1. 定义远程服务调用接口
@FeignClient(name = "nacos-sentinel",fallback = RmoteTestFallback.class)
interface RemoteTest{
    @RequestMapping("/test")
    public String test();
}

为了简写fallback,我们更倾向于用fallbackFactory = RmoteTestFallbackFactory.class

@FeignClient(name = "nacos-sentinel",fallbackFactory = RmoteTestFallbackFactory.class)
interface RemoteTest{
    @RequestMapping("/test")
    public String test();
}
  1. 服务降级处理fallback
@Component
class RmoteTestFallback implements RemoteTest{
    @Override
    public String test() {
        return null;
    }
}
  1. 服务降级处理fallbackFactory
@Component
class RmoteTestFallbackFactory implements FallbackFactory<RemoteTest> {
    @Override
    public RemoteTest create(Throwable throwable) {
        return null;
    }
}
目录
相关文章
|
7月前
|
Dubbo Java 应用服务中间件
深入了解Spring Cloud Alibaba Dubbo
在现代分布式系统开发中,构建高性能、可伸缩性和弹性的微服务架构变得越来越重要。Spring Cloud Alibaba Dubbo(简称Dubbo)是一个开源的分布式服务框架,可以帮助开发者构建强大的微服务架构,具备负载均衡、服务治理、远程调用等强大功能。本文将深入介绍Spring Cloud Alibaba Dubbo,帮助你理解它的核心概念、工作原理以及如何在你的项目中使用它。
|
5月前
|
Kubernetes Java 微服务
Spring Boot 单体应用一键升级成 Spring Cloud Alibaba(1)
Spring Boot 单体应用一键升级成 Spring Cloud Alibaba(1)
85 0
Spring Boot 单体应用一键升级成 Spring Cloud Alibaba(1)
|
3月前
|
Java 中间件 开发者
Spring Cloud Alibaba
【1月更文挑战第27天】【1月更文挑战第127篇】Spring Cloud Alibaba
74 1
|
8月前
|
Java Nacos Sentinel
Spring Cloud Alibaba学习指南
由于在2018年Netflix公司宣布对其核心组件Hystrix、Ribbon、zuul、Eureka等进入维护状态,也就是Spring Cloud Netflix系列。由此Spring Cloud Alibaba就诞生了,值得注意的是Spring Cloud Alibaba完全兼容了Spring Cloud Netflix中的Ribbon、Feign、Eureka等组件,所以基于Spring Cloud Netflix的项目可以无缝迁移到Spring Cloud Alibaba。
395 0
|
4月前
|
消息中间件 Java Maven
Spring Cloud Alibaba 简介
Spring Cloud Alibaba 简介
185 1
|
4月前
|
消息中间件 负载均衡 Java
【从Spring Cloud到Spring Cloud Alibaba,这些改变你都知道吗?】—— 每天一点小知识
【从Spring Cloud到Spring Cloud Alibaba,这些改变你都知道吗?】—— 每天一点小知识
【从Spring Cloud到Spring Cloud Alibaba,这些改变你都知道吗?】—— 每天一点小知识
|
8月前
|
SQL 消息中间件 Oracle
|
8月前
|
负载均衡 Java Spring
业界良心啊!第五次更新的Spring Cloud Alibaba升级太多内容
Spring Cloud Alibaba经历的这几年,每次的更新都会掀起更大的水花,就在近日进行了第五次的重大更新,除了修改、升级了一些内容之外,还有增加了很多细节的内容。在质上可以说是有了一个很大的飞跃!
|
9月前
|
存储 消息中间件 安全
浅谈 Spring Cloud Alibaba
Spring Cloud Alibaba是微服务开发的种解决方案。它包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。
232 0
|
9月前
|
存储 负载均衡 算法
Spring Cloud Alibaba题目
五道关于Spring Cloud Alibaba的题目,希望能帮助初学者。
157 0