关于HAProxy 1.7.9压缩与分块编码Bug的技术问询
针对你遇到的CentOS构建版HAProxy 1.7.9的压缩+分块传输挂起问题,我来逐一解答你的疑问:
问题背景回顾
你发现当HAProxy配置了compression关键字,且传输因文件大小触发chunked编码时,无论请求头是否携带Accept-Encoding: gzip(或其他编码),HAProxy都会永久挂起请求。移除所有compression配置后,后端服务器自行处理压缩,传输恢复正常。
1. 是否有修复该Bug的版本?
是的,这个问题在HAProxy 1.7分支的后续维护版本(比如1.7.10及以上)以及所有1.8+的稳定版本中已经被修复。HAProxy的维护团队会定期处理这类传输逻辑缺陷,建议你升级到1.7分支的最新稳定版(如1.7.14),或者直接迁移到1.8+的长期支持版本(LTS),以彻底解决该问题。
2. 为何使用compression algo identity时仍会出现此问题?
compression algo identity的设计是透传内容不做压缩,但HAProxy 1.7.9的压缩模块存在逻辑缺陷:只要配置了compression关键字,模块就会介入响应的传输流程,即使选择identity算法,也会错误地修改chunked编码的处理逻辑,导致传输挂起,而不是完全跳过压缩处理环节。
3. 为何本应对分块传输关闭压缩却仍出现该问题?
HAProxy 1.7.9的压缩模块没有正确识别后端返回的Transfer-Encoding: chunked响应头,导致模块没有触发“对分块传输关闭压缩”的逻辑,反而尝试对chunked数据进行处理,破坏了传输的完整性,最终引发挂起。这是模块在传输状态判断上的代码缺陷。
4. 为何当MIME类型不在压缩类型集合中时仍出现该问题?
同样是压缩模块的逻辑漏洞:只要配置了compression关键字,无论响应的MIME类型是否在配置的压缩列表中,模块都会介入传输流程,对chunked编码的响应进行不必要的干预,从而导致挂起。也就是说,模块的初始化逻辑没有正确判断“是否需要压缩”,就直接修改了传输处理链。
附加问题:专业技术人员该如何应对这类棘手情况?
遇到这类难以定位的中间件问题,我通常会按以下步骤处理:
- 二分法快速定位:先隔离变量(比如移除
compression配置),确认问题是否由特定模块引发; - 抓包分析传输细节:用
tcpdump或Wireshark抓取客户端-HAProxy-后端之间的数据包,观察挂起时的TCP状态(比如是否存在半连接、未发送的FIN/RST包); - 查阅官方文档与Bug记录:查看HAProxy的官方Changelog和Bug tracker,确认是否是已知问题以及对应的修复版本;
- 临时规避方案:在升级前,采用你已经验证的方案——让后端自行处理压缩,关闭HAProxy的
compression配置; - 升级验证:在测试环境部署更高版本的HAProxy,复现场景验证问题是否解决;
- 提交Bug报告:如果确认是未被记录的Bug,整理复现步骤、环境信息和抓包数据,提交给HAProxy社区帮助完善产品。
测试输出记录
问题复现(挂起场景)
admin@bastion1$ time curl -v -k -o/dev/null -H "Accept-Encoding: gzip" 'http://IP/URLto/deps.js' * About to connect() to XXX port 80 (#0) * Trying XXX... % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to XXX (XXX) port 80 (#0) > GET /URLto/deps.js HTTP/1.1 > User-Agent: curl/7.29.0 > Host: XXX > Accept: */* > Accept-Encoding: gzip > < HTTP/1.1 200 OK < Connection: close < Date: Wed, 09 Oct 2019 15:14:29 GMT < Last-Modified: Mon, 02 Sep 2019 19:28:26 GMT < ETag: "3bfdf549feec78af317650f9c35a7687" < Content-Type: application/javascript < Vary: Accept-Encoding < { [data not shown] 100 15136 0 15136 0 0 247 0 --:--:-- 0:01:01 --:--:-- 0^C
本次请求超时,无论是否携带
Accept-Encoding: gzip,无论压缩类型是否为application/javascript或其他类型,甚至使用compression offload时均会出现该问题。
移除compression配置后的正常场景
带gzip压缩请求
admin@bastion1$ time curl -v -k -o/dev/null -H "Accept-Encoding: gzip" 'http://.../deps.js' [...]> GET .../deps.js HTTP/1.1 > User-Agent: curl/7.29.0 > Accept: */* > Accept-Encoding: gzip > < HTTP/1.1 200 OK < Connection: close < Date: Wed, 09 Oct 2019 15:20:40 GMT < Last-Modified: Mon, 02 Sep 2019 19:28:26 GMT < ETag: "3bfdf549feec78af317650f9c35a7687--gzip" < Content-Type: application/javascript < Vary: Accept-Encoding < Content-Encoding: gzip < { [data not shown] 100 596k 0 596k 0 0 5523k 0 --:--:-- --:--:-- --:--:-- 5574k * Closing connection 0 real 0m0.112s user 0m0.004s sys 0m0.002s
无压缩请求
admin@bastion1$ time curl -v -k -o/dev/null 'http://.../deps.js' [...]> GET .../deps.js HTTP/1.1 > User-Agent: curl/7.29.0 > Accept: */* > < HTTP/1.1 200 OK < Connection: close < Date: Wed, 09 Oct 2019 15:26:05 GMT < Last-Modified: Mon, 02 Sep 2019 19:28:26 GMT < ETag: "3bfdf549feec78af317650f9c35a7687" < Content-Type: application/javascript < Vary: Accept-Encoding < { [data not shown] 100 1592k 0 1592k 0 0 52.2M 0 --:--:-- --:--:-- --:--:-- 53.6M * Closing connection 0 real 0m0.034s user 0m0.000s sys 0m0.006s
内容的提问来源于stack exchange,提问作者ikrabbe

