【SpringCloud】5.0 流量控制(熔断,降级、限流等)——Sentinel

微服务架构

  • SpringCloud
    服务注册发现:Nacos
    服务限流降级:Sentinel
    分布配置中⼼:Nacos
    分布式事务保证数据一致性:Seata
    分布式定时任务:Spring Scheduling Tasks
    服务⽹关:SpringCloud Gateway
    异步消息削峰填谷:RocketMQ
    服务之间调⽤:OpenFeign、Ribbon
    链路追踪:Sleuth+Zipkin

技术栈版本控制

序号 名称 版本 用途 备注
1 openJDK 21 Java JDK
2 postgresSQL 17.4 基础数据库
3 Maven 3.9.9 Java第三方依赖包管理工具
4 springboot 3.4.3 Java MVC框架
5 springcloud 2024.0.1 微服务框架
6 springcloud Alibaba 2023.0.3.2 阿里巴巴微服务框架扩展

组件版本控制

序号 名称 版本 用途 备注
1 Nacos 2.5.1 服务注册发现、分布配置中⼼
2 Sentinel 1.8.8 服务限流降级 面向云原生微服务的高可用流控防护组件
3 Seata 2.3.0 分布式事务保证数据一致性

高并发下的微服务架构存在的问题和解决方案

海量请求下的微服务架构存在的问题

微服务拆分多个系统,服务之间互相依赖,可能会由于系统负载过高,突发流量或者网络等各种异常情况 导致服务不可用。

核心思想-面向失败编程

  • 不要外界影响
  • 不被请求拖垮
    上游服务
    下游服务

