zuul 网关超时优化

1. 概述

前段时间,线上的服务不知道为啥,突然全部的服务都超时,所有的请求经过网关都超时,后来进行链路追踪排查,发现有一个服务链接 RDS 数据库,一个查询花费了 20S 的查询时间,导致后续调用该服务的应用都超时。然后超时的连接占满了 zuul 的转发池,最终导致了所有经过 gateway 的服务都在等待,导致全体服务全部超时。

原因找出来之后,我就在纳闷,为何一个服务超时会导致所有服务都延时,作为一个高可用的网关, zuul 的设计应该不会这么差吧,并且,当时系统的 QPS 也不是很高,所以,必须找出这次超时的问题所在,于是,我就开始了此次网关超时的排查和优化!

下图是出现问题是的相关监控

1715158142695.png

因为公司的服务是 java 和 node 应用都存在,所以使用的 zuul 是简单路由转发,未使用 服务注册中心之类的,所以,熔断器和

2. 问题分析

首先,因为网关的相关配置都是之前填的,有些参数不是特别的清楚,下面的配置文件是我当时系统的相关配置。

zuul:
  host:
    connect-timeout-millis: 30000
    socket-timeout-millis: 60000

ribbon:
  ConnectTimeout: 300000
  ReadTimeout: 60000
  eureka:
    enabled: false

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 70000

2.1 zuul 参数解释

connect-timeout-millis

此参数为 zuul 网关连接服务的时间,单位为毫秒,我这里配置的是 30S,如果 30S 之内未连接到待转发的下一服务,则转发将报错,此请求也就将结束。这段时间为下图的第 1 步的时间

如下图所示:

1715158174139.png

socket-timeout-millis

zuul 网关连接到服务并且服务返回结果这一部分时间,单位为毫秒,我这里配置的是 60S,如果 60S 之内下一服务还没有返回, gateway 将报转发超时。

此时间为上图的 1+2+3 三部分时间

ribbon.ConnectTimeout

此为 ribbon 转发的连接时间,如果 zuul 使用的服务调用,则将采用此时间

ribbon.ReadTimeout

此为 ribbon 转发到返回的时间,如果 zuul 使用的是服务调用,则将采用此时间

超时时间采用哪个?

以上四个都是 zuul 的超时时间,但是问题来了,四个时间,到底采用哪两个呢?

我通过阅读 zuul 的相关文档,了解到,如果 zuul 使用的服务发现,则将会使用 rebbon进行负载均衡,即 ribbon.ConnectTimeoutribbon.ReadTimeout。 如果 zuul 使用的是简单路由(通过配置 url 进行路由转发),则将采用 socket-timeout-millisconnect-timeout-millis

If you want to configure the socket timeouts and read timeouts for requests proxied through Zuul, you have two options, based on your configuration:

  • If Zuul uses service discovery, you need to configure these timeouts with the ribbon.ReadTimeout and ribbon.SocketTimeout Ribbon properties.
  • If you have configured Zuul routes by specifying URLs, you need to use zuul.host.connect-timeout-millis and zuul.host.socket-timeout-millis.

2.2 问题分析

因为我的服务未使用服务注册中心,所以,很明显, 配置的 ribbon 并未生效,zuul 超时时间使用的 socket-timeout-millisconnect-timeout-millis

但是问题又来了,我 zuul 的超时时间为 60S,为何我的服务相应时间平均达到了 3 分钟,远远超过了我设置的 60S,所以肯定是 zuul 还出现了相应的问题。

后续通过了解到 zuul 源码和架构,明白 zuul 是 NIO 架构,即一个请求进来,经过 zuul 拦截器 Filter,最终交给 HttpClient 进行请求,zuul 为了高性能,使用 HttpClient 连接池。

获取连接源码

下面是 zuul 获取 HttpClient 连接池的代码

AbstractConnPool.getPoolEntryBlocking,看这个名字就知道。这是一个阻塞获取池资源的方法

    private E getPoolEntryBlocking(
            final T route, final Object state,
            final long timeout, final TimeUnit timeUnit,
            final Future<E> future) throws IOException, InterruptedException, ExecutionException, TimeoutException {
   
   

        Date deadline = null;
        if (timeout > 0) {
   
   
            deadline = new Date (System.currentTimeMillis() + timeUnit.toMillis(timeout));
        }
        this.lock.lock();
        try {
   
   
            final RouteSpecificPool<T, C, E> pool = getPool(route);
            E entry;
            for (;;) {
   
   
                Asserts.check(!this.isShutDown, "Connection pool shut down");
                if (future.isCancelled()) {
   
   
                    throw new ExecutionException(operationAborted());
                }
                for (;;) {
   
   
                    entry = pool.getFree(state);
                    if (entry == null) {
   
   
                        break;
                    }
                    if (entry.isExpired(System.currentTimeMillis())) {
   
   
                        entry.close();
                    }
                    if (entry.isClosed()) {
   
   
                        this.available.remove(entry);
                        pool.free
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值