接口间断性 504 分析 (一)

本贴最后更新于 2240 天前,其中的信息可能已经水流花落

刚进新公司就遇到一个很棘手的问题:线上一个接口每天 0.5% 左右的概率会出现 504,出现的时机也是随机的,每天大概有一到两个时间点会触发,非常诡异。

API 请求路径如下图所示,haproxy 做为网关,后端接两个 server,client 通过 haproxy 来访问 server 端的服务:
imagepng

首先开始去查 haproxy 的日志,如下图所示,注意到第 1 行中的 504,以及前面的 12000ms,说明 server 端返回超时了,haproxy 超时时间为 2 分钟:
imagepng

再看 server 端的日志,没有发现 504 对应的请求,最长的响应时间也不超过 15 秒,为什么 haproxy 会超时 120 秒呢?再去查 haproxy 的日志发现存在 504 的接口不止一个。
imagepng

于是怀疑是不是 haproxy 主动断掉,再仔细检查日志,发现存在 sH 的标识,以下是对应的解释:

sH #服务器可以返回其响应头之前的“超时服务器”冲突。 #这是最常见的异常,表示太长的事务,可能是由服务器或数据库饱和引起的。 #立即的解决方法是增加“超时服务器”设置,但请务必记住,用户体验将遭受这些长时间的响应。 #唯一的长期解决方案是修复应用程序。 #参考:https://blog.csdn.net/chengfei112233/article/details/78983041

这就否定了 haproxy 本身的问题,haproxy 确实是等了 120 秒,server 没有响应。

那是不是 server 端出现了什么问题,导致不能返回给 haproxy 正确的响应呢?server 的应用日志里没有现象,接下来就可以充分怀疑 tcp 本身的机制导致的响应丢弃,网上搜索了下,发现这个参数 tcp_tw_recycle 与 tcp_timestamps 这两个参数同时开启时,在 NAT 环境会出现连接失败的情况。
(60 秒内,连接两个相同的请求(四元组一致:源 IP/端口 + 目标 IP/端口),后一个时间戳的请求,会被忽略。缓存每个连接最新的时间戳,后续请求中如果时间戳小于缓存的时间戳,即视为无效,相应的数据包会被丢弃。)

那我们是不是也是这样的原因呢?查了下参数确实都配置了,并且也 netstat 存在 reject 的日志,确实跟这个问题很像。与领导沟通了下,觉得这个问题最好还是抓包确认下,不能盲目参照别人经验。于是接下来开始了抓包之旅。
imagepng

抓包下来,分析却发现 TCP 连接是没问题的,TCP 包序列并没有发现参数导致的大量异常序列(TCP Retransmission),但是应用就是没有返回,真的是非常诡异。
imagepng

再去分析应用截取日志,通过 IP 与端口对应到请求:
imagepng

从上面两张图可以清楚的看到:haproxy 断开连接后,应用才收到请求,非常诡异。

从以上对网络层面的分析,能推断出 centos 在 TCP 握手后,没有将后续的请求推送到应用。但是接下来怎么排查,真的是一点思路都没有。但是问题仍然存在,分析不能停止,于是向运维申请了一些服务器监控的权限,试图从 zabbix 上再找到些蛛丝马迹。结果仍然没有收获。

这时候怀疑是不是服务器性能比较差,压力抗不住,因为只有其中一台配置比较差的 504 的情况很多,而且每天可能就一到两个时间点会爆发。于是将 haproxy 的负载又做了调整,调整成了 8:2,将 504 的那台服务器的比例调整低了。

观察了一周时间,并没有发现 504 有任何明显的降低,这充分说明并非负载导致的 504。而且发现一个现象,当问题出现后,明显发现 linux 的剩余内存少了非常多,只有大概几十 M。

初步怀疑存在内存泄露,但是 JVM 并没有错误迹象,并且检查 gc 日志都是正常的,非常奇怪。最终,向运维申请加了一台服务器,三台服务器的比例调整成 6:2:2,观察了一周,发现 504 仍然存在,但是只会出现在那台一直报 504 的机器上。再观察一段时间,会把 504 多的那台设备下掉。

下面是三台机器的内存情况:

imagepng
imagepng
imagepng

明显发现最上面一台可用内存很少,504 到此为止算是解决了。

总结一下,针对间断性 504 的异常问题,分别从网络、日志、监控、参数、命令等多个途径寻找异常点,来确定问题产生原因。最终结论是系统剩余内存太小,导致网络请求一直停留在系统层面,没有到达应用,超过了 haproxy 的超时限制。

其实还是走了一些弯路的,一开始就怀疑过内存,但是这个结论难以令人信服,所以先排除应用本身的问题后,才推动资源去通过替换服务器的方式解决该问题。