面向失败编程-微服务架构容错方案

  • 限流
  • 漏斗
  • 不管流量多大,均匀的流入容器,令牌桶算法,漏桶算法
  • 熔断:
  • 保险丝,熔断服务,为了防止整个系统故障,包含当前和下游服务 下单服务 -》商品服务-》用户服务 -》(出现异常-》熔断风控服务
  • 降级:
  • 抛弃一些非核心的接口和数据,返回兜底数据 旅行箱的例子:只带核心的物品,抛弃非核心的,等有条件的时候再去携带这些物品
  • 隔离:
  • 服务和资源互相隔离,比如网络资源,机器资源,线程资源等,不会因为某个服务的资源不足而抢占其他服务的资源
  • 熔断和降级互相交集
  • 相同点:
    • 从可用性和可靠性触发,为了防止系统崩溃
    • 最终让用户体验到的是某些功能暂时不能用
  • 不同点
    • 服务熔断一般是下游服务故障导致的,而服务降级一般是从整体系统负荷考虑,由调用方控制
    • 想进行微服务的容错,业界目前有Sentinel、Hystrix,相对于AlibabaCloud而言,Sentinel是最好的搭配

分布式系统的流量防卫兵-Sentinel介绍

简介:介绍什么是分布式系统的流量防卫兵Sentinel

  • 什么是Sentinel

    • 阿里巴巴开源的分布式系统流控工具

Sentinel 具有以下特征:

  • 丰富的应用场景
    Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
  • 完备的实时监控
    Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
  • 广泛的开源生态
    Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Apache Dubbo、gRPC、Quarkus 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。同时 Sentinel 提供 Java/Go/C++ 等多语言的原生实现。
  • 完善的 SPI 扩展机制
    Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
  • 核心概念:

    • 资源:是 Sentinel 中的核心概念之一,可以是java程序中任何内容,可以是服务或者方法甚至代码,总结起来就是我们要保护的东西
    • 规则:定义怎样的方式保护资源,主要包括流控规则、熔断降级规则等


      image.png

      image.png

Sentinel 分为两个部分:

  • 核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
  • 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。

微服务引入Sentinel依赖

  • 查看机器列表以及健康情况:收集 Sentinel 客户端发送的心跳包,用于判断机器是否在线。
  • 监控 (单机和集群聚合)通过 Sentinel 客户端暴露的监控 API,定期拉取并且聚合应用监控信息,最终可以实现秒级的实时监控。
  • 规则管理和推送:统一管理推送规则。
  • 鉴权:生产环境中鉴权非常重要。这里每个开发者需要根据自己的实际情况进行定制。

————————————————————
> 注意:Sentinel 控制台目前仅支持单机部署

安装控制台

点击这里进入下载页面

image.png

//启动 Sentinel 控制台需要 JDK 版本为 1.8 及以上版本,
//-Dserver.port=8080 用于指定 Sentinel 控制台端口为 8080
//默认用户名和密码都是 sentinel

我的是window用迅雷下载的,所以下载快,然后传送到服务器/home/ubuntu/sentinel下面。


image.png
cd /home/ubuntu/sentinel
普通进程
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.8.jar

守护进程
nohup java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.8.jar
// 自定义用户名密码
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard  -Dsentinel.dashboard.auth.username=sentinel -Dsentinel.dashboard.auth.password=123456 -jar sentinel-dashboard-1.8.8.jar

然后在当前目录下执行命令:

cd /home/ubuntu/sentinel

nohup java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard  -Dsentinel.dashboard.auth.username=sentinel -Dsentinel.dashboard.auth.password=123456 -jar sentinel-dashboard-1.8.8.jar
image.png

执行项目:


image.png

云服务器记得防火墙开启8080端口


image.png

浏览器打开公网地址http://106.xxx.xxxx.xxx:8080/

image.png

image.png

AliababCloud微服务整合Sentinel限流配置

多个微服务接入Sentinel配置

spring:
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080 
        port: 9999 

#dashboard: 8080 控制台端口
#port: 9999 本地启的端口,随机选个不能被占用的,与dashboard进行数据交互

首先在具体服务中添加依赖:

会在应用对应的机器上启动一个 Http Server,该 Server 会与 Sentinel 控制台做交互, 若被占用,则开始+1一次扫描
微服务注册上去后,由于Sentinel是懒加载模式,所以需要访问微服务后才会在控制台出现

限流配置
online-edu-order-service/pom.xml

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

同样配置online-edu-user-service/pom.xml和online-edu-video-service/pom.xml,更新maven。

修改三个项目的application.yml


image.png

端口必须本地没有被占用的3个,我用的9991、9992、9993

查看可视化控制台,发现并没有找到这3个服务。

然后用Apipost多请求几次:


image.png

就可以看到服务已经被发现:

image.png

这里发现,服务虽然被发现了,但没有数据,是因为本地运行代码启动的服务,而控制台在云服务器(本地通过路由器连的互联网)。

修改代码为127.0.0.1:8080,本地(window11系统)运行sentinel-dashboard-1.8.8.jar。
window系统执行:

将sentinel-dashboard-1.8.8.jar包放入D:\program\sentinel目录,在该目录下路径栏搜索cmd。
执行:
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard  -Dsentinel.dashboard.auth.username=sentinel -Dsentinel.dashboard.auth.password=123456 -jar sentinel-dashboard-1.8.8.jar

运行:


image.png
image.png

这里的请求通过Apipost,自动化测试实现:


image.png

Sentinel多种流控规则

Sentinel流量控制详细操作
流量控制(flow control)

原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。

两种规则

  • 基于统计并发线程数的流量控制——并发数控制用于保护业务线程池不被慢调用耗尽
    Sentinel 并发控制不负责创建和管理线程池,而是简单统计当前请求上下文的线程数目(正在执行的调用数目)
    如果超出阈值,新的请求会被立即拒绝,效果类似于信号量隔离。
  • 基于统计QPS的流量控制——当 QPS 超过某个阈值的时候,则采取措施进行流量控制

控制面板介绍

  • 资源名:默认是请求路径,可自定义
    针对来源:对哪个微服务进行限流,默认是不区分来源,全部限流,这个是针对 区分上游服务进行限流, 比如 视频服务 被 订单服务、用户服务调用,就可以针对来源进行限流
image.png

簇点链路,修改 流控:


image.png

为了方便测试,这里用QBS(每秒查询率,请求数/秒),阙值为2,其他默认:


image.png
image.png

我们用压测,快速发起20次请求:


image.png
image.png

我们看到失败的,报错Blocked by Sentinel (flow limiting),就是流量控制在限制请求流量。

基于统计并发线程数进行限流配置

并发数控制用于保护业务线程池不被慢调用耗尽

  • Sentinel 并发控制不负责创建和管理线程池,而是简单统计当前请求上下文的线程数目(正在执行的调用数目)
  • 如果超出阈值,新的请求会被立即拒绝,效果类似于信号量隔离。并发数控制通常在调用端进行配置

流控规则会下发到微服务(Java某个微服务子项目),微服务如果重启,则流控规则会消失,可以持久化配置

测试

增加接口:
online-edu-order-service/src/main/java/org/online_edu/controller/VideoOrderController.java

    @RequestMapping("/list")
    public Object list() {
        // 模拟现成睡眠的效果
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            // 恢复中断状态
            Thread.currentThread().interrupt();
            // 记录异常或者返回友好的错误消息
            return "Error: The request was interrupted.";
        }
        Map<String, String> map = new HashMap<>();
        map.put("title1", "面试专题视频1");
        map.put("title2", "面试专题视频2");
        return map;
    }

