一、网关核心定位与价值
网关是微服务架构的统一流量入口,核心解决以下问题:
| 核心能力 | 解决的痛点 |
|---|---|
| 统一路由转发 | 前端无需对接多个微服务地址,路由规则集中管理 |
| 全局鉴权 / 限流 / 熔断 | 避免每个微服务重复开发通用逻辑 |
| 服务发现与动态路由 | 对接注册中心(Nacos/Eureka),自动感知服务上下线 |
| 请求 / 响应转换 | 统一处理参数格式、跨域、数据脱敏等 |
| 链路监控与日志 | 全链路请求日志、耗时统计,便于问题排查 |
技术选型:优先选 Spring Cloud Gateway(基于 WebFlux 异步非阻塞,性能优于 Zuul 1.x),适配 Spring Cloud 生态。
二、环境准备与基础搭建
1. 核心依赖(Maven)
xml
<!-- Spring Cloud Gateway 核心 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- 注册中心对接(以Nacos为例) -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 配置中心(可选) -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 熔断器(Sentinel/Resilience4j) -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- JWT鉴权 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
2. 基础配置(application.yml)
yaml
server:
port: 8888 # 网关端口
spring:
application:
name: gateway-service # 网关服务名
cloud:
# Nacos 注册中心配置
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: dev # 环境隔离
# Gateway 核心配置
gateway:
# 开启服务发现(对接Nacos,支持动态路由)
discovery:
locator:
enabled: true
lower-case-service-id: true # 服务名小写
# 路由规则配置
routes:
# 示例1:用户服务路由
- id: user-service
uri: lb://user-service # lb:// 表示负载均衡,对接注册中心
predicates: # 路由匹配规则
- Path=/user/** # 路径匹配
- Method=GET,POST # 请求方法匹配
filters: # 路由过滤器
- StripPrefix=1 # 去掉路径前缀(/user/xxx → /xxx 转发到微服务)
- AddResponseHeader=X-Request-Id, ${random.uuid} # 添加响应头
# 示例2:订单服务路由
- id: order-service
uri: lb://order-service
predicates:
- Path=/order/**
filters:
- StripPrefix=1
# 跨域配置
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "*" # 生产环境需指定具体域名
allowedMethods: "*"
allowedHeaders: "*"
allowCredentials: true
三、核心功能实战
1. 路由转发(静态 + 动态)
(1)静态路由(固定地址)
适用于非微服务地址(如第三方接口):
yaml
routes:
- id: third-party-api
uri: https://api.xxx.com # 固定地址
predicates:
- Path=/third/**
filters:
- StripPrefix=1
(2)动态路由(对接注册中心)
依赖 nacos-discovery,网关自动从 Nacos 拉取服务列表,无需手动配置服务地址:
- 核心配置:
spring.cloud.gateway.discovery.locator.enabled=true - 访问规则:
网关地址/服务名/接口路径(如http://localhost:8888/user-service/user/1)
2. 全局鉴权(JWT 示例)
(1)JWT 工具类
java
运行
@Component
public class JwtUtil {
// 密钥(生产环境需配置在Nacos,避免硬编码)
private static final String SECRET_KEY = "your-secret-key-123456";
// 过期时间(2小时)
private static final long EXPIRE_TIME = 7200000;
// 生成Token
public String generateToken(String userId, String role) {
return Jwts.builder()
.setSubject(userId)
.claim("role", role)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRE_TIME))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY.getBytes(StandardCharsets.UTF_8))
.compact();
}
// 解析并校验Token
public Claims parseToken(String token) {
return Jwts.parserBuilder()
.setSigningKey(SECRET_KEY.getBytes(StandardCharsets.UTF_8))
.build()
.parseClaimsJws(token)
.getBody();
}
}
(2)自定义鉴权过滤器
java
运行
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {
// 白名单(无需鉴权的接口)
private static final List<String> WHITE_LIST = Arrays.asList("/auth/login", "/auth/register");
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String path = request.getPath().toString();
// 1. 白名单接口直接放行
if (WHITE_LIST.stream().anyMatch(path::startsWith)) {
return chain.filter(exchange);
}
// 2. 提取Token
String token = request.getHeaders().getFirst("Authorization");
if (token == null || !token.startsWith("Bearer ")) {
return buildUnauthorizedResponse(exchange);
}
token = token.replace("Bearer ", "");
// 3. 校验Token
try {
Claims claims = new JwtUtil().parseToken(token);
// 4. 解析用户信息,透传给微服务(写入请求头)
ServerHttpRequest newRequest = request.mutate()
.header("X-User-Id", claims.getSubject())
.header("X-User-Role", claims.get("role").toString())
.build();
return chain.filter(exchange.mutate().request(newRequest).build());
} catch (Exception e) {
// Token过期/无效
return buildUnauthorizedResponse(exchange);
}
}
// 构建401响应
private Mono<Void> buildUnauthorizedResponse(ServerWebExchange exchange) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
// 返回自定义错误信息
String errorMsg = JSONObject.toJSONString(Result.fail(401, "未授权或Token失效"));
DataBuffer buffer = response.bufferFactory().wrap(errorMsg.getBytes(StandardCharsets.UTF_8));
return response.writeWith(Mono.just(buffer));
}
// 过滤器执行顺序(数值越小越先执行)
@Override
public int getOrder() {
return -100;
}
}
3. 限流(基于 Sentinel)
(1)配置限流规则
yaml
spring:
cloud:
sentinel:
transport:
dashboard: 127.0.0.1:8080 # Sentinel控制台地址
gateway:
filters:
- name: SentinelGatewayFilter
args:
order: -1000 # 执行顺序
(2)自定义限流响应
java
运行
@Component
public class SentinelFallbackHandler implements BlockRequestHandler {
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {
Map<String, Object> result = new HashMap<>();
result.put("code", 429);
result.put("msg", "请求过于频繁,请稍后重试");
return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(result));
}
}
4. 熔断降级(Resilience4j)
yaml
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/user/**
filters:
- name: Resilience4JCircuitBreaker
args:
name: userServiceCircuitBreaker
fallbackUri: forward:/fallback/user # 降级回调地址
降级回调接口
java
运行
@RestController
@RequestMapping("/fallback")
public class FallbackController {
@GetMapping("/user")
public Result<?> userFallback() {
return Result.fail(503, "用户服务暂时不可用,请稍后重试");
}
}
5. 请求 / 响应日志
java
运行
@Component
public class LogGlobalFilter implements GlobalFilter, Ordered {
private static final Logger log = LoggerFactory.getLogger(LogGlobalFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 记录请求信息
ServerHttpRequest request = exchange.getRequest();
String path = request.getPath().toString();
String method = request.getMethod().name();
String ip = request.getRemoteAddress().getAddress().getHostAddress();
long startTime = System.currentTimeMillis();
// 记录响应信息
return chain.filter(exchange).doFinally(signalType -> {
long costTime = System.currentTimeMillis() - startTime;
ServerHttpResponse response = exchange.getResponse();
int statusCode = response.getStatusCode().value();
log.info("网关请求日志 - IP: {}, 方法: {}, 路径: {}, 响应码: {}, 耗时: {}ms",
ip, method, path, statusCode, costTime);
});
}
@Override
public int getOrder() {
return -99; // 鉴权之后执行
}
}
四、生产环境优化
1. 性能调优
-
异步非阻塞:Spring Cloud Gateway 基于 WebFlux,避免配置 Tomcat(默认用 Netty),无需额外线程池配置;
-
连接池 :配置 HttpClient 连接池,提升服务转发效率:
yaml
spring: cloud: gateway: httpclient: pool: max-connections: 200 # 最大连接数 acquire-timeout: 1000ms # 获取连接超时 -
禁用不必要的过滤器:减少非核心逻辑的性能损耗。
2. 高可用部署
-
多实例部署:网关部署至少 2 个实例,避免单点故障;
-
Nginx + 网关 :外层 Nginx 做负载均衡,转发到多个网关实例:
nginx
upstream gateway_cluster { server 127.0.0.1:8888; server 127.0.0.1:8889; } server { listen 80; location / { proxy_pass http://gateway_cluster; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
3. 配置中心管理
将网关的路由规则、密钥、限流阈值等配置放到 Nacos 配置中心,支持动态刷新,无需重启网关:
yaml
spring:
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
namespace: dev
group: GATEWAY_GROUP
file-extension: yml
4. 安全加固
-
避免暴露网关端口到公网,仅通过 Nginx 转发;
-
Token 密钥、服务密钥等敏感信息加密存储(如 Nacos 配置加密);
-
限制请求体大小,防止大请求攻击: yaml
spring: cloud: gateway: max-in-memory-size: 1048576 # 1MB
五、问题排查与监控
1. 日志排查
开启网关详细日志,定位路由 / 过滤器问题:
yaml
logging:
level:
org.springframework.cloud.gateway: DEBUG
org.springframework.web.reactive: DEBUG
reactor.netty: DEBUG
2. 监控指标
集成 Prometheus + Grafana,监控网关的 QPS、响应时间、异常率:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
yaml
management:
endpoints:
web:
exposure:
include: prometheus,gateway,routes
metrics:
tags:
application: ${spring.application.name}
3. 常见问题
| 问题现象 | 排查方向 |
|---|---|
| 404 找不到路由 | 检查路由规则、服务名是否正确,注册中心是否能拉取到服务 |
| 401 鉴权失败 | 检查 Token 是否正确、过滤器执行顺序、白名单配置 |
| 503 服务不可用 | 检查微服务是否在线,熔断规则是否触发 |
| 性能卡顿 | 检查过滤器是否有阻塞操作(需异步)、连接池配置、微服务响应时间 |
六、与 Nginx 的分工总结
| 功能 | Nginx | Spring Cloud Gateway |
|---|---|---|
| 静态资源代理 | ✅ 擅长(高性能) | ❌ 不推荐 |
| TCP/HTTP 层负载均衡 | ✅ 擅长 | ✅ 支持但推荐 Nginx 做外层 |
| 微服务动态路由 | ❌ 需手动配置 | ✅ 对接注册中心,动态感知 |
| 业务层鉴权 / 限流 | ❌ 能力弱 | ✅ 支持复杂业务逻辑 |
| 请求 / 响应修改 | ✅ 简单修改 | ✅ 复杂修改(如 JSON 处理) |
| 跨域处理 | ✅ 支持 | ✅ 更适配微服务 |
最佳实践:Nginx 做外层(静态资源、公网入口、四层负载),网关做内层(微服务路由、业务逻辑、动态管控)。