2018-12-25 续:
真的解决了么?其实并没有,真正的原因在下一篇总结。

  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1063 引用 • 3455 回帖 • 167 关注
  • HAProxy
    5 引用 • 9 回帖
  • Netty

    Netty 是一个基于 NIO 的客户端-服务器编程框架,使用 Netty 可以让你快速、简单地开发出一个可维护、高性能的网络应用,例如实现了某种协议的客户、服务端应用。

    49 引用 • 33 回帖 • 30 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Visio
    1 引用 • 2 回帖
  • 大疆创新

    深圳市大疆创新科技有限公司(DJI-Innovations,简称 DJI),成立于 2006 年,是全球领先的无人飞行器控制系统及无人机解决方案的研发和生产商,客户遍布全球 100 多个国家。通过持续的创新,大疆致力于为无人机工业、行业用户以及专业航拍应用提供性能最强、体验最佳的革命性智能飞控产品和解决方案。

    2 引用 • 14 回帖 • 1 关注
  • Jenkins

    Jenkins 是一套开源的持续集成工具。它提供了非常丰富的插件,让构建、部署、自动化集成项目变得简单易用。

    54 引用 • 37 回帖
  • 开源

    Open Source, Open Mind, Open Sight, Open Future!

    409 引用 • 3585 回帖
  • 正则表达式

    正则表达式(Regular Expression)使用单个字符串来描述、匹配一系列遵循某个句法规则的字符串。

    31 引用 • 94 回帖
  • Ubuntu

    Ubuntu(友帮拓、优般图、乌班图)是一个以桌面应用为主的 Linux 操作系统,其名称来自非洲南部祖鲁语或豪萨语的“ubuntu”一词,意思是“人性”、“我的存在是因为大家的存在”,是非洲传统的一种价值观,类似华人社会的“仁爱”思想。Ubuntu 的目标在于为一般用户提供一个最新的、同时又相当稳定的主要由自由软件构建而成的操作系统。

    127 引用 • 169 回帖
  • SpaceVim

    SpaceVim 是一个社区驱动的模块化 vim/neovim 配置集合,以模块的方式组织管理插件以
    及相关配置,为不同的语言开发量身定制了相关的开发模块,该模块提供代码自动补全,
    语法检查、格式化、调试、REPL 等特性。用户仅需载入相关语言的模块即可得到一个开箱
    即用的 Vim-IDE。

    3 引用 • 31 回帖 • 116 关注
  • RemNote
    2 引用 • 16 回帖 • 12 关注
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    116 引用 • 54 回帖 • 1 关注
  • Vim

    Vim 是类 UNIX 系统文本编辑器 Vi 的加强版本,加入了更多特性来帮助编辑源代码。Vim 的部分增强功能包括文件比较(vimdiff)、语法高亮、全面的帮助系统、本地脚本(Vimscript)和便于选择的可视化模式。

    29 引用 • 66 回帖
  • GAE

    Google App Engine(GAE)是 Google 管理的数据中心中用于 WEB 应用程序的开发和托管的平台。2008 年 4 月 发布第一个测试版本。目前支持 Python、Java 和 Go 开发部署。全球已有数十万的开发者在其上开发了众多的应用。

    14 引用 • 42 回帖 • 802 关注
  • Openfire

    Openfire 是开源的、基于可拓展通讯和表示协议 (XMPP)、采用 Java 编程语言开发的实时协作服务器。Openfire 的效率很高,单台服务器可支持上万并发用户。

    6 引用 • 7 回帖 • 98 关注
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    128 引用 • 858 回帖 • 1 关注
  • WebClipper

    Web Clipper 是一款浏览器剪藏扩展,它可以帮助你把网页内容剪藏到本地。

    3 引用 • 9 回帖 • 4 关注
  • OpenResty

    OpenResty 是一个基于 NGINX 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

    17 引用 • 49 关注
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    27 引用 • 196 回帖 • 26 关注
  • 电影

    这是一个不能说的秘密。

    122 引用 • 608 回帖
  • flomo

    flomo 是新一代 「卡片笔记」 ,专注在碎片化时代,促进你的记录,帮你积累更多知识资产。

    6 引用 • 140 回帖
  • Notion

    Notion - The all-in-one workspace for your notes, tasks, wikis, and databases.

    10 引用 • 76 回帖 • 1 关注
  • 酷鸟浏览器

    安全 · 稳定 · 快速
    为跨境从业人员提供专业的跨境浏览器

    3 引用 • 59 回帖 • 46 关注
  • 导航

    各种网址链接、内容导航。

    43 引用 • 177 回帖 • 3 关注
  • Angular

    AngularAngularJS 的新版本。

    26 引用 • 66 回帖 • 546 关注
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    549 引用 • 674 回帖
  • PostgreSQL

    PostgreSQL 是一款功能强大的企业级数据库系统,在 BSD 开源许可证下发布。

    22 引用 • 22 回帖 • 1 关注
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    945 引用 • 1460 回帖 • 1 关注
  • React

    React 是 Facebook 开源的一个用于构建 UI 的 JavaScript 库。

    192 引用 • 291 回帖 • 377 关注
  • OpenCV
    15 引用 • 36 回帖