Nginx* HTTPS 优化指南 - 基于第 3 代英特尔® 至强® 可扩展处理器及 Crypto-NI 技术

发布日期: 08/17/2021

介绍

Nginx* 由俄罗斯软件工程师 Igor Sysoev 开发,是一款基于类似 BSD 许可的高性能 HTTP 和逆向代理 web 服务器。同时,它还可以提供 IMAP/POP3/SMTP 服务。自 2004 年第一版发布以来市场普及率逐年攀升,目前在许多一线互联网公司和 IT 企业中都得到广泛使用。Nginx 的架构设计非常灵活,有一个非常小巧简洁的内核,其中包含内核模块、基本模块和三方模块。它通过文件静态映射和可配置指令与模块协作,在 HTTP 代理、静态和动态分离、负载均衡、虚拟主机、逆向代理、高速缓存加速、授权访问等各种应用场景中突出高性能、高并发和低内存的显著优势。

nginx 架构

有关 Nginx 的更多信息请访问:http://nginx.org

Nginx 遵循 SSL/TLS 来加强 web 站点的访问安全性。英特尔已推出基于第 3 代英特尔® 至强® 可扩展处理器(代号 Ice Lake/Whitley)的 Crypto-NI 软件解决方案。它可以有效提高网络访问的安全性。

Crypto-NI(NI 指代新指令)是第 3 代英特尔® 至强® 可扩展处理器中关于加密和解密领域的新指令集,在之前英特尔® 至强® 可扩展处理器已经具备的英特尔® 高级加密标准新指令(英特尔® AES-NI)的基础上增加了矢量化 AES 和整数融合乘法加法等新指令。该解决方案使用的主要软件为 IPP 加密库、英特尔 Multi-Buffer Crypto for IPsec Library (intel-ipsec-mb) 和英特尔® 通信加速技术(英特尔® QAT),可提供多个 SSL 请求的批量提交和基于新指令集的并行异步处理机制,极大地提高了性能。

nginx 软件

系统所需软硬件环境如下:

服务器配置

硬件

CPU

英特尔® 至强® PLATINUM 8360Y CPU @ 2.20GHz

内存

16 个 32GB DDR4,3200 MT/秒

硬盘

英特尔固态硬盘 S4610,960G

网卡

英特尔® 以太网控制器 XXV700 25GbE SFP28

软件

操作系统

CentOS* 7.8

内核

3.10.0-1127.el7.x86_64

Nginx

asynch_mode_nginx v0.4.4

OpenSSL

v1.1.1j

IPP 加密库

ippcp_2020u3

Multi-Buffer Crypto for IPsec Library

v0.55

英特尔 QAT 引擎

v0.6.4

注意:

  • 本文中描述的配置基于第 3 代英特尔® 至强® 可扩展处理器的指令集。前几代处理器不支持所有的这些相同选项。内存、硬盘、网卡可视客户用量需求确定。
  • 此配置中列出的软件可参考 https://github.com/intel/QAT_Engine 此链接指向的页面中描述了支持的每个软件的最旧版本。本文中列出的软件版本均满足以上要求,并已经过验证和测试。
  • Asynch_mode_nginx 是 Nginx 经过优化的版本,英特尔将其用于支持 Nginx 硬件和软件加速。下载之后可直接编译。相关说明请参阅以下链接:https://github.com/intel/asynch_mode_nginx
  • 适用于 OpenSSL 的 QAT 引擎链接:https://github.com/intel/QAT_Engine

BIOS 设置

BIOS 可优化配置项及推荐值如下:

配置项

推荐值

超线程

启用

CPU C6 报告

自动

SpeedStep (Pstates)

启用

Turbo 模式

启用

PCIe 链路速度

Gen4

节能加速技术

禁用

启动性能模式

最高性能

Linux* 优化

系统优化

     1.设置相应的系统启动参数

intel_iommu=off

processor.max_cstates=1 idle=poll pcie_aspm=off

     2.关闭 cpupower 服务

