浏览 5.4k
原文作者:Mikhail Isachenkov of F5, Timo Stark of F5
原文链接:使用Kernel TLS 和 SSL_sendfile( ) 提高 NGINX 性能 - NGINX
转载来源:NGINX 官方网站
TLS(传输层安全协议)是一种极为受欢迎的加密协议。在内核 (kernel) 中实施 TLS (即 kTLS) 可显著降低在用户空间与内核之间复制操作的需求,从而提高 NGINX 的性能。
通过结合使用 kTLS 和 sendfile(),数据可以直接在内核空间加密,然后再传递到网络堆栈进行传输。这使得我们不再需要将数据复制到用户空间、利用 TLS 库进行加密、再返回内核空间进行传输的这一过程。kTLS 还可以将 TLS 的处理过程卸载到硬件,包括将 TLS 对称加密处理任务卸载到网络设备。
现代 Linux 和 FreeBSD 内核支持将 TLS 卸载到内核,而 NGINX 开源版现在也同样能做到!NGINX 1.21.4 在使用 SSL_sendfile() 传输静态文件时引入了 kTLS 支持,可以极大地改善性能。如下所述,内核和 OpenSSL 只有采用 kTLS 构建,才能让 NGINX 使用 SSL_sendfile()。
本文详细介绍了支持 kTLS 的操作系统以及 OpenSSL 版本,并展示了如何针对 kTLS 构建和配置内核与 NGINX。为了向您展示 kTLS 的性能改善效果,我们还将分享在 FreeBSD 和 Ubuntu 上进行测试的具体说明和结果数据。
注:kTLS 的实施这一新兴事物正在迅速发展中。本文描述了截至 2021 年 11 月 NGINX 对 kTLS 的支持情况,但本文提供的信息和说明可能会在之后进行更新,请随时关注 nginx.org 和 NGINX 博客上的公告。
截至 2021 年 11 月,在 NGINX 开源版支持的所有操作系统中,以下操作系统支持 kTLS 和指定的密码。有关密码支持的详细信息,请参阅 TLS 协议和密码支持。
| TLSv1.2 密码 | TLSv1.3 密码套件 | TLS_CHACHA20_POLY1305_SHA256 密码 | Linux 内核版本 | |
|---|---|---|---|---|
| Amazon Linux 2* | ✅ | ✅ | ❌ | 5.10 |
| CentOS 8** | ✅ | ❌ | ❌ | 4.18 |
| FreeBSD 13.0 | ✅ | ✅ | ❌ | 不适用 |
| RHEL 8 | ✅ | ❌ | ❌ | 4.18 |
| SLES 15 SP2 | ✅ | ✅ | ✅ | 5.3 |
| Ubuntu 20.04 LTS | ✅ | ❌ | ❌ | 5.4 |
| Ubuntu 21.04 | ✅ | ✅ | ✅ | 5.11 |
| Ubuntu 21.10 | ✅ | ✅ | ✅ | 5.13 |
* 内核版本必须是 5.10(不能是 4.14);请参阅不支持 kTLS 的操作系统和 Amazon Linux 2 常见问题解答
** 继承了上游源 RHEL 8 的 kTLS 支持特性
*** 请参阅 FreeBSD 操作日志
以下操作系统不支持 KTLS,原因如下:
如上所述,支持 kTLS 的操作系统对 TLS 协议和密码的支持各不相同。
对于 TLSV1.2,KTLS 模块支持以下密码:
对于 TLSv1.3,kTLS 模块支持以下密码套件:
如要验证 NGINX 二进制文件中启用了哪些 OpenSSL 支持的 TLS 密码,请运行构建 NGINX 的目录(例如主目录)中的 openssl-3.0.0/.openssl/bin/openssl ciphers 命令。
我们在文首的介绍中说过,kTLS 可提高 NGINX 的性能,因为所有加密和解密操作都在内核中进行。数据可以直接在内核空间加密,然后传递到网络堆栈进行传输,消除了将数据复制到用户空间、使用 TLS 库对其加密、再返回内核空间进行传输的这一过程的必要性。

