[关闭]
@lsmn 2016-04-13T10:02:38.000000Z 字数 2070 阅读 3059

NGINX应用性能优化指南(第六部分):连接优化

迷你书


【编者的话】本文是“NGINX应用性能优化指南”系列文章的第六篇,主要介绍了如何从连接优化方面实现NGINX应用性能优化。

注:本文最初发布于MaxCDN博客,InfoQ中文站在获得作者授权的基础上对文章进行了翻译。

正文

RFC 7413定义了TCP Fast Open(TFO)——一种对TCP协议的扩展,允许在TCP握手期间的TCP-SYN 和TCP-SYN/ACK数据包中夹带数据,这样就减少了一个RTT。

此处输入图片的描述

在原有TCP连接的基础上,客户端生成一个TFO cookie,并将其放进TCP-SYN数据包作为一个TCP选项。稍后,当客户端再次连接时,它会在TCP-SYN数据包中再次发送同样的cookie,同数据一起——可能是一个HTTP请求或者一个TLS ClientHello。如果服务器识别出这个cookie,那么它立即就会转换为已连接状态,并接收在TCP-SYN数据包中找到的数据。

虽然服务器可以使用TCP-SYN/ACK数据包中的数据回复,但更可能(从时间角度),TCP栈会在应用程序数据跟随到来之前发出TCP-SYN/ACK数据包。不管哪一种情况,数据较少的TCP握手往返现在可以用于发送和接收数据了,节省了一次往返。

这有益于加速HTTP请求,改善流媒体的首字节时间(TTFB)。实现TFO的核心以及NGINX所需要的所有东西就是listen指令的fastopen参数。

自3.7版本开始,在IPv4上支持TFO已经合并进Linux内核主干上(可以使用uname -r查看内核版本)。如果你运行着3.13或更好版本的内核,TFO很可能已经默认启用。可以使用下面的命令(Linux)检查TFO是否启用:

$ cat /proc/sys/net/ipv4/tcp_fastopen

0值表明它被禁用了;位0对应客户端操作,而位1对应服务器操作。把tcp_fastopen设为3可将两者同时启用。

大多数可下载NGINX程序包都不包含TFO支持,因为TCP_FASTOPEN并不一定在tcp.h中定义——即使内核提供了支持。你可以通过源代码构建NGINX,并将编译时将限定-DTCP_FASTOPEN=23添加到NGINX的配置脚本中(--with-cc-opt)。

相关教程:在CentOS 7上启用TFO for NGINX

证书验证

在TLS协商期间,客户端必须验证服务器的证书,以确信那个服务器就是它实际上请求的服务器。

验证通常包括生成一个OCSP请求,并发送给证书认证中心(CA),这意味着生成一个DNS查询和一个新的TCP连接。所有这些步骤都延长了同服务器进行TLS协商的时间。

OCSP Stapling概念将OCSP查询的负担从客户端移到了服务器。结果是,服务器将CA的时限应答“钉合(stapling)”到服务器的证书上,这样一来就简化了客户端的证书验证步骤。

NGINX通过ssl_stapling及相关指令来支持OCSP Stapling。

TLS会话恢复

有两种机制可以用于让后续TLS连接(下面会讨论)少一次往返:

  1. TLS会话ID
  2. TLS会话票证

此处输入图片的描述

需要注意的是,TLS会话恢复在服务器端会泄露TLS会话信息,破坏“完全前向保密(perfect forward secrecy)”。因此,如果需要PFS,就不应该用它。另一方面,通过在一个TLS隧道中复用多个请求,HTTP/2提供了同TLS会话恢复一样的RTT优化,而且不用牺牲PFS。

TLS会话ID

在最初的TLS握手期间,服务器会生成一个TLS会话ID,并通过ServerHello消息发送给客户端——这在Wireshark跟踪文件中可以看到:

此处输入图片的描述

对于后续的TLS握手,客户端可能会在其ClientHello消息中发送会话ID。这就使得服务器可以恢复缓存的TLS上下文,在一次TLS握手中省掉两次往返。

NGINX通过ssl_session_cachessl_session_timeout指令支持TLS会话ID。

TLS会话票证

TLS会话票证TLS会话ID的概念类似,不过存储会话信息的负担由服务器端转移到了客户端。

在一次普通的TLS握手期间,服务器会加密其TLS会话信息,并将结果票证发送给客户端。虽然客户端无法解码票证,但它可以在下次想要建立TLS连接时将其发回服务器。

TLS会话ID一样,这会减少一次往返——但服务器不必维护SSL缓存。不过,服务器必须维护一个用于加密票证的密钥(ssl_session_ticket_key),并要确保它的安全。

找到属于自己的理想NGINX设置

按照设计,NGINX是完全开放的。它是一辆装有光面轮胎的赛车,而且驾驶它的是一个疯狂的司机。所以大家一起尽情地玩,尝试一些东西,让我们知道你能让它多快。此外,如果你认为有什么东西应该加入到这份指南中,请告诉我们。我们会在第二个版本中补充和修正。

查看英文原文:NGINX Application Performance Optimization:Connection Optimizations

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注