You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

高并发下Finagle服务报ChannelClosedException上游地址不可用问题咨询

问题复现说明

我们的Scala/Thrift服务运行在Java8环境,依赖的Twitter Finagle版本为2.12-18.10.0。服务在单请求或低并发场景下运行正常,高并发场景下偶现如下异常:

com.twitter.finagle.ChannelClosedException: ChannelException at remote address: hostname:9091 from service: calcservice-thrift. Remote Info: Upstream Address: Not Available, Upstream id: Not Available, 
    at org.apache.thrift.TApplicationException.readFrom(TApplicationException.java:131)

客户端测试代码如下:

log.info("started");
IntStream.range(0,500)
        .parallel()
        .forEach(i->{
            try {
                //remote call to finagle service
            }
            catch(Exception e){
                log.error("error " ,e);
            }
        });
log.info("end");
服务端随机关闭通道的核心原因
  • Finagle默认连接池阈值触发:高并发下连接数触及服务端默认的连接上限、请求并发上限,服务端为避免资源耗尽,主动回收闲置或超额连接,若此时客户端正好使用被回收的连接发起请求,就会抛出通道关闭异常
  • 服务端过载熔断触发:短时间内并发请求量超出服务端处理能力,请求队列积压触发Finagle默认的过载保护机制,主动关闭过载的连接释放资源
  • 版本已知缺陷:Finagle 2.12-18.10.0版本存在连接状态判断的偶发bug,高并发场景下会误将活跃连接判定为闲置连接进行回收
  • 传输限制触发:若业务存在大体积请求,超出Finagle默认的Thrift帧最大长度限制,服务端会主动关闭传输异常的连接,故障偶现是因为只有部分请求超过阈值
  • 操作系统层面限制:服务端所在机器的文件描述符上限、TCP连接回收参数配置不合理,高并发下连接被操作系统内核主动关闭
可行修复方案
  • 调整Finagle服务端配置:放宽连接池、并发请求限制,调大闲置连接超时时间,示例配置参考:
    // 服务端配置调整
    Thrift.server
      .withSessionPool.maxSize(1024) // 调大最大连接数
      .withSessionPool.maxIdleTime(5.minutes) // 调长闲置连接回收时间
      .withMaxConcurrentRequests(2048) // 调大最大并发请求数
      .withAdmissionControl.concurrencyLimit(maxWaiters = 1024) // 调大等待队列长度
    
  • 配置客户端重试策略:针对幂等请求,配置Finagle客户端对ChannelClosedException这类连接异常进行自动重试,示例配置参考:
    // 客户端配置调整
    Thrift.client
      .withRetryPolicy(
        RetryPolicy.tries(
          3, 
          RetryPolicy.TimeoutAndWriteExceptionsOnly
            .or(RetryPolicy.equalTo(classOf[ChannelClosedException]))
        )
      )
    
  • 升级Finagle版本:如果依赖升级不受限制,建议升级到2.12-22.7.0及以上的稳定版本,修复已知的连接回收逻辑缺陷
  • 调整操作系统网络配置:调大服务端机器的文件描述符上限(ulimit -n 65535),优化TCP keepalive、TIME_WAIT回收等参数,避免内核主动关闭正常业务连接
  • 调大Thrift帧限制:如果业务存在大请求场景,同步调整服务端和客户端的Thrift帧最大长度,示例配置:
    .withThriftFramedTransport.maxFrameSize(10 * 1024 * 1024) // 调整帧上限为10MB
    
  • 优化客户端并发逻辑:JDK并行流默认使用公共ForkJoin池,并发度不可控,容易突发打满服务端资源,建议替换为自定义线程池,控制请求并发速率,做削峰处理。

内容的提问来源于stack exchange,提问作者Ashish Garg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 15:54:04