启动online-edu-order-service服务。

选择阈值类型 ”线程数“ ,配置是1


image.png

image.png

打开http://localhost:8000/api/v1/video_order/list,刷新浏览器,不等待结果返回,立即再次刷新,就可以看到流量控制生效:

image.png

流控规则效果-直接拒绝-冷启动预热-匀速排队

image.png

基于并发线程进⾏限流配置
流量控制的效果包括以下⼏种:

  • 直接拒绝:默认的流量控制⽅式,当QPS超过任意规则的阈值后,新的请求就会被⽴即拒绝

  • Warm Up:冷启动/预热,如果系统在此之前⻓期处于空闲的状态,我们希望处理请求的数量是缓步的增多,经过预期的时间以后,到达系统处理请求个数的最⼤值


    image.png
  • 派对等待(匀速排队):严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法,主要⽤于处理间隔性突发的流量,如消息队列,想象⼀下这样的场景,在某⼀秒有⼤量的请求到来,⽽接下来的⼏秒则处
    于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,⽽不是在第⼀秒直接拒绝多余的请求

image.png
  • 注意:
    匀速排队等待策略是 Leaky Bucket 算法结合虚拟队列等待机制实现的。
    匀速排队模式暂时不⽀持 QPS > 1000 的场景

熔断降级规则

Sentinel熔断降级规则

  • 熔断降级(虽然是两个概念,基本都是互相配合)
  • 对调⽤链路中不稳定的资源进⾏熔断降级也是保障⾼可⽤的重要措施之⼀
  • 对不稳定的弱依赖服务调⽤进⾏熔断降级,暂时切断不稳定调⽤,避免局部不稳定因素导致整体的雪崩
  • 熔断降级作为保护⾃身的⼿段,通常在客户端(调⽤端)进⾏配置

Sentinel降级规则

⽂档:
https://github.com/alibaba/Sentinel/wiki/熔断降级
就是配置⼀定规则,然后满⾜之后就对服务进⾏熔断降级。

可以在控制台进行控制。(控制台重启,或者代码重新运行都会洗掉配置)。也可以在微服务项目通过代码进行控制。

Sentinel 熔断策略

  • 慢调⽤⽐例(响应时间)
    选择以慢调⽤⽐例作为阈值,需要设置允许的慢调⽤ RT(响应时间阈值,即最⼤的响应时间),请求的响应时间⼤于该值则统计为慢调⽤
  • ⽐例阈值:比例阈值的范围是[0.0, 1.0],对应0%到100%。例如,设置0.5即50%的请求响应时间超过最大RT时触发。(1.8.1版本通过补丁修复了“当设置熔断比例为100%(例如异常比例或慢调用比例阈值设为1.0)时,熔断规则可能无法正确触发。”)

  • 熔断时⻓:超过时间后会尝试恢复

  • 最⼩请求数:熔断触发的最⼩请求数,请求数⼩于该值时即使异常⽐率超出阈值也不会熔断

  • 统计时长:表示系统在触发熔断前,统计请求数据的时间窗口长度。例如:若设置为 1000ms(默认值),表示每秒统计一次请求数据(如请求总数、慢调用数、异常数等) 若设置为 60000ms(1分钟),则按分钟级窗口统计。

