Spring Cloud Gateway 实战:网关配置与 Sentinel 限流详解

在微服务架构中,网关扮演着统一入口、负载均衡、安全认证、限流等多种角色。Spring Cloud Gateway 是 Spring Cloud 官方推出的新一代网关组件,相比于第一代 Netflix Zuul,性能更强、功能更丰富,且基于 Netty 和 WebFlux 开发,完全非阻塞、响应式。

本文将详细介绍 Spring Cloud Gateway 的基础配置、与 Nacos 注册中心的整合,以及如何基于 Sentinel 进行网关限流(包括路由限流和 API 分组限流)。


什么是 Spring Cloud Gateway

Spring Cloud Gateway 是 Spring Cloud 官方网关组件,属于第二代网关解决方案,替代了 Zuul。

优点

  • 基于 Netty + WebFlux,性能更高
  • 支持丰富的路由谓词和过滤器
  • 与 Spring Cloud 生态无缝集成

注意事项

  • 不兼容 Servlet(例如 SpringMVC)
  • 不支持 war 包部署,只能以 jar 形式运行

快速上手 Spring Cloud Gateway

引入依赖

一定不能引入 spring-boot-starter-web,因为它基于 Servlet,会导致冲突。

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

application.yml 配置

以下为最简单的静态路由配置(不使用注册中心):

server:port: 8010
spring:application:name: gatewaycloud:gateway:routes:- id: provider_routeuri: http://localhost:8081predicates:- Path=/provider/**filters:- StripPrefix=1- id: consumer_routeuri: http://localhost:8181predicates:- Path=/consumer/**filters:- StripPrefix=1

说明

  • id:路由标识
  • uri:转发地址
  • predicates:请求匹配条件(如路径)
  • filters:过滤器(如去前缀)

整合 Nacos 服务注册中心

通过 Nacos 让 Gateway 自动发现服务,无需手动配置 routes。

引入依赖

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

修改配置

server:port: 8010
spring:application:name: gatewaycloud:gateway:discovery:locator:enabled: true

开启后,Gateway 会自动根据 Nacos 上注册的服务自动创建路由。


Gateway 限流(基于 Sentinel)

在实际生产环境中,网关限流非常重要,可以防止后端服务被恶意或突发大流量冲击。

引入依赖

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>

基于路由 ID 的限流

配置 routes

server:port: 8010
spring:application:name: gatewaycloud:gateway:discovery:locator:enabled: trueroutes:- id: provider_routeuri: http://localhost:8081predicates:- Path=/provider/**filters:- StripPrefix=1

配置限流类

@Configuration
public class GatewayConfiguration {private final List<ViewResolver> viewResolvers;private final ServerCodecConfigurer serverCodecConfigurer;public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,ServerCodecConfigurer serverCodecConfigurer) {this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);this.serverCodecConfigurer = serverCodecConfigurer;}@Bean@Order(Ordered.HIGHEST_PRECEDENCE)public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);}@PostConstructpublic void initGatewayRules() {Set<GatewayFlowRule> rules = new HashSet<>();rules.add(new GatewayFlowRule("provider_route").setCount(1).setIntervalSec(1));GatewayRuleManager.loadRules(rules);}@Bean@Order(Ordered.HIGHEST_PRECEDENCE)public GlobalFilter sentinelGatewayFilter() {return new SentinelGatewayFilter();}@PostConstructpublic void initBlockHandlers() {BlockRequestHandler blockRequestHandler = (exchange, throwable) -> {Map<String, Object> map = new HashMap<>();map.put("code", 0);map.put("msg", "被限流了");return ServerResponse.status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(map));};GatewayCallbackManager.setBlockHandler(blockRequestHandler);}
}

被限流后,返回自定义 JSON 响应 {"code":0,"msg":"被限流了"}


基于 API 分组的限流

除了基于路由 ID 的限流,还可以针对 URL 前缀或具体路径进行分组限流。

修改配置

只开启服务发现,不写 routes。

server:port: 8010
spring:application:name: gatewaycloud:gateway:discovery:locator:enabled: true

配置限流类

