微服务网关介绍
在单体应用时代,客户端(Client)直接与后端应用交互。但进入微服务架构后,系统被拆分为成百上千个微服务(如用户服务、订单服务、仓储服务…)。
如果让客户端直接与这些微服务通信,会带来巨大的问题:
- 复杂性爆炸:客户端需要记录所有微服务的地址(IP:Port),一旦后端重构或迁移,前端必须同步修改。
- 安全隐患:所有微服务直接暴露在公网,难以统一进行身份认证(Authentication)和鉴权(Authorization)。
- 跨域问题:每个服务都需要单独处理 CORS。
这时候,我们需要一个**微服务网关 (API Gateway)**。
可以将其比喻为“工业园区的传达室”或“大门保卫处”:
所有外部访客(客户端请求)必须先通过大门(网关)。
- 保安(鉴权):检查你是否有工牌(Token),防止非法人员进入。
- 前台(路由):你问“我要去财务部”,她会告诉你“右转上三楼”(将请求转发给 Finance Service)。
- 围墙(保护):外界无法直接翻墙进入某个具体的办公室(微服务IP不暴露),保护了内部隐私。

核心功能
- **路由转发 (Routing)**:根据请求路径,将请求准确分发到后端微服务。
- **负载均衡 (Load Balancing)**:配合注册中心,将流量分散到服务的多个实例。
- **认证鉴权 (Security)**:统一处理登录校验、签名验证。
- **限流熔断 (Rate Limiting)**:保护后端服务不被突发流量冲垮。
微服务网关选型
市面上主流的网关解决方案主要有以下几种:
1. Nginx / Kong
- Nginx:高性能反向代理服务器,通过 Lua 脚本(OpenResty)扩展。
- Kong:基于 Nginx 和 Lua 开发的商业化 API 网关。
- 优点:性能极高。
- 缺点:二次开发需要掌握 Lua 语言,对 Java 开发团队不友好;更适合作为流量网关(最前端),而非业务网关。
2. Zuul 1.x (Netflix)
- 特点:Spring Cloud Netflix 早期的核心组件。
- 架构:基于 Servlet 2.5,采用阻塞式 I/O (Blocking I/O) 编程模型。
- 痛点:每个请求占用一个线程。在并发量极高、后端服务响应慢(I/O密集型)的场景下,线程池很容易被耗尽,导致性能急剧下降。且目前已停止维护。
3. Spring Cloud Gateway (推荐)
- 血统:Spring Cloud 官方推出的第二代网关,旨在替代 Zuul。
- 架构:基于 Spring Boot 2.x, Spring WebFlux 和 Project Reactor。
- 优势:
- **异步非阻塞 (Non-blocking)**:基于 Netty 运行,使用极少的线程就能处理大量并发请求,资源利用率高。
- 功能丰富:内置了大量路由断言(Predicates)和过滤器(Filters)。
- 生态融合:与 Spring Cloud Alibaba (Nacos, Sentinel) 集成极其方便。
结论:在“慕聘网”项目中,我们毫不犹豫地选择 Spring Cloud Gateway。
微服务网关端口规范
在微服务开发中,为了避免端口冲突和方便管理,我们需要约定一套清晰的端口规范。

我们采用如下的分配策略:
1. 8xxx:系统/网关服务
这部分端口预留给基础设施和网关层。
8888: 配置中心 (Config Server,如果独立部署)8848: Nacos Server8000: API Gateway (微服务网关)8080: Sentinel 控制台
2. 9xxx:公共服务/支撑服务
用于一些通用的、被各个业务线调用的支撑服务。
9000: 接口文档聚合 (Swagger/Knife4j)9001: 监控平台 (Prometheus/Grafana)9002: 文件上传服务 (OSS)9003: 短信服务 (SMS)
3. 6xxx / 7xxx:业务微服务
用于核心业务逻辑的服务。
6001: User Service (用户服务)6002: Company Service (企业服务)7001: Order Service (订单服务)7002: Resume Service (简历服务)
遵循这套规范,开发人员看到端口号就能立刻判断出该服务属于哪一类,极大地降低了沟通成本。
构建微服务网关
既然选定了 Spring Cloud Gateway,接下来我们就动手搭建一个网关微服务。
1. 创建模块
在 imooc-hire 父工程下创建一个新的 Maven 模块,命名为 gateway。
2. 引入依赖 (Critical)
这是最容易踩坑的地方!Spring Cloud Gateway 基于 WebFlux (Netty),而普通的 Spring Boot Web 项目基于 Servlet (Tomcat)。两者不兼容!
如果你的项目中(或者引入的公共模块 hire-common 中)包含 spring-boot-starter-web,必须将其排除,否则启动会报错。
gateway/pom.xml:
1 | <dependencies> |
3. 启动类配置
由于网关通常不需要直接连接数据库(除非将路由存储在数据库中),我们在启动时可以排除数据库自动配置,加快启动速度。
Application.java:
1 |
|
4. 核心配置与路由规则
配置 Nacos 地址、网关端口以及路由规则。这是网关的灵魂所在。
application.yml:
1 | server: |
- id: 路由的唯一标识。
- uri: 目标服务地址。使用
lb://前缀表示从 Nacos 获取服务列表并进行负载均衡。 - predicates (断言): 路由匹配规则。最常用的是
Path,表示请求路径匹配该规则时才进行转发。 - globalcors: 统一解决跨域问题,无需在每个微服务中单独配置。
启动 gateway 服务后,刷新 Nacos 控制台,你应该能看到 gateway 已经成功注册。
负载均衡 (LoadBalancer)
在早期的 Spring Cloud 版本中,我们要实现负载均衡,闭着眼都会选 Ribbon。但随着 Netflix 组件的全面停更,Ribbon 也进入了维护模式。
Spring Cloud 官方推出了自己的替代方案:Spring Cloud LoadBalancer。
1. 移除 Ribbon,拥抱 LoadBalancer
在 Spring Cloud 2020.0.0 (Ilford) 版本之后,spring-cloud-starter-netflix-ribbon 已经被彻底移除。如果我们使用新版 Spring Cloud,必须显式引入 LoadBalancer。
我们在构建网关时已经引入了它:
1 | <dependency> |
2. 在网关中的应用
引入 LoadBalancer 后,Gateway 就能通过服务名(Service ID)解析出具体的服务实例 IP 列表,并根据负载均衡策略(默认轮询)分发请求。
这也是为什么我们在配置路由时(下一章会讲),URI 都是以 lb:// 开头的:
1 | uri: lb://user-service |
lb: 代表 LoadBalancer。user-service: 注册在 Nacos 中的服务名。
Gateway 解析到 lb 协议后,会利用 LoadBalancer 从 Nacos 获取 user-service 的所有健康实例,然后选择一个进行转发,从而实现客户端负载均衡。