当前位置: 首页 > news >正文

浅聊一下微服务的网关模块

大家好呀!今天来跟大家好好聊聊微服务里超重要的 “守门人”——Spring Cloud Gateway。不管是做微服务架构设计,还是日常开发调试,网关都是绕不开的环节,这篇就从基础到实战,把 Gateway 的核心知识点讲明白,新手也能轻松看懂~

一、先搞懂:为什么需要网关?Gateway 是什么?

首先得明确一个问题:微服务集群里,为啥非要整个网关?
其实网关就像小区的保安亭,所有外部请求都得先经过它,再转发到对应的微服务。没有网关的话,每个微服务都要自己处理权限校验、流量控制,既冗余又难维护,而网关能把这些 “通用活儿” 全揽下来,让微服务专心搞业务。

再说说 Spring Cloud Gateway 本身:它是 Spring Cloud 家族的新成员,基于 Spring 5.0、Spring Boot 2.0 和响应式编程技术开发,性能比老款的 Zuul(基于 Servlet 阻塞编程)好不少,现在基本是微服务网关的首选。

二、Gateway 核心功能:这 3 件事它最擅长

网关不是花架子,核心就干 3 件关键事儿,咱们一个个说:

  1. 权限控制:比如用户没登录、没权限,网关直接拦住请求,不用让请求跑到微服务里再被打回来,效率高多了。
  2. 路由 + 负载均衡:你访问/product-serv/xxx,网关知道要转发到 “商品微服务”;要是商品微服务有 3 个实例,网关还能自动帮你分配请求,实现负载均衡(不用自己再搭 Nginx 那套)。
  3. 限流:比如秒杀活动时请求突然暴涨,网关能按微服务能承受的速度 “放行”,避免微服务被冲垮,保障系统稳定。

放个简单的架构图,大家一看就懂:

注册中心/配置中心(Nacos)↓(微服务注册、网关读配置)
微服务A(连数据库)←→ Feign ←→ Gateway网关 ←→ Feign → 微服务B(连数据库)↓微服务C(连数据库)

三、实战上手:Gateway 快速搭建(超详细步骤)

光说不练假把式,咱们一步步搭建一个基础网关,实现路由功能。

3.1 第一步:创建 Gateway 服务,引入依赖

先建一个 Spring Boot 模块(比如叫api-gateway),然后在pom.xml里加两个关键依赖:网关本身和 Nacos 服务发现(后面负载均衡要用)。

<!-- 网关核心依赖 -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- Nacos服务发现依赖(网关要从Nacos找微服务) -->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

3.2 第二步:写配置文件,搞定路由规则

接下来写application.yml,核心是配置 “服务基本信息” 和 “路由规则”。这里分两个版本,新手先看基础版,再看高级版。

基础版(固定地址转发)

适合刚开始测试,直接指定微服务的 IP + 端口:

yaml

server:port: 7000  # 网关的端口
spring:application:name: api-gateway  # 网关服务名cloud:gateway:routes:  # 路由数组:一个路由对应一个微服务的转发规则- id: product_route  # 路由唯一标识(随便起,但不能重复)uri: http://localhost:8081/  # 转发目标地址(商品微服务的地址)order: 1  # 优先级:数字越小越先执行predicates:  # 断言:满足这个条件才转发- Path=/product-serv/**  # 路径规则:请求路径以/product-serv开头就转发filters:  # 过滤器:转发前处理请求- StripPrefix=1  # 去掉路径的第一级(比如请求/product-serv/product/19,转发后变成/product/19)
高级版(从 Nacos 拉取微服务,支持负载均衡)

实际项目里微服务地址会变,而且可能多实例,这时候就用lb://服务名的方式,让网关从 Nacos 找微服务,自动做负载均衡:

server:port: 7000
spring:application:name: api-gatewaycloud:nacos:discovery:server-addr: 127.0.0.1:8848  # Nacos的地址gateway:discovery:locator:enabled: true  # 允许网关发现Nacos里的微服务routes:- id: product_routeuri: lb://service-product  # lb=负载均衡,service-product是微服务在Nacos的名字order: 1predicates:- Path=/product-serv/**filters:- StripPrefix=1

还要注意:启动类上要加@EnableDiscoveryClient注解,让网关能注册到 Nacos~

3.3 第三步:测试一下

启动网关、Nacos 和商品微服务(假设商品微服务端口 8081,有个接口/product/19):
访问http://localhost:7000/product-serv/product/19,网关会自动转发到http://localhost:8081/product/19,能拿到结果就说明搭建成功啦!

四、断言工厂:网关怎么判断 “该转发给谁”?

