是否遇到过这种情况:在实验室中对服务器进行基准测试后,将其部署到实际流量环境中,却发现实际性能远不及基准测试结果?CPU利用率很低,空闲资源也很充足,但客户端仍抱怨响应缓慢,而您却找不到提高服务器利用率的方法。
您观察到的现象,是我们所说的“HTTP繁重处理”带来的影响之一。在这篇博文中,我们将探讨HTTP的工作原理,以及常见HTTP服务器如何处理HTTP事务。我们还会分析可能出现的一些性能问题,并了解NGINX的事件驱动模型如何成为这些HTTP服务器高效的加速代理。借助NGINX,可以改善实际流量下的性能,使其恢复到本地基准测试的水平。
有关如何调优Linux和NGINX以提升应用速度和可扩展性的建议,请参阅我们博客中的《NGINX性能调优》。
HTTP 与 Keepalive 连接简介
HTTP持久连接是一项必不可少的性能功能,可降低延迟并加快网页加载速度。
HTTP是一种简单的文本协议。如果以前没有查看过,不妨看看HTTP调试工具(例如Web浏览器内置的调试工具)的输出,了解标准的请求和响应结构:

在最简单的实现中,HTTP客户端会与目标服务器建立新的TCP连接,发送请求并接收响应。随后,服务器会关闭该TCP连接以释放资源。

这种运行模式可能效率很低,尤其是在网页结构复杂、包含大量元素或网络链路速度较慢时。建立新的TCP连接需要进行“三次握手”,断开连接也需要执行双向关闭过程。为每条消息反复建立和关闭TCP连接,就像在电话交谈中,每当一方说完一句话就挂断并重新拨号。
HTTP使用一种称为“保持活动连接”的机制,在HTTP事务完成后继续保持客户端与服务器之间的TCP连接。如果客户端需要执行另一个HTTP事务,可以使用空闲的保持活动连接,而无需创建新的TCP连接。

客户端通常会同时与服务器建立多个TCP连接,并通过所有这些连接执行保活事务。这些连接会保持打开状态,直到客户端或服务器确定不再需要它们,通常是因为触发了空闲超时。
现代Web浏览器通常会打开6至8个保持活动连接,并保持这些连接数分钟,之后才会因超时而断开。可以将Web服务器配置为更早让这些连接超时并将其关闭。
保持连接对HTTP服务器有何影响?
如果大量客户端使用HTTP持久连接,而Web服务器存在并发限制或可扩展性问题,那么一旦达到该限制,性能就会急剧下降。
上述方法旨在尽可能提升单个客户端的性能。但遗憾的是,在类似“公地悲剧”的情形下,如果所有客户端都采用这种方式,许多常见Web服务器和Web应用的性能可能会受到不利影响。
这是因为许多服务器设有固定的并发数上限。例如,在常见配置中,Apache HTTP Server只能处理数量有限的并发TCP连接:使用worker多进程处理模块(MPM)时为150个,使用prefork MPM时为256个。每个空闲的HTTP持久连接都会占用一个并发槽位;所有槽位均被占用后,服务器将无法再接受任何HTTP连接。
通常的做法是关闭Web服务器上的持久连接,或将其生存期限制得非常短。这些连接很容易成为SlowHTTPTest和Slowloris拒绝服务攻击的途径(如需快速解决方案,请参阅serverfault.com上的《防范Keep‑Dead拒绝服务攻击》)。
此外,这些Web服务器和应用服务器通常会为每个连接分配一个操作系统线程或进程。TCP连接是一种非常轻量级的操作系统对象,而线程或进程则非常重量级。线程和进程需要占用内存,必须由操作系统主动管理,并且线程或进程之间的“上下文切换”会消耗CPU资源。为每个连接分配单独的线程或进程效率极低。