image.png
  • 异常⽐例
    当单位统计时⻓内请求数⽬⼤于设置的最⼩请求数⽬,并且异常的⽐例⼤于阈值,则接下来的熔断时⻓内请求会⾃动被熔断⽐例阈值
  • ⽐例阈值

  • 熔断时⻓:超过时间后会尝试恢复

  • 最⼩请求数:熔断触发的最⼩请求数,请求数⼩于该值时,即使异常⽐率超出阈值也不会熔断

  • 统计时长

image.png

异常数
当单位统计时⻓内的异常数⽬超过阈值之后会⾃动进⾏熔断

  • 异常数:出现异常报错接口请求的次数

  • 熔断时⻓:超过时间后会尝试恢复

  • 最⼩请求数:熔断触发的最⼩请求数,请求数⼩于该值时即使异常⽐率超出阈值也不会熔断

  • 统计时长

image.png

熔断状态和恢复

服务熔断⼀般有三种状态(画图)

  • 熔断关闭(Closed)
    服务没有故障时,熔断器所处的状态,对调⽤⽅的调⽤不做任何限制

  • 熔断开启(Open)
    后续对该服务接⼝的调⽤不再经过⽹络,直接执⾏本地的fallback⽅法

  • 半熔断(Half-Open)
    所谓半熔断就是尝试恢复服务调⽤,允许有限的流量调⽤该服务,并监控调⽤成功率

  • 熔断恢复
    经过熔断时⻓后熔断器会进⼊探测恢复状态(HALF-OPEN 状态)尝试恢复服务调⽤,允许有限的流量调⽤该服务,并监控调⽤成功率。如果成功率达到预期,则说明服务已恢复,进⼊熔断关闭状态;如果成功率仍旧很低,则重新进⼊熔断状态

代码Demo演示

修改online-edu-order-service/src/main/java/org/online_edu/controller/VideoOrderController.java

package org.online_edu.controller;

import org.online_edu.domain.Video;
import org.online_edu.domain.VideoOrder;
import org.online_edu.service.VideoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * (VideoOrder)表控制层
 *
 * @author makejava
 * @since 2024-08-30 23:00:25
 */
@RestController
@RequestMapping("/api/v1/video_order")
public class VideoOrderController {

    ******
    int temp = 0;

    @RequestMapping("/list")
    public Object list() {
//        // 模拟线程睡眠的效果
//        try {
//            TimeUnit.SECONDS.sleep(5);
//        } catch (InterruptedException e) {
//            // 恢复中断状态
//            Thread.currentThread().interrupt();
//            // 记录异常或者返回友好的错误消息
//            return "Error: The request was interrupted.";
//        }
        // 模拟抛出异常
        temp++;
        if (temp % 3 == 0) {
            throw new RuntimeException("模拟异常");
        }

        Map<String, String> map = new HashMap<>();
        map.put("title1", "面试专题视频1");
        map.put("title2", "面试专题视频2");
        return map;
    }
}

重新运行服务,通过Apipost发起3次请求,看是否出发模拟。


image.png

image.png

配置熔断规则,比如如下:


image.png

发起压测:
image.png

image.png

调整规则,再次发起:


image.png

image.png

image.png

说明我们配置的熔断规则是真实有效的。

当然每次压测的结果不一样,可以多测试几次,比如我再次执行,效果如下:


image.png

注意:要不要配置熔断按业务来定,具体问题具体分析,很多接口不需要配置熔断,或者不能配置熔断。

如下图的“热点”、“授权”,实际用得不是很多,也是流控管理更加细节的配置规则,如有需要可具体可以参考官方文档进行配置。


image.png

