每日Java面试场景题知识点之-微服务中的网关架构

一、为什么微服务需要网关?

在微服务架构中,系统被拆分为多个独立服务,每个服务都有独立的网络地址和端口。如果客户端直接与各个微服务通信,会面临以下问题:

  • 客户端需要知道每个服务的地址,耦合度极高
  • 每个服务都需要独立处理跨域、鉴权、限流等公共逻辑,代码冗余严重
  • 内部服务地址直接暴露,存在安全隐患
  • 服务拆分或扩缩容时,客户端需要同步修改,运维成本极高

网关(API Gateway)作为微服务架构中的统一入口,完美解决了上述痛点。它是所有客户端请求的"前门",负责将请求路由到对应的微服务,同时承载了众多非业务性的横切关注点。

二、网关的核心功能

2.1 动态路由

路由是网关最基础的功能。它根据请求的URL、Header、参数等条件,将请求转发到对应的下游服务。

Spring Cloud Gateway中的路由配置示例:

spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/user/**
          filters:
            - StripPrefix=1
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/order/**
          filters:
            - StripPrefix=1

关键点解析:

  • id:路由唯一标识
  • uri:目标服务地址,lb://表示基于注册中心的负载均衡
  • predicates:路由断言,匹配条件
  • filters:路由过滤器,对请求/响应进行处理

结合Nacos等注册中心,路由可实现动态感知——服务实例上下线时,网关自动更新路由表,无需重启。

2.2 统一鉴权

网关是做统一鉴权的最佳位置,避免每个微服务都重复实现鉴权逻辑。

常见鉴权流程:

  1. 客户端携带Token请求网关
  2. 网关全局过滤器拦截请求,解析并验证Token
  3. 验证通过后,将用户信息放入请求Header传递给下游服务
  4. 验证失败,直接返回401 Unauthorized
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        if (StringUtils.isBlank(token) || !validateToken(token)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        // 解析用户信息,放入Header透传给下游服务
        String userId = parseUserId(token);
        ServerHttpRequest request = exchange.getRequest().mutate()
                .header("X-User-Id", userId)
                .build();
        return chain.filter(exchange.mutate().request(request).build());
    }

    @Override
    public int getOrder() {
        return -1; // 优先级最高
    }
}

2.3 限流熔断

限流 protects系统在高并发下不被冲垮,熔断 则防止下游服务故障引发级联崩溃。

限流实现(基于Redis + Lua脚本)

Spring Cloud Gateway内置了RequestRateLimiter过滤器,基于Redis实现令牌桶限流:

spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/user/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 100  # 每秒填充令牌数
                redis-rate-limiter.burstCapacity: 200   # 令牌桶容量
                key-resolver: "#{@userKeyResolver}"       # 限流维度
@Bean
public KeyResolver userKeyResolver() {
    // 按用户ID限流
    return exchange -> Mono.just(
        exchange.getRequest().getHeaders().getFirst("X-User-Id")
    );
}
熔断降级(结合Sentinel)

Alibaba Sentinel与Spring Cloud Gateway的集成是目前主流的熔断方案:

spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080
      scg:
        fallback:
          mode: response
          response-status: 200
          response-body: '{"code":503,"message":"服务降级"}'

Sentinel支持按路由ID或API分组配置流控规则,实现精细化熔断策略。

2.4 请求日志与监控

网关作为流量入口,是采集请求日志和监控指标的天然节点:

  • 访问日志:记录每个请求的路径、耗时、状态码
  • 链路追踪:生成TraceId,注入请求Header,实现分布式链路追踪
  • 指标采集:QPS、响应时间、错误率等,对接Prometheus + Grafana
@Component
public class LoggingGlobalFilter implements GlobalFilter, Ordered {

    private static final Logger log = LoggerFactory.getLogger(LoggingGlobalFilter.class);

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String traceId = UUID.randomUUID().toString();
        ServerHttpRequest request = exchange.getRequest().mutate()
                .header("X-Trace-Id", traceId)
                .build();
        long startTime = System.currentTimeMillis();
        return chain.filter(exchange.mutate().request(request).build())
                .doFinally(signalType -> {
                    long duration = System.currentTimeMillis() - startTime;
                    log.info("TraceId:{}, Path:{}, Status:{}, Duration:{}ms",
                            traceId,
                            request.getPath(),
                            exchange.getResponse().getStatusCode(),
                            duration);
                });
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}

三、主流网关方案对比

Spring Cloud Gateway

  • 技术栈:基于Spring WebFlux + Netty,非阻塞异步模型
  • 优势:与Spring Cloud生态深度融合,编程模型友好,社区活跃
  • 适用场景:Spring Cloud技术栈项目,中小到中大规模
  • 注意:基于WebFlux,不支持传统的Servlet API

Kong

  • 技术栈:基于OpenResty(Nginx + Lua),性能极致
  • 优势:高性能、插件生态丰富、支持多语言插件
  • 适用场景:超大规模流量、多语言微服务架构
  • 注意:学习曲线较陡,运维复杂度较高

APISIX

  • 技术栈:基于Nginx + etcd,Apache顶级项目
  • 优势:高性能、动态配置热更新、插件热加载、多协议支持
  • 适用场景:云原生环境、Kubernetes Ingress、需要极致动态能力
  • 注意:相对较新,企业级案例在积累中

四、网关架构设计要点(面试高频)

4.1 网关高可用设计

网关是整个系统的咽喉,必须保证高可用:

  • 多实例部署:网关无状态设计,水平扩展
  • 前置负载均衡:Nginx/SLB做网关的负载均衡
  • 健康检查:自动剔除异常实例
  • 同城双活/异地多活:跨机房容灾部署

4.2 网关性能优化

  • Reactor模型:Spring Cloud Gateway基于Netty的Reactor线程模型,天然支持高并发
  • 连接池优化:调整Netty的连接池参数,如最大连接数、连接超时
  • 缓存策略:对不常变化的接口响应做网关层缓存
  • 异步化:过滤器逻辑尽量异步非阻塞,避免阻塞Reactor线程

4.3 网关安全防护

  • HTTPS双向认证:保证传输层安全
  • 防重放攻击:请求加时间戳+签名,网关校验
  • IP黑白名单:基于远程地址过滤器
  • SQL/XSS注入检测:对请求参数做安全过滤
  • 接口签名验证:防止参数篡改

4.4 灰度发布

网关是实现灰度发布的利器,常见策略:

  • 基于权重:新版本分配10%流量,老版本90%
  • 基于Header/Cookie:特定标识的请求路由到新版本
  • 基于用户标签:白名单用户优先体验新功能
spring:
  cloud:
    gateway:
      routes:
        - id: user-service-v1
          uri: lb://user-service-v1
          predicates:
            - Path=/api/user/**
            - Weight=group1, 90
        - id: user-service-v2
          uri: lb://user-service-v2
          predicates:
            - Path=/api/user/**
            - Weight=group1, 10

五、面试高频问题

Q1:网关和服务注册中心的关系?

网关通过注册中心(如Nacos、Eureka)动态发现服务实例,实现路由的自动更新。网关本身也是微服务,也需要注册到注册中心。当服务实例上下线时,注册中心通知网关更新路由表,实现动态路由。

Q2:网关过滤器与微服务内部拦截器的区别?

  • 网关过滤器作用于所有经过网关的请求,是全局性的横切逻辑
  • 微服务拦截器作用于单个服务内部,处理服务特定的业务逻辑
  • 建议将鉴权、限流、日志等公共逻辑放在网关,业务相关的校验放在服务内部

Q3:Spring Cloud Gateway为什么选择WebFlux而不是传统的Spring MVC?

Spring MVC基于Servlet容器,采用线程池模型——每个请求占用一个线程,高并发时线程资源消耗大。WebFlux基于Reactor + Netty,采用事件驱动和非阻塞I/O模型,少量线程即可处理大量并发连接,更适合网关这种高并发、I/O密集型的场景。

Q4:网关如何处理跨域?

网关统一配置CORS,避免每个服务单独处理:

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowed-origins: "*"
            allowed-methods: "*"
            allowed-headers: "*"
            max-age: 3600

六、总结

微服务网关是架构设计中不可或缺的一环,其核心价值在于统一入口、解耦客户端与服务、收敛横切关注点。在实际选型时:

  • Spring Cloud体系 → 优先选Spring Cloud Gateway
  • 极致性能需求 → 考虑Kong或APISIX
  • 云原生/K8s环境 → APISIX是热门选择

掌握网关的路由、鉴权、限流、熔断四大核心功能,以及高可用和性能优化的设计要点,是Java面试中微服务模块的高频加分项。

感谢读者观看

更多推荐