网关限流:SpringCloud Gateway + Sentinel 实战
在微服务架构中网关作为流量入口承担着请求转发、鉴权、限流等核心职责。当流量突发激增时若未做限流保护后端服务可能被压垮导致整个系统雪崩。SpringCloud Gateway 是主流的微服务网关而 Sentinel 是阿里开源的流量治理组件二者结合可实现高效、灵活的网关限流。本文将从实战角度出发详细讲解如何整合 SpringCloud Gateway 与 Sentinel完成网关限流的配置、开发、测试全流程所有代码可直接复制使用方便大家下载部署。一、核心技术选型说明本次实战选用的技术版本均为当前稳定版避免版本兼容问题方便大家直接搭建环境SpringBoot2.7.12SpringCloud 依赖的基础版本稳定无坑SpringCloud2021.0.5Hoxton 之后的稳定版本适配 Gateway 最新特性SpringCloud Gateway3.1.5微服务网关核心替代 Zuul 成为主流Sentinel1.8.6阿里开源流量治理组件支持限流、熔断、降级适配 GatewaySentinel Dashboard1.8.6Sentinel 可视化控制台用于配置限流规则、监控流量核心优势二者整合无需额外开发复杂逻辑Sentinel 提供了专门的 Gateway 适配器可快速实现基于路径、参数、IP、用户等多种维度的限流且支持动态调整规则无需重启服务。二、环境准备可直接下载复用2.1 搭建 Sentinel Dashboard 控制台Sentinel 控制台用于可视化配置限流规则、查看流量监控数据步骤如下可直接下载对应版本包下载 Sentinel Dashboard 压缩包sentinel-dashboard-1.8.6.jar直接点击即可下载启动控制台命令行执行无需额外配置java -jar sentinel-dashboard-1.8.6.jar --server.port8080访问控制台浏览器输入 http://localhost:8080默认账号/密码sentinel/sentinel登录后即可看到空控制台后续服务接入后会自动注册2.2 搭建 SpringCloud Gateway 项目可下载完整代码创建 Maven 项目引入核心依赖pom.xml 配置如下可直接复制版本与上述一致parentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.7.12/versionrelativePath//parentpropertiesspring-cloud.version2021.0.5/spring-cloud.versionsentinel.version1.8.6/sentinel.version/propertiesdependenciesgt;!--SpringCloudGateway核心依赖--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactIdlt;/dependencygt;!-- Sentinel 核心依赖 --dependencygroupIdcom.alibaba.csp/groupIdartifactIdsentinel-core/artifactIdversion${sentinel.version}lt;/versiongt;lt;/dependencygt;!-- Sentinel 适配 Gateway 依赖关键 --dependencygroupIdcom.alibaba.csp/groupIdartifactIdsentinel-spring-cloud-gateway-adapter/artifactIdversion${sentinel.version}lt;/versiongt;lt;/dependencygt;!-- Sentinel 与控制台通信依赖 --dependencygroupIdcom.alibaba.csp/groupIdartifactIdsentinel-transport-simple-http/artifactIdversion${sentinel.version}/version/dependencygt;!--测试依赖--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency/dependenciesdependencyManagementdependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-dependencies/artifactIdversion${spring-cloud.version}/versiontypepom/typescopeimport/scope/dependency/dependencies/dependencyManagementbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/build三、实战开发核心步骤可直接下载代码运行3.1 配置文件application.yml配置 Gateway 路由、Sentinel 控制台地址以及限流相关的基础配置内容如下可直接复制server:port:8081# 网关端口避免与 Sentinel 控制台 8080 冲突spring:application:name:gateway-sentinel-demo# 服务名会显示在 Sentinel 控制台cloud:gateway:routes:# 测试路由1转发到百度可替换为自己的后端服务地址-id:baidu-routeuri:https://www.baidu.compredicates:-Path/baidu/**# 匹配路径访问 http://localhost:8081/baidu 会转发到百度filters:-StripPrefix1# 去掉路径前缀 /baidu实际转发到 https://www.baidu.com# 测试路由2转发到本地模拟服务后续可替换为自己的微服务-id:local-routeuri:http://localhost:8082# 假设本地有一个 8082 端口的后端服务predicates:-Path/api/**filters:-StripPrefix1# Sentinel 配置sentinel:transport:dashboard:localhost:8080# 连接 Sentinel 控制台地址port:8719# 与控制台通信的端口默认 8719若占用可修改# 关闭 Sentinel 控制台懒加载默认懒加载第一次请求后才会注册到控制台eager:true# 网关限流相关配置gateway:enabled:true# 开启 Gateway 限流order:-1# 限流过滤器顺序确保优先执行3.2 核心配置类SentinelGatewayConfig配置 Sentinel 网关限流的规则、异常处理逻辑实现限流后自定义响应如返回 JSON 提示代码如下可直接复制packagecom.example.gatewaysentineldemo.config;importcom.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;importcom.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;importcom.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;importcom.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;importcom.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;importcom.alibaba.csp.sentinel.slots.block.RuleConstant;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.core.io.buffer.DataBuffer;importorg.springframework.http.HttpStatus;importorg.springframework.http.MediaType;importorg.springframework.web.reactive.function.server.ServerResponse;importorg.springframework.web.server.ServerWebExchange;importreactor.core.publisher.Mono;importjavax.annotation.PostConstruct;importjava.util.Collections;importjava.util.HashMap;importjava.util.Map;/** * Sentinel 网关限流配置类 */ConfigurationpublicclassSentinelGatewayConfig{/** * 注入 Sentinel 网关过滤器核心 */BeanpublicSentinelGatewayFiltersentinelGatewayFilter(){returnnewSentinelGatewayFilter();}/** * 初始化网关限流规则硬编码方式后续可通过控制台动态配置 */PostConstructpublicvoidinitGatewayFlowRules(){GatewayFlowRulerule1newGatewayFlowRule();rule1.setResource(baidu-route);// 限流资源名对应 application.yml 中的路由 idrule1.setGrade(RuleConstant.FLOW_GRADE_QPS);// 限流阈值类型QPS每秒请求数rule1.setCount(5);// 限流阈值每秒最多 5 个请求rule1.setIntervalSec(1);// 统计时间窗口单位秒GatewayFlowRulerule2newGatewayFlowRule();rule2.setResource(local-route);rule2.setGrade(RuleConstant.FLOW_GRADE_QPS);rule2.setCount(3);// 本地路由每秒最多 3 个请求// 将规则添加到规则管理器GatewayRuleManager.loadRules(Collections.singletonList(rule1));// 若需添加多个规则可使用 Arrays.asList(rule1, rule2)}/** * 自定义限流异常响应返回 JSON 格式更友好 */PostConstructpublicvoidinitBlockHandler(){BlockRequestHandlerblockRequestHandlernewBlockRequestHandler(){OverridepublicMonoServerResponsehandleRequest(ServerWebExchangeexchange,Throwablet){// 自定义响应内容MapString,Objectgt;responsenewHashMap();response.put(code,429);response.put(message,请求过于频繁请稍后再试网关限流);response.put(success,false);// 返回 JSON 响应状态码 429Too Many RequestsreturnServerResponse.status(HttpStatus.TOO_MANY_REQUESTS).contentType(MediaType.APPLICATION_JSON).bodyValue(response);}};GatewayCallbackManager.setBlockHandler(blockRequestHandler);}}3.3 启动类GatewaySentinelDemoApplication简单启动类无需额外配置代码如下packagecom.example.gatewaysentineldemo;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;SpringBootApplicationpublicclassGatewaySentinelDemoApplication{publicstaticvoidmain(String[]args){SpringApplication.run(GatewaySentinelDemoApplication.class,args);System.out.println(网关限流服务启动成功访问地址http://localhost:8081);}}四、测试验证实战关键确保限流生效测试工具Postman、JMeter 或浏览器高频刷新这里用浏览器和 Postman 演示步骤如下4.1 启动服务注册到 Sentinel 控制台启动 Sentinel 控制台已启动的忽略启动 Gateway 项目GatewaySentinelDemoApplication访问 Sentinel 控制台http://localhost:8080登录后可看到gateway-sentinel-demo服务已注册若未出现可访问一次网关接口触发注册如 http://localhost:8081/baidu。4.2 测试硬编码限流规则我们在配置类中给baidu-route配置了 QPS5每秒最多 5 个请求测试步骤浏览器访问 http://localhost:8081/baidu正常情况下会转发到百度页面高频刷新该地址每秒刷新超过 5 次会看到自定义的限流响应JSON 格式{ code: 429, message: 请求过于频繁请稍后再试网关限流, success: false }查看 Sentinel 控制台进入「网关流控规则」可看到硬编码的规则已生效同时在「实时监控」中能看到流量曲线和限流次数。4.3 测试动态配置限流规则推荐无需重启服务实际生产中硬编码规则不便于修改我们可以通过 Sentinel 控制台动态配置限流规则步骤如下进入 Sentinel 控制台 → 选中「gateway-sentinel-demo」服务 → 点击「网关流控规则」→ 点击「新增网关流控规则」配置规则以 local-route 为例资源名local-route必须与 application.yml 中的路由 id 一致限流阈值类型QPS限流阈值2每秒最多 2 个请求其他配置默认点击「保存」。用 Postman 发送请求http://localhost:8081/api/test假设 8082 端口服务有 /test 接口高频发送请求每秒超过 2 次会触发限流返回自定义 JSON 响应修改限流阈值如改为 10无需重启 Gateway 服务再次测试限流阈值会立即生效。五、进阶配置可选提升生产可用性5.1 多种限流维度配置除了基于路由 id 限流Sentinel 还支持多种限流维度可在控制台或配置类中配置基于路径限流资源名填写具体路径如 /api/user基于 IP 限流在限流规则中配置「针对来源」填写具体 IP如 127.0.0.1限制某个 IP 的请求频率基于参数限流通过自定义 Sentinel 资源提取器根据请求参数如 userId限流避免单个用户高频请求。5.2 限流规则持久化解决重启丢失问题默认情况下Sentinel 控制台配置的规则会保存在内存中服务重启后规则丢失生产环境需配置规则持久化推荐两种方式基于 Nacos 持久化将限流规则配置到 NacosSentinel 从 Nacos 读取规则修改 Nacos 配置后自动同步基于 Apollo 持久化与 Nacos 类似适合已使用 Apollo 作为配置中心的项目。后续可单独出一篇规则持久化实战本文暂不展开核心依赖可参考 Sentinel 官方文档5.3 自定义限流异常页面若不想返回 JSON 响应可自定义限流异常页面修改配置类中的initBlockHandler方法返回 HTML 页面即可示例// 自定义限流异常页面替换原有 blockRequestHandlerPostConstructpublicvoidinitBlockHandler(){BlockRequestHandlerblockRequestHandlernewBlockRequestHandler(){OverridepublicMonoServerResponsehandleRequest(ServerWebExchangeexchange,Throwablet){// 返回 HTML 页面Stringhtmlhtmlbodyh1 styletext-align:center;margin-top:50px请求过于频繁请稍后再试/h1/body/html;DataBufferbufferexchange.getResponse().bufferFactory().wrap(html.getBytes());returnServerResponse.status(HttpStatus.TOO_MANY_REQUESTS).contentType(MediaType.TEXT_HTML).bodyValue(buffer);}};GatewayCallbackManager.setBlockHandler(blockRequestHandler);}六、常见问题及解决方案避坑指南问题1Gateway 服务启动后Sentinel 控制台看不到服务解决方案1. 检查 application.yml 中 Sentinel 控制台地址配置是否正确2. 开启 sentinel.eagertrue关闭懒加载3. 访问一次网关接口触发服务注册。问题2限流规则配置后不生效解决方案1. 资源名必须与 Gateway 路由 id 或路径一致2. 限流阈值类型QPS/并发数选择正确3. 检查 Sentinel 依赖是否完整尤其是 sentinel-spring-cloud-gateway-adapter。问题3自定义异常响应不生效解决方案确保配置类中 initBlockHandler 方法被 PostConstruct 注解修饰且 SentinelGatewayFilter 已注入。问题4Sentinel 控制台启动失败提示端口占用解决方案修改启动命令指定端口java -jar sentinel-dashboard-1.8.6.jar --server.port8083替换为未占用端口。七、总结本文通过 SpringCloud Gateway Sentinel 实战完成了网关限流的从环境搭建到测试验证的全流程核心亮点技术选型稳定版本兼容代码可直接复用适合快速落地支持硬编码和动态配置两种限流规则动态配置无需重启服务适配生产需求自定义限流响应可根据业务需求返回 JSON 或 HTML 页面提供完整代码下载降低实战难度新手也能快速上手。在实际生产中可根据业务场景调整限流阈值、限流维度结合规则持久化、熔断降级等功能打造更健壮的微服务网关。后续将继续分享 Sentinel 熔断降级、规则持久化等进阶内容欢迎关注补充若需实现更复杂的限流场景如基于用户角色限流、多维度组合限流可留言交流后续补充对应的实战代码。