Spring Cloud Alibaba 快速学习之 Sentinel

1. 引言

在微服务系统中,一个对外的业务功能可能会涉及很长的服务调用链路。当其中某个服务出现异常,如果没有服务调用保护机制可能会造成该服务调用链路上大量相关服务直接或间接调用的服务器仍然持续不断发起请求,最终导致相关的所有服务资源耗尽产生异常发生雪崩效应。限流和降级分别作为在流量控制和服务保护方面的两个重要手段,可以有效地应对此类问题。Sentinel以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

本章将快速讲解Sentinel的简单应用,阅读前需要先了解前置章节 Spring Cloud Alibaba 快速学习之 OpenFeign

2. 安装Sentinel控制台

2.1 下载jar包

打开下载地址,往下滚动,下载最新jar包。
在这里插入图片描述

2.2 运行jar包

在jar包存放位置,打开CMD命令行,运行以下命令,端口号可自行修改。

 java -Dserver.port=8849 -Dcsp.sentinel.dashboard.server=localhost:8849 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.8.jar

在这里插入图片描述

2.3 访问Sentinel控制台

浏览器打开:http://127.0.0.1:8849/#/login,账号密码都是sentinel,
在这里插入图片描述

3. 代码展示

代码在 Spring Cloud Alibaba 快速学习之 OpenFeign的基础上,更新了父级pom.xml文件和user-a项目。项目整体结构如下图:
在这里插入图片描述

3.1 父项目spring-cloud-alibaba-demo

3.1.1 pom.xml

在原来的基础上加入sentinel依赖。
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>spring-cloud-alibaba-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>server-a</module>
        <module>user-a</module>
        <module>server-b</module>
    </modules>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <!--  为Spring Boot项目提供一系列默认的配置和依赖管理-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.2</version>
        <relativePath/>
    </parent>

    <dependencies>
        <!--  Spring Boot核心-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- Spring Boot单元测试和集成测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Spring Boot构建Web应用程序-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Nacos 配置管理-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            <version>2023.0.1.2</version>
        </dependency>
        <!-- Nacos 服务发现-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2023.0.1.2</version>
        </dependency>
        <!-- spring cloud 负载均衡-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
            <version>4.1.4</version>
        </dependency>
        <!-- spring cloud openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>4.1.3</version>
        </dependency>
        <!-- spring cloud alibaba 限流降级-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>2023.0.1.2</version>
        </dependency>

    </dependencies>

</project>

3.2 子项目user-a

3.2.1 application.properties

修改配置,加入了sentinel相关的配置。
在这里插入图片描述

#spring应用程序监听的端口号
server.port=8082
#spring应用程序的名称
spring.application.name=user-a
#spring当前激活的配置文件
spring.profiles.active=dev
#nacos服务地址
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
#nacos不导入配置文件,也能正常启动项目
spring.cloud.nacos.config.import-check.enabled=false
#OpenFeign开启sentinel功能
feign.sentinel.enabled=true
#sentinel端口号
spring.cloud.sentinel.transport.port=8850
#sentinel dashboard地址
spring.cloud.sentinel.transport.dashboard=127.0.0.1:8849

3.2.2 org/example/openfeign/ServerAClientFallback.java

新增一个类,与ServerAClient.java中的openfeign注解对应,用于实现Sentinel限流降级后的方法。
在这里插入图片描述

package org.example.openfeign;

import java.util.Map;


public class ServerAClientFallback implements ServerAClient {


    @Override
    public String get() {
        return "get fallback";
    }

    @Override
    public String get(String string) {
        return "get String fallback ";
    }

    @Override
    public Object getObj(Map<String, Object> info) {
        return "getObj fallback";
    }

    @Override
    public String sleep() {
        return "sleep fallback";
    }
}

3.2.3 org/example/openfeign/ServerAClient.java

修改方法,加入openfeign注解,用于关联Sentinel服务
在这里插入图片描述

package org.example.openfeign;


import org.example.conf.FeignConfiguration;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

import java.util.Map;


@FeignClient(name = "server-a", path = "/test", fallback = ServerAClientFallback.class, configuration = FeignConfiguration.class)
public interface ServerAClient {

    @RequestMapping("/get")
    String get();

    @GetMapping("/get/{string}")
    String get(@PathVariable String string);

