微服务网关(Spring Cloud Gateway)实战攻略

一、网关核心定位与价值

网关是微服务架构的统一流量入口,核心解决以下问题:

核心能力 解决的痛点
统一路由转发 前端无需对接多个微服务地址,路由规则集中管理
全局鉴权 / 限流 / 熔断 避免每个微服务重复开发通用逻辑
服务发现与动态路由 对接注册中心(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 做外层(静态资源、公网入口、四层负载),网关做内层(微服务路由、业务逻辑、动态管控)。

相关推荐
TT_44193 小时前
缓存设计之探了又探
缓存·架构
技术破壁人3 小时前
《SkyWalking 分布式链路追踪实战》—— 快速定位微服务性能瓶颈!
分布式·微服务·skywalking
神算大模型APi--天枢6463 小时前
国产硬件架构大模型算力服务平台:本地化部署与标准端口开发的创新实践
大数据·人工智能·科技·深度学习·架构·硬件架构
凌云若寒3 小时前
半导体标签打印的核心痛点分析
java
灰乌鸦乌卡3 小时前
泛微OA集成档案信息包生成
java
2301_803554523 小时前
利用信号完成这个联动需求
java·开发语言
500843 小时前
鸿蒙 Flutter 超级终端适配:多设备流转与状态无缝迁移
java·人工智能·flutter·华为·性能优化·wpf
codealy3 小时前
Spring 事务失效的八大场景深度解析
java·spring boot·后端·spring
九河云3 小时前
华为云 GaussDB 分布式架构解析:企业级数据库高可用与性能调优方案
分布式·架构·华为云·云计算·gaussdb