systemctl stop cpupower.service

     3.关闭防火墙

systemctl disable firewalld.service

     4.用户进程设置

ulimit -c unlimited #generate core dump

ulimit -n 1000000 #set the maximum number of file open handles

网络优化

  • 准备如下 tune_affinity.sh 脚本用于设置网卡队列中断的 CPU 亲和性,可将网卡队列的中断均匀分发到本机的 CPU 内核:
set_affinity()

{

    if [ $VEC -ge 32 ]

    then

        MASK_FILL=""

        MASK_ZERO="00000000"

        let "IDX = $VEC / 32"

        for ((i=1; i<=$IDX;i++))

        do

            MASK_FILL="${MASK_FILL},${MASK_ZERO}"

        done



        let "VEC -= 32 * $IDX"

        MASK_TMP=$((1<<$VEC))

        MASK=`printf "%X%s" $MASK_TMP $MASK_FILL`

    else

        MASK_TMP=$((1<<$VEC))

        MASK=`printf "%X" $MASK_TMP`

    fi



    printf "%s mask=%s for /proc/irq/%d/smp_affinity\n" $DEV $MASK $IRQ

    printf "%s" $MASK > /proc/irq/$IRQ/smp_affinity

}



if [ "$1" = "" ] ; then

    echo "Description:"

    echo " This script attempts to bind each queue of a multi-queue NIC"

    echo " to the same numbered core, ie tx0|rx0 --> cpu0, tx1|rx1 --> cpu1"

    echo "usage:"

    echo " $0 eth0 [eth1 eth2 eth3]"

fi



# check for irqbalance running

#

IRQBALANCE_ON=`ps ax | grep -v grep | grep -q irqbalance; echo $?`

if [ "$IRQBALANCE_ON" == "0" ] ; then

    echo " WARNING: irqbalance is running and will"

    echo " likely override this script's affinitization."

    echo " Please stop the irqbalance service and/or execute"

    echo " 'killall irqbalance'"

fi



# Set up the desired devices.

#

for DEV in $*

do

  for DIR in rx tx TxRx

  do

     MAX=`grep $DEV-$DIR /proc/interrupts | wc -l`

     if [ "$MAX" == "0" ] ; then

       MAX=`egrep -i "$DEV:.*$DIR" /proc/interrupts | wc -l`

     fi

     if [ "$MAX" == "0" ] ; then

       echo no $DIR vectors found on $DEV

       continue

     fi

     for VEC in `seq 0 1 $MAX`

     do

        IRQ=`cat /proc/interrupts | grep -i $DEV-$DIR-$VEC"$" | cut -d:  -f1 | sed "s/ //g"`

        if [ -n "$IRQ" ]; then

          set_affinity

        else

           IRQ=`cat /proc/interrupts | egrep -i $DEV:v$VEC-$DIR"$" | cut -d:  -f1 | sed "s/ //g"`

           if [ -n "$IRQ" ]; then

             set_affinity

           fi

        fi

     done

  done

done
  • 执行 shell 脚本:
$ sh tune_affinity.sh <network interface card name>

Crypto-NI 安装

IPP Cryptography Library 和 intel-ipsec-mb 安装

  • 下载 IPP 加密库源代码
$ git clone --recursive https://github.com/intel/ipp-crypto.git
  • 构建并安装 IPP 加密库
$ cd ipp-crypto

$ git checkout ipp-crypto_2020_update3

$ cd sources/ippcp/crypto_mb

$ cmake . -Bbuild -DCMAKE_INSTALL_PREFIX=/usr

$ cd build

$ make -j

$ make install
  • 下载 intel-ipsec-mb 源代码
$ git clone https://github.com/intel/intel-ipsec-mb.git

 

  • 构建并安装 intel-ipsec-mb
$ cd intel-ipsec-mb

$ git checkout v0.55

$ make -j SAFE_DATA=y SAFE_PARAM=y SAFE_LOOKUP=y

$ make install NOLDCONFIG=y