大量并发客户端连接,加上为每个连接分配一个线程或进程,会产生所谓的“HTTP繁重处理”现象,即处理轻量级HTTP事务需要投入不成比例的大量资源。
这在实践中意味着什么?
只需少量客户端,即可达到许多现代Web服务器和应用服务器的并发上限。
如果一个客户端打开8个TCP连接,并在每个连接最后一次使用后继续保持15秒,则该客户端会占用8个并发连接槽位,持续15秒。如果客户端以每秒1个的速率访问网站,空闲的持久连接将持续占用120个并发连接槽位。如果速率为每秒2个客户端,则会占用240个并发连接槽位。一旦槽位耗尽,新客户端将无法连接,直至现有连接超时。
这可能导致服务水平严重不均。成功建立保持活动连接的客户端可以随意浏览服务,而在并发槽位全部占用时尝试连接的客户端则无法接入,只能排队等待。
为什么在基准测试期间看不到这些影响?
这些问题只会在客户端数量较多的低速网络中出现。通过高速本地网络使用单个客户端进行基准测试时,不会出现这些问题。
在基准测试中可能观察不到这些影响,原因有以下几点。
- 如果在基准测试期间未启用持久连接,客户端会为每个事务创建新的TCP连接(并在事务完成后断开该连接)。由于基准测试很可能是在高速本地网络上运行,因此测试能够成功完成,而您不会发现未使用持久连接所导致的性能问题。
- 如果确实启用了持久连接,则很可能只需运行少于服务器上限的并发连接,基准测试客户端就会使每个连接达到饱和状态(即重复使用连接),从而将服务器推至最大容量。但这与实际环境中的连接特征并不相符。
请注意,大多数基准测试工具仅报告成功的事务。因资源耗尽而停滞的连接可能不会被报告,也可能看起来只占成功连接的极小一部分。这会掩盖实际流量中问题的真实情况。
这个问题有多常见?
任何基于线程或进程的Web服务器或应用服务器都容易受到并发限制的影响。
任何为每个连接分配一个线程或进程的Web或应用平台都存在这一固有问题。在经过优化的基准测试环境中,这一问题不易被发现,但在实际环境中会表现为性能不佳和CPU利用率过高。
可以采取以下几项措施来解决此问题:
- 增加线程或进程的数量:这只是一项非常短期的措施。线程和进程是重量级操作系统对象,随着创建数量不断增加,管理开销也会迅速上升。
- 禁用或限制使用HTTP持久连接,这可以推迟达到并发上限,但会导致每个客户端的性能大幅下降。
- 使用专门的keepalive处理机制:Apache HTTP Server(Web服务器)提供了一个相对较新的event MPM。当连接在“活动”和“空闲keepalive”状态之间切换时,该MPM会在工作线程与专用事件线程之间转移连接。如果使用的其他模块支持此MPM,可以考虑采用这种方式;请注意,SSL/TLS连接仍完全由专用线程处理。
- 采用更高效的处理模型:一种简单且有效的措施是在Web服务器或应用服务器前部署高效的HTTP代理。NGINX等事件驱动型代理不受上述并发限制,能够轻松应对慢速连接和空闲的持久连接。此外,它还能将客户端的慢速连接及其中多个空闲的持久连接,有效转换为快速、本地且高效的基准测试式连接,从而充分发挥Web服务器和应用服务器的性能。
使用NGINX作为HTTP加速代理
NGINX采用不同的架构,不会受到上述并发问题的影响。它将速度较慢的客户端连接转换为经过优化、类似基准测试的连接,从而充分发挥服务器的性能。
NGINX采用高效的事件驱动模型来管理连接。
每个NGINX进程都可以同时处理多个连接。接受新连接时,开销非常低(仅包括一个新的文件描述符和一个待轮询的新事件),这与上述每进程或每线程模型不同。NGINX采用了高效的事件循环:

这使每个NGINX进程都能轻松扩展,同时处理数十、数千乃至数十万个连接。
随后,NGINX使用本地长连接池将请求代理到上游服务器。这样无需承担建立和关闭TCP连接所产生的开销,TCP协议栈也能快速调整到合适的窗口大小和重试参数。通过经过优化的本地网络写入请求和读取响应,速度会快得多:

最终效果是,上游服务器通过高速网络仅与一个本地客户端(NGINX)通信。该客户端会充分利用HTTP持久连接,在减少连接建立开销的同时,避免不必要地保持连接打开。这使服务器恢复到接近基准测试的理想运行环境。
当NGINX充当HTTP代理时,您会看到:
- 更充分地利用现有资源。由于不再承担繁重的HTTP处理任务,Web服务器和应用服务器每秒可以处理更多事务。
- 降低错误率。由于NGINX充当所有客户端的中央调度器,HTTP超时的可能性大幅降低。
- 提升最终用户体验。服务器运行效率更高,处理连接的速度更快。
NGINX 加速服务的其他方式
减轻繁重的HTTP处理负担,只是NGINX可用于改善应用基础设施过载状况、提升性能的措施之一。
NGINX的HTTP缓存功能可以缓存上游服务器的响应,并遵循标准缓存语义来控制缓存的内容和时长。如果多个客户端请求同一资源,NGINX可以直接从缓存中响应,避免重复请求增加上游服务器的负担。
NGINX还可以从上游服务器卸载其他操作。可以卸载数据压缩操作以减少带宽使用,集中处理SSL/TLS加密和解密,执行初始客户端身份验证(例如,使用HTTP基本身份验证、向外部身份验证服务器发送子请求和JSON Web令牌),并在必要时应用各种规则来限制流量速率。
非同寻常的负载均衡器或ADC
最后,请不要忘记,与其他加速代理、负载均衡器或应用交付控制器(ADC)不同,NGINX还是一款功能完备的Web服务器。您可以使用NGINX提供静态内容,将流量转发到使用Java、PHP、Python、Ruby及其他语言的应用服务器,交付媒体内容(音频和视频),与身份验证和安全系统集成,甚至可以使用嵌入NGINX配置中的规则直接响应事务。
NGINX和NGINX Plus没有内置性能限制,无论现在还是未来,都能充分利用部署它们的硬件。
要试用NGINX Plus,立即开始30天免费试用,或联系我们,讨论您的使用场景。
关于作者

相关博客文章
NGINX Plus R26 正式发布
NGINX Plus R26通过缓存JSON Web密钥集加快JWT验证,并强化TLS握手,从而提升安全性。NGINX JavaScript的新功能包括增强对异步函数的支持,以及实现WebCrypto API。
使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击
gRPC具备开发人员设计和部署现代应用所需的速度与灵活性,但其开放性也使其极易受到第7层DoS攻击。NGINX App Protect DoS可保护gRPC应用免受此类破坏性攻击。
Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划
了解选择错误的Ingress控制器可能带来的风险,以及如何从关键方面着手,让您的选择更好地适应未来需求。
NGINX Plus R19 正式发布
NGINX Plus R19扩展了监控功能,不仅提供更多指标,还新增了指标分析方式;增加试运行模式,用于测试限速效果;增强键值存储,以支持IP地址范围;并使限速更加动态。
NGINX现已正式加入F5
NGINX现已正式成为F5的一部分。Gus Robertson现任F5 NGINX业务部门负责人。他阐述了两家公司在人才、文化和愿景方面融合的价值,以及双方将如何携手增强NGINX的开源产品和商业产品。