    @PostMapping("/getObj")
    Object getObj(@RequestBody Map<String, Object> info);

    @GetMapping("/sleep")
    String sleep();


}

3.2.4 org/example/conf/MyBlockExceptionHandler.java

新增一个类,在Sentinel发生限流降级时会调用handle方法。
在这里插入图片描述

package org.example.conf;

import com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;

/*
 *  Sentinel发生限流降级时调用handle方法。配规则不带服务名,例如:/test/get
 *
 *  BlockExceptionHandler优先级高于Fallback中实现方法
 *
 * */
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, String s, BlockException ex) throws Exception {
        String msg = null;
        if (ex instanceof FlowException) {
            msg = "限流";
        } else if (ex instanceof DegradeException) {
            msg = "降级";
        } else if (ex instanceof ParamFlowException) {
            msg = "热点参数限流";
        } else if (ex instanceof SystemBlockException) {
            msg = "系统规则限流或降级";
        } else if (ex instanceof AuthorityException) {
            msg = "授权规则不通过";
        }
        String msgAll = "接口:[" + request.getServletPath() + "]" + msg;
        // http状态码
        response.setStatus(500);
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Type", "application/json;charset=utf-8");
        response.setContentType("application/json;charset=utf-8");
        new ObjectMapper().writeValue(response.getWriter(), msgAll);
    }
}

3.2.5 org/example/conf/FeignConfiguration.java

新增一个类,与ServerAClient.java中的openfeign注解对应,Sentinel发生限流降级时调用Fallback中实现方法。
在这里插入图片描述

package org.example.conf;


import org.example.openfeign.ServerAClient;
import org.example.openfeign.ServerAClientFallback;
import org.springframework.context.annotation.Bean;

/*
 *  Sentinel发生限流降级时调用Fallback中实现方法。匹配规则带服务名,例如:GET:http://server-a/test/get
 *
 * */
public class FeignConfiguration {

    @Bean
    public ServerAClient serverAClientFallback() {
        return new ServerAClientFallback();
    }

}

3. 代码测试

3.1 启动项目

先启动NACOS,再启动三个子项目。在NACOS控制台可以看到有一个user-a服务,两个server-a服务,说明我们的三个服务都注册成功。
在这里插入图片描述

3.2 登录sentinel控制台

浏览器打开:http://127.0.0.1:8849/#/login,账号密码都是sentinel,可以看到user-a项目已经注册到控制台。
在这里插入图片描述

3.3 刷新sentinel控制台的链路

打开浏览器访问:http://localhost:8082/test/get,然后sentinel控制台会出现新的链路。
在这里插入图片描述
在这里插入图片描述

3.4 流控测试Fallback

我们先给全路径"GET:http://server-a/test/get"新增流控,单机阈值1,表示每秒访问该接口的次数大于1时,将会出发流控。
在这里插入图片描述然后快速不停的访问:http://localhost:8082/test/get,此时可以看到浏览器会频繁的返回“get fallback”。
在这里插入图片描述这与org/example/openfeign/ServerAClientFallback.java的get()方法的返回一致,说明流控成功。
在这里插入图片描述

3.5 流控测试BlockExceptionHandler

我们给路径"/test/get"新增流控,单机阈值1,表示每秒访问该路径的次数大于1时,将会出发流控。注意BlockExceptionHandler的handle优先级高于Fallback中实现方法。
在这里插入图片描述然后快速不停的访问:http://localhost:8082/test/get,此时可以看到浏览器会频繁的返回“接口:[/test/get]限流”。
在这里插入图片描述这与org/example/conf/MyBlockExceptionHandler.java的handle()方法的返回一致,说明流控成功。
在这里插入图片描述

3.5 熔断测试BlockExceptionHandler

我们给路径"/test/sleep “新增熔断,下图配置表示,如果接口超过1000毫秒未成功返回,接口将会熔断2秒。如果列表中没有”/test/sleep ",可以先访问一下:http://localhost:8082/test/sleep,再刷新列表就有了。
在这里插入图片描述
然后快速不停的访问:http://localhost:8082/test/sleep,此时可以看到浏览器会频繁的返回““接口:[/test/sleep]降级””。
在这里插入图片描述这与org/example/conf/MyBlockExceptionHandler.java的handle()方法的返回一致,说明熔断成功。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值