服务保护

服务保护

在这个项目中我们将一个单体项目拆分成了一个微服务的项目

  • 远程调用(OpenFeign):用于微服务之间的相互调用
  • 服务治理(Nacos):由于微服务之间错综复杂的相互调用,我们使用Nacos进行服务治理
  • 请求路由(网关):使前端能够统一调用错综复杂的微服务
  • 身份认证(网关):基本上每一个微服务都需要进行身份认证,我们在网关中统一进行身份认证,减少了每个微服务中的重复代码
  • 配置管理(Nacos):由于每一个微服务的配置都太多,配置更改后不能及时刷新,我们使用Nacos进行配置管理

雪崩问题

由于微服务较多,当某一个微服务出现故障,可能导致整个链路中所有微服务都不可用,这就是雪崩

雪崩问题产生的原因

  • 微服务相互调用,服务提供者出现故障或阻塞
  • 服务调用者没有做好异常处理,导致自身故障
  • 调用链中的所有服务级联失败,导致整个集群故障

解决思路有哪些

  1. 尽量避免服务出现故障或阻塞
  • 保证代码的健壮性
  • 保证网络通畅
  • 能应对较高的并发请求
  1. 服务调用者做好远程调用异常的后备方案,避免故障扩散

雪崩问题服务保护方案

请求限流

  • 请求限流:限制访问微服务的请求并发量,避免服务因流量激增出现故障
  • 限流器:使用限流器将访问微服务的请求进行限流 保持请求数量的平稳

线程隔离

线程隔离:也叫舱壁模式,模拟船舱隔板的防水原理,通过限定每个业务能使用的线程数量而将故障业务隔离,避免故障扩散

服务熔断

  • 服务熔断:由断路器统计请求的异常比例或慢调用比例,如果超过阈值则会熔断该业务,则拦截改接口的所有请求
  • 熔断期间所有请求快速失败,全部走fallback逻辑

服务保护技术

SentinelHystrix
线程隔离信号量隔离线程隔离/信号量隔离
熔断策略基于慢调用比例或异常比例基于异常比例
限流策略基于QPS,支持流量整形有限的支持
Fallback支持支持
控制台开箱即用,可配置规则,查看秒级监控,机器发现等不完善
配置方式基于控制台,重启后失效基于注解或配置文件,永久生效

初识Sentinel

Sentinel 的使用可以分为两个部分:

  • 核心库(Jar包):不依赖任何框架/库,能够运行于 Java 8 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。在项目中引入依赖即可实现服务限流、隔离、熔断等功能。
  • 控制台(Dashboard):Dashboard 主要负责管理推送规则、监控、管理机器信息等。

下载Sentinel客户端并在docker中运行

运行jar包启动客户端

  • 端口为8090
  • 名称为sentinel-dashboard
java -Dserver.port=8090 -Dcsp.sentinel.dashboard.server=localhost:8090 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.6.jar

批处理文件sentinel启动器,带打开浏览器功能

@echo off
chcp 65001 >nul
title Sentinel Dashboard Launcher

echo ========================================
echo    启动 Sentinel Dashboard
echo ========================================
echo.

REM 检查必要文件
if not exist "sentinel-dashboard-1.8.6.jar" (
    echo [错误] 未找到 sentinel-dashboard-1.8.6.jar
    pause
    exit
)

REM 启动服务(在新窗口中)
start "Sentinel Dashboard" cmd /k "java -Dserver.port=8090 -Dcsp.sentinel.dashboard.server=localhost:8090 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.6.jar"

echo ✓ 服务正在启动...
echo   请等待15-30秒后访问: http://localhost:8090
echo   默认账号: sentinel
echo   默认密码: sentinel
echo.
echo 将在15秒后自动打开浏览器...
echo 按 Ctrl+C 取消自动打开
timeout /t 15 /nobreak > nul

REM 打开浏览器
start "" "http://localhost:8090"

echo ✓ 浏览器已打开
echo.
echo 注意: 不要关闭Sentinel Dashboard的控制台窗口
echo 按任意键退出启动器...
pause > nul