@Configuration
public class GatewayConfiguration {private final List<ViewResolver> viewResolvers;private final ServerCodecConfigurer serverCodecConfigurer;public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,ServerCodecConfigurer serverCodecConfigurer) {this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);this.serverCodecConfigurer = serverCodecConfigurer;}@Bean@Order(Ordered.HIGHEST_PRECEDENCE)public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);}@PostConstructpublic void initGatewayRules() {Set<GatewayFlowRule> rules = new HashSet<>();rules.add(new GatewayFlowRule("provider_api1").setCount(1).setIntervalSec(1));rules.add(new GatewayFlowRule("provider_api2").setCount(1).setIntervalSec(1));GatewayRuleManager.loadRules(rules);}@Bean@Order(Ordered.HIGHEST_PRECEDENCE)public GlobalFilter sentinelGatewayFilter() {return new SentinelGatewayFilter();}@PostConstructpublic void initBlockHandlers() {BlockRequestHandler blockRequestHandler = (exchange, throwable) -> {Map<String, Object> map = new HashMap<>();map.put("code", 0);map.put("msg", "被限流了");return ServerResponse.status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(map));};GatewayCallbackManager.setBlockHandler(blockRequestHandler);}@PostConstructprivate void initCustomizedApis() {Set<ApiDefinition> definitions = new HashSet<>();ApiDefinition api1 = new ApiDefinition("provider_api1").setPredicateItems(new HashSet<ApiPredicateItem>() {{add(new ApiPathPredicateItem().setPattern("/provider/api1/**").setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));}});ApiDefinition api2 = new ApiDefinition("provider_api2").setPredicateItems(new HashSet<ApiPredicateItem>() {{add(new ApiPathPredicateItem().setPattern("/provider/api2/demo1"));}});definitions.add(api1);definitions.add(api2);GatewayApiDefinitionManager.loadApiDefinitions(definitions);}
}

Controller 示例

@RestController
@RequestMapping("/provider")
public class DemoController {@GetMapping("/api1/demo1")public String demo1() {return "demo1";}@GetMapping("/api1/demo2")public String demo2() {return "demo2";}@GetMapping("/api2/demo1")public String demo3() {return "demo3";}@GetMapping("/api2/demo2")public String demo4() {return "demo4";}
}

