Spring Boot/Cloud集成Sentinel实现黑白名单(授权)控制及初始本地化规则 | Spring Cloud 25
创始人
2025-05-30 08:59:42

一、前言

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。 Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

在前面我们通过以下章节对Sentinel有了基础的了解:

Sentinel:分布式系统的流量防卫兵 | Spring Cloud 19

Sentinel:资源与规则定义 | Spring Cloud 20

Sentinel:原理深入浅出解读 | Spring Cloud 21

Sentinel:流量控制规则定义详解 | Spring Cloud 22

Spring Boot/Cloud集成Sentinel实现流量控制 | Spring Cloud 23

Spring Boot/Cloud集成Sentinel实现流量控制 (二) | Spring Cloud 24

现在开始我们正式学习SentinelSpring Boot/Cloud中的集成使用。

书接上回,本节进行对以下部分进行集成演示:

  • 黑白名单(授权)控制
    • 初始化过本地规则
    • 自定义来源信息
  • 资源清理

知识点,当应用的 ApplicationContext 中存在对应的Bean的类型时,会进行自动化设置

存在Bean的类型操作作用
UrlCleanerWebCallbackManager.setUrlCleaner(urlCleaner)资源清理(比如将满足 /foo/:idURL 都归到 /foo/* 资源下)
UrlBlockHandlerWebCallbackManager.setUrlBlockHandler(urlBlockHandler)自定义限流处理逻辑
RequestOriginParserWebCallbackManager.setRequestOriginParser(requestOriginParser)设置来源信息

二、黑白名单控制

2.1 黑白名单控制简介

很多时候,我们需要根据调用来源来判断该次请求是否允许放行,这时候可以使用 Sentinel 的来源访问控制(黑白名单控制)的功能。

来源访问控制根据资源的请求来源(origin)限制资源是否通过:

  • 若配置白名单则只有请求来源位于白名单内时才可通过
  • 若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过

调用方信息通过 ContextUtil.enter(resourceName, origin) 方法中的 origin 参数传入。

2.2 规则配置

来源访问控制规则(AuthorityRule)非常简单,主要有以下配置项:

  • resource:资源名,即限流规则的作用对象。
  • limitApp:对应的黑名单/白名单,不同 origin 用 , 分隔,如 appA,appB
  • strategy:限制模式,AUTHORITY_WHITE 为白名单模式,AUTHORITY_BLACK 为黑名单模式,默认为白名单模式。

三、项目集成 Sentinel

以上篇文章的sentinel-nacos-consumer模块为基础进行扩展。

在这里插入图片描述

3.1 初始化本地规则

Sentinel 提供多样化的 SPI 接口用于提供扩展的能力。

其中包括:初始化过程扩展,供 InitFunc SPI接口,添加自定义的一些初始化逻辑,如动态规则源注册。

3.1.1 本地文件数据源

com/gm/sentinel_nacos_consumer/init/FileDataSourceInit.java

import com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource;
import com.alibaba.csp.sentinel.datasource.FileWritableDataSource;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.WritableDataSource;
import com.alibaba.csp.sentinel.init.InitFunc;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.transport.util.WritableDataSourceRegistry;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import java.net.URLDecoder;
import java.util.List;public class FileDataSourceInit implements InitFunc {@Overridepublic void init() throws Exception {loadAuthorityRule();loadFlowRule();}private  String encodeJson(T t) {return JSON.toJSONString(t);}private void loadAuthorityRule() throws Exception {ClassLoader classLoader = getClass().getClassLoader();String authorityRulePath = URLDecoder.decode(classLoader.getResource("rules/AuthorityRule.json").getFile(), "UTF-8");ReadableDataSource> ds = new FileRefreshableDataSource<>(authorityRulePath, source -> JSON.parseObject(source, new TypeReference>() {}));// 将可读数据源注册至 AuthorityRuleManager.AuthorityRuleManager.register2Property(ds.getProperty());WritableDataSource> wds = new FileWritableDataSource<>(authorityRulePath, this::encodeJson);// 将可写数据源注册至 transport 模块的 WritableDataSourceRegistry 中.// 这样收到控制台推送的规则时,Sentinel 会先更新到内存,然后将规则写入到文件中.WritableDataSourceRegistry.registerAuthorityDataSource(wds);}private void loadFlowRule() throws Exception {ClassLoader classLoader = getClass().getClassLoader();String flowRulePath = URLDecoder.decode(classLoader.getResource("rules/FlowRule.json").getFile(), "UTF-8");ReadableDataSource> ds = new FileRefreshableDataSource<>(flowRulePath, source -> JSON.parseObject(source, new TypeReference>() {}));// 将可读数据源注册至 FlowRuleManager.FlowRuleManager.register2Property(ds.getProperty());WritableDataSource> wds = new FileWritableDataSource<>(flowRulePath, this::encodeJson);// 将可写数据源注册至 transport 模块的 WritableDataSourceRegistry 中.// 这样收到控制台推送的规则时,Sentinel 会先更新到内存,然后将规则写入到文件中.WritableDataSourceRegistry.registerFlowDataSource(wds);}
}

本地文件数据源会定时轮询文件的变更,读取规则。这样我们既可以在应用本地直接修改文件来更新规则,也可以通过 Sentinel 控制台推送规则。以本地文件数据源为例,推送过程如下图所示:
在这里插入图片描述
首先 Sentinel 控制台通过 API 将规则推送至客户端并更新到内存中,接着注册的写数据源会将新的规则保存到本地的文件中。使用 pull 模式的数据源时一般不需要对 Sentinel 控制台进行改造。

这种实现方法好处是简单,不引入新的依赖,坏处是无法保证监控数据的一致性。

3.3.2 通过 SPI 注册 InitFunc 实现类

src/main/resources/META-INF/services/com.alibaba.csp.sentinel.init.InitFunc

com.gm.sentinel_nacos_consumer.init.FileDataSourceInit

3.2 自定义设置来源信息

利用上文提到的知识点,自定义RequestOriginParser实现设置来源信息。

com/gm/sentinel_nacos_consumer/component/CustomRequestOriginParser.java

import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;@Component
public class CustomRequestOriginParser implements RequestOriginParser {@Overridepublic String parseOrigin(HttpServletRequest httpServletRequest) {String origin = httpServletRequest.getParameter("origin");if (!StringUtils.isEmpty(origin)) {return origin;}return httpServletRequest.getRemoteHost();}
}

3.3 编辑本地规则文件

授权规则src/main/resources/rules/AuthorityRule.json

[{"resource":"message","limitApp":"127.0.0.1","strategy":0
}]

流量控制规则src/main/resources/rules/FlowRule.json

[]

3.4 资源清理配置

利用上文提到的知识点,自定义UrlCleaner满足如:/urlCleaner/:idURL 都归到 /urlCleaner/* 资源下。

com/gm/sentinel_nacos_consumer/component/CustomUrlCleaner.java

import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.UrlCleaner;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.List;@Slf4j
@Component
public class CustomUrlCleaner implements UrlCleaner {@Value("#{'${url-cleaner.list}'.split(',')}")private List list;@Overridepublic String clean(String s) {log.info(s);if (StringUtils.isBlank(s)) {return s;}for (String url : list) {if (s.startsWith(url)) {return url + "*";}}return s;}
}

com/gm/sentinel_nacos_consumer/controller/ConsumerController.java新增用于测试资源清理的请求:

    /*** 测试UrlCleaner自定义实现URL归类** @param value* @return*/@RequestMapping(value = "say/{value}", method = RequestMethod.GET)public String say(@PathVariable String value) {return value;}/*** 测试UrlCleaner自定义实现URL归类** @param value* @return*/@RequestMapping(value = "clear/{value}", method = RequestMethod.GET)public String clear(@PathVariable String value) {return value;}

调整配置文件src/main/resources/bootstrap.yml新增要处理的资源清理请求:

url-cleaner:list: /clean/,/say/

3.5 黑白名单控制效果测试

先访问:http://127.0.0.1:3000/sayHelloDirect 测试功能是否正常访问:
在这里插入图片描述
再次访问:http://192.168.1.82:3000/sayHelloDirect 验证黑白名单控制是否生效:

在这里插入图片描述
通过Sentinel 控制台将原本地规则文件设置的限制模式strategy由白名单切换至黑名单:

在这里插入图片描述

再次访问:http://192.168.1.82:3000/sayHelloDirect 验证黑白名单控制是否生效:

在这里插入图片描述

验证 Sentinel 控制台推送推着是否已保存至本地文件:

在这里插入图片描述

注意文件目录为:target/classes/rules/AuthorityRule.json

3.6 资源清理效果测试

先访问:http://127.0.0.1:3000/say/hello 测试功能是否正常访问:

在这里插入图片描述
通过Sentinel 控制台资源清理效果:

在这里插入图片描述

相关内容

热门资讯

国际荐酒师(香港)协会(IRW... 国际荐酒师(香港)协会(IRWA): 以“荐”为媒,架设全球酒业文化与商业的桥梁 国际荐酒师(香港...
2025海南餐饮综合推荐榜:海... 2025年,海南餐饮市场迎来了重大的变革与机遇。在政策支持下,诸如《海南省餐饮业发展规划(2021-...
这道被全家点名的冬日家常菜,香... 冬天的餐桌,有一道菜总是被反复安利。 不张扬、不复杂,却一上桌就被抢光——香肠什锦炒时蔬。 土豆软糯...
灶间甜香:一碗面糊烙出的芝麻脆... 午后的厨房总该有些甜香萦绕,这道芝麻脆饼便是最省心的选择。无需复杂配料,打开橱柜就能凑齐全部食材——...
地道泰国风味儿!泰铺华北首店落... 齐鲁晚报·齐鲁壹点记者 管悦 近年来,泰国菜以其独特的酸辣风味与鲜明的地域文化,在国内餐饮市场迅速崛...