@lsmn
2016-04-13T10:02:38.000000Z
字数 2070
阅读 3099
迷你书
【编者的话】本文是“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
)。
证书验证
在TLS协商期间,客户端必须验证服务器的证书,以确信那个服务器就是它实际上请求的服务器。
验证通常包括生成一个OCSP请求,并发送给证书认证中心(CA),这意味着生成一个DNS查询和一个新的TCP连接。所有这些步骤都延长了同服务器进行TLS协商的时间。
OCSP Stapling概念将OCSP查询的负担从客户端移到了服务器。结果是,服务器将CA的时限应答“钉合(stapling)”到服务器的证书上,这样一来就简化了客户端的证书验证步骤。
NGINX通过ssl_stapling
及相关指令来支持OCSP Stapling。
TLS会话恢复
有两种机制可以用于让后续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_cache
和ssl_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