一、Jetty作为Spring Cloud Gateway底层服务器的适用场景

1.1 典型应用场景

微服务架构里,API网关是流量的核心入口,比如电商大促的秒杀活动、订单查询这类场景,短时间内会有海量请求涌入。若网关扛不住流量,就会导致用户请求失败,直接影响业务。Jetty作为轻量级底层服务器,比默认的Netty更灵活,参数调整更精准,刚好适配网关需要高弹性、高并发的特性。比如618大促时,网关要同时处理百万级请求,还要防止下游订单、商品服务被冲垮,用Jetty+Gateway的组合就能更好控制流量和资源。

1.2 技术优缺点

优点:Jetty内存占用比传统Tomcat低,启动速度快,适合快速部署;采用NIO线程模型,一个线程能处理多个连接,比传统IO阻塞模型效率高;参数调整灵活,可精准控制连接和线程数量,适配网关这类需要精细调优的场景。缺点:对新手来说,Jetty参数比Netty复杂,需理解线程模型原理;参数调错反而会降低性能;需要替换默认依赖,有一定配置成本。

二、Jetty底层服务的弹性参数调整

2.1 依赖替换(必须先做的准备)

Spring Cloud Gateway默认用Netty作为底层服务器,要换成Jetty,必须先排除Netty依赖,加入Jetty相关包,这是新手最容易踩的坑。如果没做这一步,Jetty配置不会生效,启动后还是用Netty。

<!-- 替换Spring Cloud Gateway底层服务器为Jetty,技术栈:Spring Boot 2.7.12 + Spring Cloud Gateway 2021.0.5 + Jetty 11 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
    <!-- 排除默认Netty服务器依赖,这一步不可或缺 -->
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-reactor-netty</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- 引入Spring Boot的Jetty启动器,替换底层服务器 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<!-- Jetty响应式HTTP客户端,配合Gateway处理路由请求 -->
<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-reactive-httpclient</artifactId>
    <version>1.1.10</version>
</dependency>

2.2 Jetty核心弹性参数配置

Jetty弹性参数主要包括线程池、acceptor和selector线程,这些参数决定了底层服务的流量承载能力,配置在application.yml中,用生活化语言说明:

server:
  jetty:
    threads:
      minThreads: 15 # 最小存活线程数,类似公司最少留15人值班,不能全空
      maxThreads: 300 # 最大线程数,最多允许300人同时干活,太多会挤,太少不够用,按CPU核心数×2调整
      idleTimeout: 60000 # 线程空闲60秒就销毁,节省资源,类似临时员工没活就下班
    acceptors: 2 # acceptor线程数,负责接收新连接请求,按CPU核心数1/2设置,比如4核就设2,太多会抢资源
    selectors: 4 # selector线程数,负责处理连接读写,一般等于CPU核心数,专门处理请求传输

这里要注意,maxThreads不能盲目设大,若4核服务器设300,压测时CPU使用率超过80%,反而会因为线程上下文切换频繁降低性能,需结合实际负载调整。

三、Gateway层结合Jetty的限流策略配置

仅调整底层Jetty参数不够,还要在Gateway层配置限流,防止请求过多冲垮下游服务。这里用Redis结合Gateway的RequestRateLimiter,是常用的可靠限流方案,示例如下:

3.1 限流KeyResolver配置

需定义限流的唯一标识,比如客户端IP,避免单个IP请求影响其他用户:

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
// 技术栈:Spring Boot 2.7.12 + Spring Cloud Gateway + Redis 6.2.7
@Component
public class IpKeyResolver implements KeyResolver {
    // 用客户端公网IP作为限流唯一标识,简单有效,适合网关层限流
    @Override
    public Mono<String> resolve(ServerWebExchange exchange) {
        // 获取请求远程地址,提取IP地址
        return Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
    }
}

3.2 Gateway路由限流配置

在application.yml中配置Gateway限流规则,配合Jetty参数设置合理阈值,保证流量可控:

spring:
  cloud:
    gateway:
      routes:
        - id: order-service-route # 路由唯一标识
          uri: lb://order-service # 负载均衡到order-service微服务
          predicates:
            - Path=/order/** # 匹配所有/order开头的请求路径
          filters:
            - name: RequestRateLimiter # 启用请求限流过滤器
              args:
                key-resolver: "#{@ipKeyResolver}" # 使用刚才定义的IP作为限流Key
                redis-rate-limiter.replenishRate: 500 # 每秒允许处理500个请求,和Jetty maxThreads匹配留余量
                redis-rate-limiter.burstCapacity: 600 # 令牌桶最大容量,允许瞬时突发600个请求,应对流量高峰
                redis-rate-limiter.requestedTokens: 1 # 每个请求消耗1个令牌,规则简单清晰

这里的replenishRate和burstCapacity需和Jetty的maxThreads配合,比如Jetty最大线程300,设限流500看起来超过,但令牌桶允许突发,只要Jetty连接数没超配置值,请求会正常处理,既保证流量又不冲垮下游。

四、调优过程中的注意事项

4.1 依赖替换的正确性

一定要排除Spring Boot默认的reactor-netty依赖,否则启动后还是用Netty,Jetty配置无效。若启动时报Jetty相关错误,优先检查依赖是否排除Netty。

4.2 参数的匹配性

Jetty的maxThreads和Gateway限流阈值要匹配,比如Jetty最大线程300,限流QPS设为400不合理,因为最多只能处理300个请求,剩下100会排队超时,限流阈值不能超过Jetty最大承载请求数。另外,Jetty的connectionTimeout要和Gateway路由超时一致,比如都设为5秒,避免超时不一致导致请求异常。

4.3 熔断降级的配合

限流触发后不能直接返回500错误,要结合Resilience4j或Sentinel,返回友好提示,比如“当前访问人数过多,请稍后再试”,同时对下游服务降级,比如无订单数据时返回默认值,提升用户体验。

4.4 压测验证

所有参数调整后必须做压测,用JMeter或Locust模拟大流量,监控Jetty的CPU、内存使用率,Gateway的响应时间,确认限流生效、无请求堆积。比如压测时,请求超限流阈值后,Gateway返回429错误,Jetty连接数不超配置最大值,才是正确的。

五、总结和落地建议

总的来说,用Spring Cloud Gateway搭配Jetty时,弹性与限流调整分三步:第一步正确替换依赖,把底层换成Jetty;第二步调整Jetty的线程和连接参数,让底层承载足够流量;第三步配置Gateway限流策略,防止冲垮下游;最后配合熔断降级和压测,确保系统稳定。落地时先从最小参数调整,逐步增加,压测验证,直到达到预期效果,就能打造出高可用、高弹性的微网关,应对各类高并发场景。