Docker环境Spring Boot应用undertow大量http请求超时
发布日期:2021-05-16 22:38:38 浏览次数:20 分类:精选文章

本文共 1801 字,大约阅读时间需要 6 分钟。

Docker环境下Spring Boot应用undertow大量http请求超时问题

背景

项目采用Spring Cloud微服务架构,每个微服务都是一个Spring Boot应用。

  • 项目使用嵌入式Web容器undertow进行http接口的相互通讯。
  • 服务部署在阿里云容器服务(AliCloud Container Service,ACS)上。
  • Spring Boot版本为1.5.9.RELEASE。
  • Undertow版本为1.4.21.Final。

问题

某个关键微服务接口出现大量超时请求,严重影响系统正常运营。

定位过程

发现一:性能日志异常

通过查看超时请求的运行日志,发现以下警告日志:

timerCache is above the warning threshold of 1000 with size 2312

  • 问题分析
    • 2312的位置数字逐渐增加,没有下降趋势。
    • 与之前日志对比,今天的警告日志数量明显增加。
  • 关联性分析
    • 该日志来自org.springframework.cloud.netflix.metrics.servo.ServoMonitorCache类的getTimer方法。
    • 该类与RestTemplate相关服务监控有关。
    • 结合当前微服务大量使用RestTemplate进行http请求,初步怀疑是RestTemplate导致的性能问题。

解决尝试一:禁用Servo监控

在微服务的yml文件中添加配置:

spring:  metrics:    servo:      enabled: false
  • 实施方法
    • 尝试通过/refresh接口动态刷新配置,但发现配置无法生效。
    • 问题根源在于ServoMetricsAutoConfiguration仅在启动时生效。
  • 最终结果
    • 重启微服务后,警告日志消失,表明配置生效。
    • 但未能解决http请求超时问题,仍需进一步排查。

发现二:JVM内存与GC问题

  • 问题分析
    • 观察微服务的容器内存使用情况,发现JVM内存使用正常。
    • 使用jstat -gcutil PID 1s监控GC情况,发现YGC(Young Generation Collection)每隔10秒执行一次,未见异常。
  • 异常现象
    • 调用方报告5秒超时,而此微服务记录显示请求进入后10多秒才输出日志。
    • 初步怀疑是请求进入队列排队,导致超时及日志延迟输出。

发现三:undertow线程配置不足

  • 线程池状态
    • 通过Spring Boot Admin查看线程堆栈,发现此微服务仅有16个XNIO-2-task工作线程。
    • 大部分线程处于waiting状态,少部分阻塞于业务逻辑处理。
  • 负载分析
    • 16个工作线程远远不足以处理当前的请求量。
    • 不时的线程阻塞导致服务响应变慢,甚至达到超时。
  • 服务状态
    • Spring Boot Admin显示此微服务时而在线,时而离线(离线原因是/health接口超时)。

解决方法

配置线程池参数

在微服务的yml文件中增加以下配置:

server:  undertow:    io-threads: 16    worker-threads: 256
  • 实施效果
    • 重启微服务后,观察到http请求超时问题得到有效缓解。
    • 服务状态在Spring Boot Admin中保持稳定在线。

结论

原因分析

  • 问题根源
    • undertow的默认工作线程配置不足,无法处理大量的并发http请求。
    • 16个工作线程在高并发场景下显然无法满足需求,导致请求排队和超时。

扩展思考

常见问题与解决方案

  • Web应用大量http请求超时

    • 检查Web容器配置:确保工作线程数量和队列大小适当。
    • 监控Web容器状态:关注线程池的活跃状态、排队请求数等关键指标。
  • 容器级监控

    • 使用工具(如Prometheus + Grafana)对Web容器进行全面监控,包括CPU、内存、线程池状态等。
    • 若有需要,可开发自定义监控组件,实时追踪关键指标。
  • ###疑问解答

    • 默认配置

      • Undertow默认工作线程配置较为保守,以确保兼容性和稳定性。
      • 如果其他微服务未做线程池调整,可能是因为其业务需求较低或使用模式不同。
    • 线程配置为何选择256

      • 根据实际负载测试结果,确定最小需要256个工作线程以满足高并发需求。
      • 可通过负载测试模拟大量请求,动态调整线程池参数。
    上一篇:Docker环境undertow线程数不足问题探究
    下一篇:Java后端服务明显变慢诊断思路

    发表评论

    最新留言

    哈哈,博客排版真的漂亮呢~
    [***.90.31.176]2025年04月15日 20时50分35秒