在现代 FreeBSD 和 Linux 发行版中,kTLS 通常被构建为一个模块(使用 CONFIG_TLS=m 选项)。在启动 NGINX 之前,必须将 kTLS 模块显式加载到内核。
# kldload ktls ocf
# sysctl kern.ipc.tls.enable=1有关 FreeBSD 命令选项的详细信息,请参阅 ktls(4) 的手册页。
# modprobe tls如要在 FreeBSD 上启用 NGINX 的 kTLS 支持,您可以使用与 Linux 发行版相同的操作说明。但我们建议您执行以下步骤,以便在 FreeBSD 端口集合的 openssl-devel 树中使用支持 kTLS 的 NGINX。有关更多信息(包括 kTLS 概述),请参阅 FreeBSD 网站上的将 TLS 卸载到内核。
1. 构建支持 kTLS 的 OpenSSL 3.0,在配置菜单中选择适当的选项:
# cd /usr/ports/security/openssl-devel && make config && make install
2. 修改 /etc/make.conf,将 openssl-devel 用作 SSL 库:
# echo "DEFAULT_VERSIONS+=ssl=openssl-devel >> /etc/make.conf3. 构建 NGINX:
# cd /usr/ports/security/openssl-devel & make install大多数当前的 Linux 发行版都包含早于 3.0.0(通常是版本 1.1)的 OpenSSL 版本。因此,您需要使用 OpenSSL 3.0.0 从源代码构建 NGINX。
configure 命令中启用 kTLS 支持的两个关键选项是:
另一个 configure 选项面向 NGINX 官方二进制包(请见 nginx.org)中的模块。您还可以指定一组自定义模块。如要查看当前 NGINX 二进制文件的构建选项,请运行 nginx -V。
如要使用 OpenSSL 3.0.0 构建 NGINX,请运行以下命令:
$ wget https://nginx.org/download/nginx-1.21.4.tar.gz
$ wget https://www.openssl.org/source/openssl-3.0.0.tar.gz
$ tar xzf openssl-3.0.0.tar.gz
$ cd nginx-1.21.4
$ ./configure \
--with-debug \
--prefix=/usr/local \
--conf-path=/usr/local/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/run/nginx.lock \
--http-client-body-temp-path=/var/cache/nginx/client_temp \
--http-proxy-temp-path=/var/cache/nginx/proxy_temp \
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
--http-scgi-temp-path=/var/cache/nginx/scgi_temp \
--user=nginx \
--group=nginx \
--with-compat \
--with-file-aio \
--with-threads \
--with-http_addition_module \
--with-http_auth_request_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_mp4_module \
--with-http_random_index_module \
--with-http_realip_module \
--with-http_secure_link_module \
--with-http_slice_module \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_sub_module \
--with-http_v2_module \
--with-mail \
--with-mail_ssl_module \
--with-stream \
--with-stream_realip_module \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--with-openssl=../openssl-3.0.0 \
--with-openssl-opt=enable-ktls \
--with-cc-opt='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' \
-with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'
$ make –j4
$ make install注:生成的 NGINX 二进制文件静态链接到 OpenSSL 3.0.0 库。如果日后需要修补 OpenSSL,您必须下载并解压新的 OpenSSL 源文件,然后运行上述命令重建 NGINX 二进制文件。
如要启用 kTLS,在 server{}中的 ssl_conf_command 指令中添加 Options KTLS 参数,如我们的测试中使用的示例配置:
worker_processes auto;
error_log /var/log/nginx/error.log debug;
events {}
http {
sendfile on;
server {
listen 443 ssl;
ssl_certificate ssl/example.crt;
ssl_certificate_key ssl/example.key;
ssl_conf_command Options KTLS;
ssl_protocols TLSv1.3;
location / {
root /data;
}
}
}如要验证 NGINX 是否正在使用 kTLS,请开启调试模式,并在错误日志中检查 BIO_get_ktls_send() 和 SSL_sendfile()。
$ grep BIO /var/log/nginx/error.log
2021/11/10 16:02:46 [debug] 274550#274550: *2 BIO_get_ktls_send(): 1
2021/11/10 16:02:49 [debug] 274550#274550: *3 BIO_get_ktls_send(): 1
$ grep SSL_sendfile /var/log/nginx/error.log
2021/11/10 16:02:46 [debug] 274550#274550: *2 SSL_sendfile: 1048576
2021/11/10 16:02:49 [debug] 274550#274550: *3 SSL_sendfile: 1048576注:我们建议您在进行这些检查后关闭调试模式(尤其是在生产环境中)。由于存在大量的写入操作,调试日志会导致性能下降;此外,调试日志可能很大,很快就会耗尽磁盘分区上的可用空间。
当在高负载下提供静态文件时,与用户空间 TLS 相比,SSL_sendfile() 可将吞吐量提高最多 2 倍,但性能提升的幅度在很大程度上取决于多种因素(磁盘性能、系统负载等)。如果您的网卡支持 TLS 卸载,它还可以减少 CPU 使用率。
如要测量您的设置的性能提升情况,可以依循以下说明来运行简单的单线程测试。如下所述,我们的测试结果表明,无需进行任何特定调整,kTLS 即可将性能提升近 30%。
使用的硬件和软件:
执行测试的方法:
1. 创建一个完全适合磁盘缓存的大文件:
# truncate -s 1g /data/1G2. 运行以下命令检查吞吐量;多次重复执行基本命令以获得更准确的结果。将输出结果输出到 ministat 实用程序[FreeBSD][Ubuntu],进行基本的统计分析。
# for i in 'seq 1 100'; do curl -k -s -o /dev/null -w '%{speed_download}\n' https://localhost/1G | ministat以下是我们的测试结果,以 ministat 的输出结果表示,每个值都是下载速度,单位是 kBytes/秒。
不支持 kTLS 的 FreeBSD 13.0 的吞吐量:
N Min Max Median Avg Stddev
x 10 532225 573348 555616 555155.6 10239.137支持 kTLS 的 FreeBSD 13.0 的吞吐量:
N Min Max Median Avg Stddev
x 10 629379 723164 717349 708600.4 28304.766支持 kTLS 的 Ubuntu 21.10 的吞吐量:
N Min Max Median Avg Stddev
x 10 529199 705720 662354 654321.6 48025.103支持 kTLS 的 Ubuntu 21.10 的吞吐量:
N Min Max Median Avg Stddev
x 10 619105 760208 756278 741848.3 43255.246在我们的测试中,与 Ubuntu 相比,FreeBSD 上的 kTLS 提升的性能更高。性能改进比例如下:
| 最小值 | 最大值 | 中位数 | 平均数 | |
|---|---|---|---|---|
| FreeBSD 13.0 | 18% | 26% | 29% | 28% |
| Ubuntu 21.10 | 16% | 8% | 14% | 13% |
NGINX 1.21.4 在使用 SSL_sendf ile() 提供静态文件时引入了 kTLS 支持。我们的测试表明,NGINX 性能可提高 8% 到 29%,具体因操作系统而异。
我们很想知道您的 kTLS 和 NGINX 使用体验,尤其是您在其他操作系统上的测试结果!您可以在下方的评论区中分享您的结果。
想要更及时全面地获取NGINX相关的技术干货、互动问答、系列课程、活动资源?
请前往NGINX开源社区:

按点赞数排序
按时间排序
微信公众号
加入微信群