前面配置里的predicates: - Path=/product-serv/**,其实是用了 “路径断言”,背后是 Spring 提供的 “断言工厂” 在工作。简单说:咱们写的断言字符串,会被断言工厂转换成判断逻辑,只有满足逻辑的请求才会被转发。

Spring Cloud Gateway 提供了十几种断言工厂,常用的列个表,大家按需选:

断言工厂(对应配置关键词)作用示例
After只转发 “某个时间点之后” 的请求- After=2037-01-20T17:42:47.789-07:00[America/Denver]
Before只转发 “某个时间点之前” 的请求- Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai]
Between转发 “两个时间点之间” 的请求- Between=2037-01-20T17:42:47.789-07:00[America/Denver],2037-01-21T17:42:47.789-07:00[America/Denver]
Cookie请求必须包含指定 Cookie- Cookie=chocolate, ch.p(Cookie 名 chocolate,值含 ch.p)
Header请求必须包含指定 Header- Header=X-Request-Id, \d+(Header 名 X-Request-Id,值是数字)
Host请求必须访问指定域名- Host=.somehost.org,.anotherhost.org
Method只转发指定请求方式(GET/POST 等)- Method=GET,POST
Path路径匹配(最常用)- Path=/red/{segment},/blue/**
Query请求必须包含指定参数- Query=name(必须有 name 参数);- Query=name,Jack(name 参数值是 Jack)
RemoteAddr请求 IP 在指定范围- RemoteAddr=192.168.1.1/24

五、过滤器工厂:请求转发前后能做啥?

网关除了转发请求,还能在转发前 / 后修改请求 / 响应,这就靠 “过滤器工厂”。比如加个请求头、删个响应头,或者做限流,都能用现成的过滤器工厂。

5.1 常用过滤器工厂

Spring 提供了 31 种过滤器工厂,挑几个常用的说说:

过滤器工厂(配置关键词)作用
AddRequestHeader给请求加一个 Header
RemoveRequestHeader从请求里删一个 Header
AddResponseHeader给响应加一个 Header
RemoveResponseHeader从响应里删一个 Header
RequestRateLimiter对请求限流(防止接口被刷爆)

5.2 实战:给请求加个 Header

比如想让所有发往商品微服务的请求,都带上msg: wake up!的请求头,修改application.ymlfilters即可:

routes:- id: product_routeuri: lb://service-productorder: 1predicates:- Path=/product-serv/**filters:- StripPrefix=1- AddRequestHeader=msg, wake up!  # 加请求头

5.3 默认过滤器:对所有路由生效

如果想让某个过滤器对所有路由都生效(比如所有请求都加同一个 Header),不用每个路由都写一遍,用default-filters配置即可:

spring:cloud:gateway:default-filters:  # 默认过滤器,所有路由都生效- AddRequestHeader=msg, wake up!routes:- id: product_route# 其他配置不变...

六、全局过滤器:自定义业务逻辑(比如权限校验)

前面的过滤器都是 “现成的”,只能干固定的活儿。但实际项目里,经常需要自定义逻辑(比如判断用户是否登录、有没有权限),这时候就需要 “全局过滤器”—— 自己写代码实现,想干啥就干啥。

6.1 全局过滤器 vs 普通过滤器

  • 普通过滤器(GatewayFilter):靠配置生效,逻辑固定,只能针对特定路由。
  • 全局过滤器(GlobalFilter):自己写代码,对所有路由生效,逻辑灵活(比如登录校验、权限判断)。

6.2 实战:自定义全局过滤器(权限校验)

需求:所有请求必须带authorization参数,且值为admin,否则拦截(返回 401 未授权)。

步骤 1:写过滤器类

实现GlobalFilter接口,加@Component让 Spring 扫描到,再用@Order指定优先级(数字越小越先执行):

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;@Component
@Order(-1)  // 优先级:-1比默认的高,先执行
public class AuthorizeFilter implements GlobalFilter {// 核心逻辑:处理请求,决定放行还是拦截@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 1. 获取请求参数(从URL里拿)var params = exchange.getRequest().getQueryParams();// 2. 拿到authorization参数的值String auth = params.getFirst("authorization");// 3. 校验:如果参数是admin,就放行if ("admin".equals(auth)) {// 放行:把请求交给下一个过滤器return chain.filter(exchange);}// 4. 拦截:返回401未授权exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);// 结束请求处理return exchange.getResponse().setComplete();}
}
步骤 2:测试
  • 访问http://localhost:7000/product-serv/product/19?authorization=admin:正常放行,返回结果。
  • 访问http://localhost:7000/product-serv/product/19(没带参数),或参数值不是 admin:返回 401,被拦截。

6.3 过滤器执行顺序

请求进入网关后,会碰到 3 类过滤器:默认过滤器(default-filters)、路由过滤器(routes 里的 filters)、全局过滤器(GlobalFilter)。它们的执行顺序按以下规则:

  1. 所有过滤器都有order值,order越小,越先执行。
  2. 全局过滤器的order自己指定(@Order 注解)。
  3. 默认过滤器和路由过滤器的order由 Spring 自动分配,按配置顺序从 1 开始递增。
  4. order相同:默认过滤器 > 路由过滤器 > 全局过滤器。

七、跨域问题:网关怎么解决?

做前后端分离项目时,肯定会碰到 “跨域”—— 浏览器出于安全考虑,禁止前端访问不同域名 / 端口的接口。比如前端跑在localhost:8090,网关跑在localhost:7000,直接请求就会被浏览器拦截。

7.1 先懂同源策略

浏览器的 “同源” 指 3 个相同:协议相同(比如都是 http)、域名相同(比如都是www.xxx.com)、端口相同(比如都是 80)。只要有一个不同,就是跨域。

7.2 网关解决跨域:配置 CORS

不用在每个微服务里配跨域,网关统一配就行。修改application.yml,加全局跨域配置:

spring:cloud:gateway:globalcors:  # 全局跨域配置add-to-simple-url-handler-mapping: true  # 解决OPTIONS请求被拦截问题corsConfigurations:'[/**]':  # 对所有路径生效allowedOrigins:  # 允许哪些前端域名访问- "http://localhost:8090"allowedMethods:  # 允许的请求方式- "GET"- "POST"- "PUT"- "DELETE"- "OPTIONS"allowedHeaders: "*"  # 允许前端带任何HeaderallowCredentials: true  # 允许前端带CookiemaxAge: 360000  # 跨域校验结果的有效期(1小时,避免频繁校验)

配完重启网关,前端再请求就不会有跨域问题了~

总结

本篇把 Spring Cloud Gateway 的核心知识点都覆盖了:从 “为什么需要网关”,到搭建、路由、断言、过滤器、全局逻辑、跨域解决,每个点都带了实战代码,新手跟着做就能上手。实际项目里,网关还能结合限流(比如用 Redis 实现)、日志收集等功能,后续有机会再跟大家深入聊~

如果有疑问,欢迎评论区交流呀!


文章转载自:

http://AaHwaWxc.fhtmp.cn
http://GOi2WwXR.fhtmp.cn
http://yT2yAXVw.fhtmp.cn
http://sE1Fbh6N.fhtmp.cn
http://mMSL1PQs.fhtmp.cn
http://TYDISv9R.fhtmp.cn
http://T7wI3I0c.fhtmp.cn
http://28d17FA1.fhtmp.cn
http://PreiMzZL.fhtmp.cn
http://7rSHEoGN.fhtmp.cn
http://g0aDnI2D.fhtmp.cn
http://fiOwwfQl.fhtmp.cn
http://mlns3cly.fhtmp.cn
http://mAXvYM6A.fhtmp.cn
http://bYuKNjAD.fhtmp.cn
http://yfo3KFgZ.fhtmp.cn
http://GgV79S2C.fhtmp.cn
http://imhC5O1V.fhtmp.cn
http://IsaaIS0g.fhtmp.cn
http://iBgWsPS2.fhtmp.cn
http://PH0h8m7P.fhtmp.cn
http://JODZZs82.fhtmp.cn
http://AzkKrnS5.fhtmp.cn
http://5wfiMLoh.fhtmp.cn
http://QDSea4lg.fhtmp.cn
http://AHNaqMJz.fhtmp.cn
http://NAbxqDOA.fhtmp.cn
http://4rZull2E.fhtmp.cn
http://DH6HyPu7.fhtmp.cn
http://oJzxcTnl.fhtmp.cn
http://www.dtcms.com/a/374041.html

相关文章:

  • 硬件开发2-ARM基本概要
  • C++11第二弹(右值引用与移动语义)
  • 数电实验二连线
  • MQTT+WebSocket工业协议实战:高并发SCADA系统通信架构设计
  • Claude-Flow AI协同开发:基础入门之 AI编排
  • Android面试指南(七)
  • 西嘎嘎学习 - C++修饰符类型 - Day 5
  • 明远智睿RK3568核心板:199元解锁多行业智能新可能
  • LeetCode算法日记 - Day 36: 基本计算器II、字符串解码
  • linux系统address already in use问题解决
  • ArcGIS学习-17 实战-密度分析
  • 08 修改自己的Centos的软件源
  • 柯美bizhub 206复印机报 警告 维修召唤(M2) 维修召唤如何解决 如何维修
  • Vue3 页面切换白屏问题解决方案
  • [硬件电路-168]:Multisim - Multisim提供的用于学习参考电路有哪些?存放位置?
  • 使用kettle批量调用大模型
  • 【系统分析师】第1章-基础知识:绪论(核心总结)
  • docker-容器
  • ARM架构详解:从内核到异常处理
  • Redis缓存击穿、雪崩、穿透
  • Go正则表达式实战指南
  • 保持元素可见但不可访问的方法: `inert`
  • ClaudeCode稳定备用方案:API接入详解
  • 【教程】Ansible 环境部署
  • Linux-信号量
  • 3000h CeB₆ 灯丝加持的 Phenom XL G3 扫描电镜技术亮点
  • C语言scanf函数的空格问题
  • 【Git】使用GitCode的全局配置
  • 论文阅读:ACL 2023 MEETINGQA: Extractive Question-Answering on Meeting Transcripts
  • Docker Compose healthcheck介绍(监控容器中服务的实际健康状态)数据库健康检查pg_isready