OpenSSL* 和 QAT 引擎安装

  • 下载 OpenSSL 源代码
$ cd /usr/local/src

$ wget https://www.openssl.org/source/openssl-1.1.1j.tar.gz

 

  • 构建并安装 OpenSSL
$ tar xvzf openssl-1_1_1j.tar.gz

$ cd ./openssl-1_1_1j

$./config --prefix=/usr/local/ssl -Wl,-rpath, /usr/local/ssl/lib

$ ./make

$ ./make install
  • 下载 QAT 引擎源代码
$ export OPENSSL_ENGINES=/usr/local/ssl/lib/engines-1.1

$ cd /usr/local/src

$ git clone https://github.com/intel/QAT_Engine.git
  • 构建并安装 QAT 引擎
$cd /QAT_Engine

$./autogen.sh

$./configure 

--with-openssl_install_dir=/usr/local/ssl 

--enable-ipsec_offload 

--enable-multibuff_offload 

--with-multibuff_install_dir=/root/ipp-crypto/sources/ippcp/crypto_mb

$ make

$ make install

以上构建和安装指令在新版本中可能会有所更改。请参阅以下 URL 来执行最新的构建和安装指令:

https://github.com/intel/QAT_Engine.git

$ ls /usr/local/ssl//lib/engines-1.1/*

列出以下文件:capi.so padlock.so qatengine.la qatengine.so

运行以下命令,以检查 QAT 引擎是否加载正常。

$./openssl engine -t -c -vvvv qatengine
  • 用户使用 openssl speed 命令可查看和验证使用 QAT 引擎之前或之后的信息。
$/usr/local/ssl/bin/openssl speed rsa2048

$/usr/local/ssl/bin openssl speed -engine qatengine -async_jobs 8 rsa2048

Nginx 安装及优化设置

Nginx 安装

  • 完成 Crypto-NI 相关软件/硬件的安装和设置。
  • 下载 Nginx 源代码
$ git clone https://github.com/intel/asynch_mode_nginx.git

 

  • 构建并安装 Nginx
$ cd asynch_mode_nginx

$ export NGINX_INSTALL_DIR=<Nginx installation directory>

$ export OPENSSL_LIB=<SSL installation directory>

$./configure 

--prefix=$NGINX_INSTALL_DIR 

--with-http_ssl_module 

--add-dynamic-module=modules/nginx_qat_module 

--with-cc-opt="-DNGX_SECURE_MEM -I$OPENSSL_LIB/include -Wno-error=deprecated-declarations" 

--with-ld-opt="-Wl,-rpath=$OPENSSL_LIB/lib -L$OPENSSL_LIB/lib"

$ make

$ make install
  • 启动 Nginx 服务

完成 Nginx 设置之后,在 Nginx 安装目录下执行 $ ./sbin/nginx 命令,以启动 Nginx 服务。

Nginx 优化设置

     1.生成 RSA 自签名证书和密钥文件。

$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout server.key -out server.crt -subj "/C=CN/ST=Beijing/L=Beijing/O=Example Inc./OU=Web Security/CN=example1.com"

Nginx 安装目录下新建 cert 目录,然后复制 server.crtserver.key 到该目录下。

     2.关键 nginx 配置。在 nginx.conf 文件中设置如下参数:

  • 设置工作进程数量和事件模式
worker_processes <number of worker processes>; # it is recommended to have the same number of worker processes as the number of CPU cores on server

events {

Use epoll; #epoll is an enhanced version of select/poll that improves the handling of large number of file descriptors

…

}
  • 加载和设置 SSL 引擎模块

l

oad_module modules/ngx_ssl_engine_qat_module.so;

ssl_engine {

use_engine qatengine;

default_algorithms ALL;

qat_engine {

qat_offload_mode async;

qat_notify_mode poll;

qat_poll_mode heuristic;

qat_shutting_down_release off;

   }

}
  • 设置 HTTPS 服务器