⾃定义降级异常不向下兼容的坑

  • 默认降级返回数据问题
    限流和熔断返回的数据有问题-微服务交互基本都是json格式,如果让⾃定义异常信息

  • AlibabCloud版本升级,不兼容问题
    v2.1.0到v2.2.0后,Sentinel⾥⾯依赖进⾏了改动,且不向下兼容

  • ⾃定义降级返回数据
    【旧版】实现UrlBlockHandler并且重写blocked⽅法

@Component
public class OnlineEduUrlBlockHandler
implements UrlBlockHandler {
 @Override
 public void blocked(HttpServletRequest
httpServletRequest, HttpServletResponse
httpServletResponse, BlockException e) throws IOException {
 //降级业务处理
 }
}

【新版】实现BlockExceptionHandler并且重写handle⽅法

public class XdclassUrlBlockHandler
implements BlockExceptionHandler {
 
 @Override
 public void handle(HttpServletRequest
httpServletRequest, HttpServletResponse
httpServletResponse, BlockException e) throws Exception {
 //降级业务处理
 }
}

新版Sentinel⾃定义异常数据开发实战

异常种类

FlowException //限流异常
DegradeException //降级异常
ParamFlowException //参数限流异常
SystemBlockException //系统负载异常
AuthorityException //授权异常

【新版】实现BlockExceptionHandler并且重写handle⽅

新建online-edu-order-service/src/main/java/org/online_edu/config/OnlineEduOrderUrlBlockHandler.java,配置文件。

package org.online_edu.config;

import package org.online_edu.config;

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.alibaba.fastjson.JSON;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
public class OnlineEduOrderUrlBlockHandler implements BlockExceptionHandler {
    /**
     * Handle the request when blocked.
     *
     * @param request      Servlet request
     * @param response     Servlet response
     * @param resourceName resource name
     * @param e            the block exception
     * @throws Exception users may throw out the BlockException or other error occurs
     */
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, String resourceName, BlockException e) throws Exception {
        Map<String, Object> backMap = new HashMap<>();
        if (e instanceof FlowException) {
            backMap.put("code", -1);
            backMap.put("msg", "限流-异常啦");
        } else if (e instanceof
                DegradeException) {
            backMap.put("code", -2);
            backMap.put("msg", "降级-异常啦");
        } else if (e instanceof
                ParamFlowException) {
            backMap.put("code", -3);
            backMap.put("msg", "热点-异常啦");
        } else if (e instanceof
                SystemBlockException) {
            backMap.put("code", -4);
            backMap.put("msg", "系统规则-异常啦");
        } else if (e instanceof
                AuthorityException) {
            backMap.put("code", -5);
            backMap.put("msg", "认证-异常啦");
        }
        // 设置返回json数据
        response.setStatus(200);
        response.setHeader("content-Type", "application/json;charset=UTF-8");

        response.getWriter().write(JSON.toJSONString(backMap));
    }
}

重新运行微服务,通过浏览器运行http://localhost:8000/api/v1/video_order/list,发现模拟异常代码仍然正常执行(2次成功1次失败循环出现。)

配置一个限流的规则:


image.png
image.png

多刷新几次浏览器链接,就可以看到限流异常抛出:


image.png

多请求几次,就可以看到实时监听:


image.png

Sentinel整合OpenFeign

整合的目的是,比如视频列表查询接口dang了,可以读取准备好的兜底数据视频数据返回给用户,比如昨天的视频,而不是最新用户应该看到的,结果虽然用户请求失败限流了,但还是返回视频是正常可以看的。

多个微服务的时候,某个微服务挂了,也不影响其他微服务的使用。


image.png

修改online-edu-order-service/src/main/java/org/online_edu/controller/VideoOrderController.java

package org.online_edu.controller;

import org.online_edu.domain.Video;
import org.online_edu.domain.VideoOrder;
import org.online_edu.service.VideoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * (VideoOrder)表控制层
 *
 * @author bobokaka
 * @since 2024-08-30 23:00:25
 */
@RestController
@RequestMapping("/api/v1/video_order")
public class VideoOrderController {

    /**
     * 服务对象
     */
    @Qualifier("org.online_edu.service.VideoService")
    @Autowired
    private VideoService videoService;