java中加入依赖

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

加入配置(推荐加入到Nocos

spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8090 # 配置sentinel控制台地址

簇点链路

  • 定义:单机调用链路,是一次请求进入服务后经过的每一个被Sentinel监控的资源链。
  • 默认Sentinel会监控SpringMvc的每一个http接口。限流熔断等都是针对,簇点链路中的资源设置的。而资源名默认就是接口请求的路径

开启请求方式前缀

Restful风格的api请求路劲一般都相同,这会导致簇点资源名称重复,因此我们要修改配置,把请求方式+请求路径作为簇点资源的名称

spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8090
      http-method-specify: true # 开启请求方式前缀

请求限流

  • Sentinel控制台的簇点链路模块中即可配置接口对应的限流模式 请求限流
  • QPS表示:(Queries Per Second)即每秒查询次数,即接口被调用的次数
  • 单机阈值:表示限流的阈值,即接口被调用的次数 请求限流配置

线程隔离

当某一个微服务发生堵塞或故障时,调用该微服务的其他服务可能被拖慢,甚至资源耗尽。因此需要限制调用该服务的最大可用线程数,实现线程隔离 线程隔离

线程隔离配置

Fallback 请求资源失败时返回备用数据

在项目中很多资源都是通过OpenFeign进行调用的,因此需要开启SentinelOpenFeign的支持

feign:
  sentinel:
    enabled: true # 开启sentinel对OpenFeign的支持
  okhttp:
    enabled: true # 开启okhttp

编写Fallback自定义工厂类

package com.hmall.api.fallback;

import cn.hutool.core.collection.ListUtil;
import com.hmall.api.client.ItemClient;
import com.hmall.api.dto.ItemDTO;
import com.hmall.api.dto.OrderDetailDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;

import java.util.Collection;
import java.util.List;

@Slf4j
public class ItemClientFallbackFactor implements FallbackFactory<ItemClient> {
    @Override
    public ItemClient create(Throwable cause) {
        return new ItemClient() {
            @Override
            public List<ItemDTO> queryItemsByIds(Collection<Long> ids) {
                log.error("查询失败线程池满", cause);
                //查询失败返回空集合
                return ListUtil.empty();
            }

            @Override
            public void deductStock(Collection<OrderDetailDTO> items) {
                log.error("扣减库存失败", cause);
                throw new RuntimeException("扣减库存失败");
            }
        };
    }
}

将自定义工厂类注册为一个Bean

public class DefaultFeginConfig {
    @Bean
    public ItemClientFallbackFactor itemClientFallbackFactor() {
        return new ItemClientFallbackFactor();
    }
}

OpenFeign配置类中添加FallbackFactory


@FeignClient(value = "item-service", fallbackFactory = ItemClientFallbackFactor.class)
public interface ItemClient {

    //批量查询商品
    @GetMapping("/items")
    List<ItemDTO> queryItemsByIds(@RequestParam("ids") Collection<Long> ids);

    //扣减库存
    @PutMapping("/items/stock/deduct")
    void deductStock(@RequestBody Collection<OrderDetailDTO> items);
}

服务熔断

  • 服务熔断是解决雪崩问题的重要手段,思路是由熔断器统计服务调用的异常比例,慢请求比例,如果超出阈值则会熔断该服务。
  • 即拦截访问该服务的一切请求;
  • 而当服务恢复时,断路器会放行访问该服务的请求

断路器

断路器 具有三种状态:closed(关闭)、open(打开)、half-open(半开)

  • closed(关闭):此时处于关闭状态,如果服务调用的异常比例,慢请求比例超出阈值,则进入open(打开)状态
  • open(打开):此时处于打开状态,将会拦截所有请求,并返回fallback 数据,open是一个临时的状态,时间可配置,如果到期后,进入half-open(半开)状态
  • half-open(半开)状态:此时处于半开状态,会放行部分请求,如果请求成功,则进入closed(关闭)状态,如果请求失败,则进入open( 打开)状态

配置

服务熔断服务熔断配置

上次更新 2026/2/5 02:04:08