server {

Listen 443 ssl reuseport so_keepalive=on... ; #if you want to verify the SSL handshake performance, then set it to off.

sendfile on;

Server_name example1.com; #consistent with certificate CN

ssl_asynch on;

ssl_session_tickets on; #set it to off, if you want to verify the SSL handshake performance

ssl_certificate <Nginx installation directory>/cert/server.crt;

ssl_certificate_key <Nginx installation directory>/cert/server.key;

ssl_ciphers AES256-SHA:AES128-SHA;

#You can set other cipher suites according to customer needs, to verify the performance of different authentication, encryption and decryption protocols

ssl_prefer_server_ciphers on;

…

}

     3. nginx.conf 的完整配置示例,适用于 RSA2K 握手性能测试:

user root;

worker_processes 8;

load_module modules/ngx_ssl_engine_qat_module.so;

events {

use epoll;

worker_connections 8192;

multi_accept on;

accept_mutex on;

}

ssl_engine {

use_engine qatengine;

default_algorithms ALL;

qat_engine {

qat_offload_mode async;

qat_notify_mode poll;

qat_poll_mode heuristic;

qat_shutting_down_release off;

 }

}

http {

server {

listen example1:443 ssl reuseport backlog=131072 so_keepalive=off rcvbuf=65536 sndbuf=65536;

keepalive_timeout 0s;

ssl_verify_client off;

ssl_session_tickets off;

access_log off;

ssl_asynch on;

ssl_session_timeout 300s;

ssl_protocols TLSv1.2;

ssl_ciphers AES128-SHA;

ssl_prefer_server_ciphers on;

ssl_certificate server2048.crt;

ssl_certificate_key server2048.key;

location / {

root html;

index index.html index.htm;

  }

 }

}

相关工具介绍

Web 服务器压力测试工具

本节我们将介绍两款网络服务器压力测试工具:wrkab

  1. wrk 是一款面向 HTTP/HTTPS 协议的基准测试工具。在由多核 CPU 支持的单台机器上,它可以使用系统的高性能 I/O 机制(如 epollkqueue),在多线程和事件 I/O 模式下在目标机器上产生巨大的工作负载。

使用示例:(用户将用他们自己的 Nginx URL 替换 URL)

$ wrk -t 10 -c 1000 -d 30S https://example1.com:443/index.html

说明:命令使用 10 个线程 1000 个并发连接取文件,对服务器进行 30 秒的压力测试。更多信息请访问 https://github.com/wg/wrk

  1. ab 工具时 Apache* 自带的压力测试工具。它不仅可以对 apache 服务器进行网站访问压力测试,也可以对或其它类型的服务器进行压力测试。例如,NginxApache Tomcat* IIS。如果用户已安装 Apache,则 ab 工具已随 Apache 安装。如果用户尚未安装 Apache,那么可以使用以下命令轻松安装 (CentOS*):
$ yum -y install httpd-tools

使用示例:(用户将用他们自己的 Nginx URL 替换 URL)

$ ab -n 100000 -c 100 -Z AES128-SHA -f TLS1.2 https://example1.com:443/index.html

 

说明:命令使用 100 个并发发送 100000 个请求 get index 文件,对服务器进行压力测试。更多信息请访问 https://httpd.apache.org/docs/2.4/programs/ab.html

 

 


通知和免责声明

英特尔技术可能需要支持的硬件、软件或服务激活。

没有任何产品或组件能保证绝对安全。

您的成本和结果可能会有所不同。

英特尔使用代号来标识正在开发且未公开的产品、技术或服务。这些并非“商用”名称,也不会被用作商标

所述产品可能包含设计缺陷或错误(即勘误表),这可能会使产品与已发布的规范有所偏差。可应要求提供当前的勘误表。

© 英特尔公司。英特尔、英特尔标志和其他英特尔标识是英特尔公司或其子公司的商标。文中涉及的其它名称及商标属于各自所有者资产。

产品和性能信息

1

性能因用途、配置和其他因素而异。请访问 www.Intel.cn/PerformanceIndex 了解更多信息。