限流效果

  • /provider/api1/** 前缀限流,每秒允许 1 个请求
  • /provider/api2/demo1 单接口限流,每秒允许 1 个请求

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/86706.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/86706.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/86706.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JAVA-常用API(二)

目录 1.Arrays 1.1认识Arrays 1.2Arrays的排序 2.JDK8的新特性&#xff1a;Lambda表达式 2.1认识Lambda表达式 2.2用Lambda表达式简化代码、省略规则 3.JDK8的新特性&#xff1a;方法引用&#xff08;进一步简化Lambda表达式&#xff09; 3.1 静态方法引用 3.2 实例方法引…

深入理解PHP的命名空间

命名空间是PHP 5.3引入的一个特性&#xff0c;它的主要目的是解决在大型应用程序中可能出现的名称冲突问题。在没有命名空间的情况下&#xff0c;如果两个不同的库或模块定义了相同名称的函数或类&#xff0c;那么在使用这些库或模块的时候就会引发冲突。为了解决这个问题&…

SwiftUI学习笔记day5:Lecture 5 Stanford CS193p 2023

SwiftUI学习笔记day5:Lecture 5 Stanford CS193p 2023 课程链接&#xff1a;Lecture 5 Stanford CS193p 2023代码仓库&#xff1a;iOS课程大纲&#xff1a; Enum 定义&#xff1a;enum MyType { … }关联值&#xff1a;case drink(name: String, oz: Int)匹配&#xff1a;switc…

idea 报错:java: 非法字符: ‘\ufeff‘

idea 报错&#xff1a;java: 非法字符: ‘\ufeff‘ 解决方案&#xff1a;

数据结构与算法之美:图

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《题海拾贝》、《C修炼之路》 欢迎点赞&#xff0c;关注&am…

SpringBoot -- 热部署

9.SpringBoot 热部署&#xff08;自动重启&#xff09; 在实际开发过程中&#xff0c;每次修改代码就得将项目重启&#xff0c;重新部署&#xff0c;对于一些大型应用来说&#xff0c;重启时间需要花费大量的时间成本。对于一个后端开发者来说&#xff0c;重启过程确实很难受啊…

HarmonyOS 5浏览器引擎对WebGL 2.0的支持如何?

以下是HarmonyOS 5浏览器引擎对‌WebGL 2.0‌支持的详细技术分析&#xff1a; 一、核心支持能力 ‌系统能力声明 HarmonyOS 5 浏览器引擎通过 SystemCapability.Graphic.Graphic2D.WebGL2 提供对 WebGL 2.0 的底层支持 支持的关键特性包括&#xff1a; OpenGL ES 3.0 特性…

Class1线性回归

Class1线性回归 买房预测 要根据历史数据来预测一套房子的价格。你发现影响房价的因素有很多&#xff0c;于是你决定使用线性回归模型来预测房价。 影响房价的因素如下&#xff1a; 房屋面积&#xff08;平方米&#xff09; 房龄&#xff08;年&#xff09; 离地铁站的距离&a…

Vue.js 3:重新定义前端开发的进化之路

Vue.js 3&#xff1a;重新定义前端开发的进化之路 引言&#xff1a;一场酝酿已久的革新 2020年9月18日&#xff0c;Vue.js团队以代号"One Piece"正式发布3.0版本&#xff0c;这不仅是框架发展史上的重要里程碑&#xff0c;更是前端工程化领域的一次革命性突破。历经…

Unity性能优化-渲染模块(1)-CPU侧(1)-优化方向

Unity 中渲染方面的优化大致可以划分为以下几块核心内容&#xff1a; CPU 优化 (减少 Draw Calls 和 CPU 瓶颈) GPU 优化 (减少像素着色和 GPU 瓶颈) 内存和显存优化 (Resource Management) 光照优化 (Lighting & Global Illumination) 这四个方面是相互关联的。一个方…

AI矢量图与视频无痕修复:用Illustrator与After Effects解锁创作新维度

最近因一个项目&#xff0c;有机会深度体验了奥地利Blueskyy艺术学院授权的Adobe教育版全家桶&#xff0c;过程中发现了不少令人惊喜的“黑科技”&#xff0c;很想和大家分享这份发掘宝藏的喜悦。一句话总结这次体验&#xff1a;慷慨且稳定。比如&#xff0c;它每周提供高达150…

Maven Javadoc 插件使用详解

Maven Javadoc 插件使用详解 maven-javadoc-plugin 是 Maven 项目中用于生成 Java API 文档的标准插件&#xff0c;它封装了 JDK 的 javadoc 工具&#xff0c;提供了更便捷的配置和集成方式。 一、基本使用 1. 快速生成 Javadoc 在项目根目录执行以下命令&#xff1a; bas…

Apache Kafka 面试应答指南

Apache Kafka 核心知识详解与面试应答指南 一、Apache Kafka 概述 Apache Kafka 作为一款分布式流处理框架,在实时构建流处理应用领域发挥着关键作用。其最广为人知的核心功能,便是作为企业级消息引擎被众多企业采用。 二、消费者组 (一)定义与原理 消费者组是 Kafka 独…

在NVIDIA Jetson和RTX上运行Google DeepMind的Gemma 3N:多模态AI的边缘计算革命

在NVIDIA Jetson和RTX上运行Google DeepMind的Gemma 3N&#xff1a;多模态AI的边缘计算革命 文章目录 在NVIDIA Jetson和RTX上运行Google DeepMind的Gemma 3N&#xff1a;多模态AI的边缘计算革命引言&#xff1a;多模态AI进入边缘计算时代文章结构概览 第一章&#xff1a;Gemma…

iOS打包流程中的安全处理实践:集成IPA混淆保护的自动化方案

随着iOS应用上线节奏的加快&#xff0c;如何在持续集成&#xff08;CI&#xff09;或交付流程中嵌入安全处理手段&#xff0c;成为开发团队构建自动化发布链路时不可忽视的一环。特别是在App已经完成构建打包&#xff0c;准备分发前这一阶段&#xff0c;对IPA进行结构层面的加固…

FFmpeg进行简单的视频编辑与代码写法实例

使用 FFmpeg 进行简单的视频编辑非常强大。它是一个命令行工具&#xff0c;虽然一开始可能看起来有点复杂&#xff0c;但掌握了基本命令后会非常有用。 以下是一些常见的简单视频编辑操作及其 FFmpeg 命令&#xff1a; 1. 剪切视频 如果你想从一个视频中剪切出一段&#xff0…

如何使用免费软件写论文?六个免费论文生成软件使用指南

在学术写作中&#xff0c;利用AI技术和免费的写作工具可以极大地提高效率&#xff0c;尤其对于需要处理大量文献、结构化写作的论文来说&#xff0c;使用合适的软件能节省时间&#xff0c;提升论文质量。这里为您推荐六个免费的论文生成软件&#xff0c;并提供使用指南&#xf…

大数据系统架构实践(二):Hadoop集群部署

大数据系统架构实践&#xff08;二&#xff09;&#xff1a;Hadoop集群部署 文章目录 大数据系统架构实践&#xff08;二&#xff09;&#xff1a;Hadoop集群部署一、Hadoop简介二、部署前准备三、部署Hadoop集群1. 下载并解压安装包2. 配置hadoop-env.sh3. 配置core-site.xml4…

42道Maven高频题整理(附答案背诵版)

1.简述什么是Maven&#xff1f; Maven是一个项目管理和构建自动化工具&#xff0c;主要服务于Java项目。使用Maven&#xff0c;开发者可以方便地管理项目的构建、文档生成、报告、依赖、SCM&#xff08;软件配置管理&#xff09;、发布和分发等过程。 Maven的核心概念是基于项…

【数字后端】- 如何进行时钟树综合?

首先&#xff0c;要明确的是&#xff0c;时钟树综合只有命令去操作这一种方式 CTS的步骤 1、时钟树综合前的准备工作-设置时钟树cell&#xff08;每个项目必做&#xff09; 最简单的项目要设置生长时钟树时可用的clock buffer和clock inverter cell list&#xff0c;如下 此…