    /**
     * 保存视频订单
     * @param videoId 视频ID
     * @return 视频订单对象
     */
    @RequestMapping("/save")
    public Object save(@RequestParam(name = "videoId") int videoId) {

        // 根据视频ID查找视频信息
        Video video = videoService.findById(videoId);
        // 创建视频订单对象
        VideoOrder videoOrder = new VideoOrder();
        // 如果视频信息不为空,则设置视频订单的相关属性
        if (video != null) {
            videoOrder.setServeInfo(video.getServeInfo());
            videoOrder.setVideoId(video.getId());
            videoOrder.setVideoTitle(video.getTitle());
            videoOrder.setCreateTime(new Date());
        }
        // 返回视频订单对象
        return videoOrder;
    }

    // 注释掉的保存视频的方法
//    @PostMapping("/save")
//    public String save(@RequestBody Video video) {
//        videoService.save(video);
//        return "OK";
//    }

......
}


新建失败回调处理服务类。
online-edu-order-service/src/main/java/org/online_edu/service/fallback/VideoServiceFallback.java

package org.online_edu.service.fallback;

import org.online_edu.domain.Video;
import org.online_edu.service.VideoService;
import org.springframework.stereotype.Service;

@Service
public class VideoServiceFallback implements VideoService {
    @Override
    public Video findById(int videoId) {
        Video video = new Video();
        video.setTitle("这个是Fallback里面的视频");
        return video;
    }

    @Override
    public int save(Video video) {
        return 0;
    }
}

修改online-edu-order-service/src/main/java/org/online_edu/service/VideoService.java
增加fallback = VideoServiceFallback.class

package org.online_edu.service;

import org.online_edu.domain.Video;
import org.online_edu.service.fallback.VideoServiceFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(value = "online-edu-video-service",fallback = VideoServiceFallback.class)
public interface VideoService {
    @GetMapping(value = "/api/v1/video/find_by_id")
    Video findById(@RequestParam("videoId") int videoId);

    @PostMapping(value = "/api/v1/video/save")
    int save(@RequestBody Video video);
}

开启Feign对Sentinel的⽀持
online-edu-order-service/src/main/resources/application.yml
增加如下代码

# 开启Feign对Sentinel的⽀持
feign:
  sentinel:
    enabled: true

完整代码如下:

server:
  port: 8000

spring:
  application:
    name: online-edu-order-service
  cloud:
    nacos:
      discovery:
        server-addr: xxx.xxx.xxx.xxx:8848
        username: nacos
        password: password
    sentinel:
      transport:
        dashboard: localhost:8080
        port: 8900
      http-method-specify: true #开启请求方式前缀
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:postgresql://localhost:5432/online_edu_order?currentSchema=public
    username: postgres
    password: 123456
    driver-class-name: org.postgresql.Driver
    druid:
      # 数据库
      # 连接池-初始化大小
      initial-size: 10
      # 连接池-最大连接数
      max-active: 100
      # 最大等待时间
      max-wait: 60000
      # 连接池-最小空闲数
      min-idle: 10
      # 检测空闲连接
      test-while-idle: true
      # 最小空闲时间
      min-evictable-idle-time-millis: 300000
mybatis-plus:
  # Mapper XML文件路径
  mapper-locations: classpath:/mapper/**/*.xml
  # 实体类别名包路径
  type-aliases-package: org.online_edu.domain
  configuration:
    # MyBatis底层日志实现
    # 控制台输出sql、下划线转驼峰
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true
# 使用随机负载均衡策略
online-edu-order-service:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
# 开启Feign对Sentinel的⽀持
feign:
  sentinel:
    enabled: true

# PageHelper分页插件
pagehelper:
  # 数据库类型
  helperDialect: postgresql
  # 是否合理处理count查询
  reasonable: true
  # 支持通过Map传入分页参数
  supportMethodsArguments: true
  # 自定义参数
  params: count=countSql

重新运行online-edu-order-service服务。
正常运行没有问题。


image.png

将online-edu-video-service服务停止运行。
再次请求:


image.png

说明配置生效。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容