TLS握手过程中非对称加密的计算开销,一直是自建CDN节点的性能瓶颈之一。当单个节点需要承载数万并发HTTPS连接时,CPU资源会被大量消耗在RSA和ECC运算上,压缩了业务处理能力。Intel QuickAssist Technology(简称QAT)通过专用硬件加速卡把这些加密运算卸载到独立芯片上执行,能够显著降低CPU占用并提升握手吞吐。本文围绕QAT的工作原理展开,介绍对称与非对称加密卸载机制、OpenSSL QAT Engine的编译安装与配置方法、在Nginx中启用QAT加速的完整流程,并对比硬件卸载前后的性能差异,同时分析压缩与解压缩卸载、NUMA亲和性等进阶调优技巧,帮助构建高并发HTTPS服务时充分利用硬件能力。

QAT硬件卸载的基本原理
QAT是Intel推出的一套加速技术,通常集成在至强可扩展处理器的芯片组中,或者以PCIe插卡的形式存在。它的核心思路很简单:把原本由CPU指令集执行的加密运算,交给专用硬件单元完成。CPU只需要把待处理的数据提交给QAT驱动,然后等待结果返回,中间的计算过程完全不占用通用计算资源。
QAT加速的能力范围主要分三大类。第一类是对称加密,包括AES-GCM、AES-CBC、ChaCha20等算法,这类运算用于TLS记录层的批量数据加密。第二类是非对称加密,也就是公钥算法,包括RSA、ECC、DH、ECDHE等,这是TLS握手阶段最消耗CPU的部分,一次RSA-2048的私钥运算在纯软件模式下可能需要消耗数百万个CPU周期。第三类是压缩与解压缩,支持Deflate和LZ4等算法,可以用于静态内容传输优化。
对于CDN场景来说,价值最大的是非对称卸载。TLS握手时服务端需要执行私钥解密或签名运算,这属于计算密集型操作,而握手之后的对称加密走AES-NI指令集其实已经很快了。QAT把最重的握手计算接过去之后,CPU可以把资源留给连接调度、缓存查询和日志处理等业务逻辑,整体吞吐能力会有明显改善。实测数据表明,在短连接高频握手的场景下,QAT卸载可以让握手吞吐提升数倍,同时CPU占用率下降一半以上。
OpenSSL QAT Engine的编译与安装
QAT本身并不能直接被应用程序使用,它需要通过驱动、运行时库和OpenSSL引擎三层软件栈协同工作。驱动的部分由Intel以内核模块形式提供,运行时库负责与驱动通信,而QAT Engine则以OpenSSL动态引擎的身份挂载到OpenSSL中,应用层无需修改任何代码。
软件准备阶段,需要先确认硬件支持情况。集成了C62x芯片组的至强平台或者安装了8970、8950等QAT PCIe卡的服务器都可以使用,执行lspci | grep QAT可以确认设备是否被识别。接下来安装内核驱动,以常见的CentOS或Ubuntu环境为例,从Intel官网下载对应的QAT驱动包,解压后编译安装:
# 解压驱动包并编译安装 tar xzf QAT20.L.1.0.xx.tar.gz cd QAT20.L.1.0.xx ./configure --enable-icp-sriov=host make -j make install # 加载内核模块并确认设备就绪 modprobe qat_c62x adf_ctl status
驱动装好后,下一步是编译QAT Engine。它依赖OpenSSL 1.1.1或3.x版本,编译时会链接QAT运行时库。整个过程的关键在于指定正确的OpenSSL头文件路径和QAT驱动源码路径:
git clone https://github.com/intel/QAT_Engine.git cd QAT_engine ./autogen.sh ./configure \ --with-qat_dir=/QAT/QAT20.L.1.0.xx \ --with-openssl_dir=/usr/local/openssl \ --with-openssl_install_dir=/usr/local/openssl make -j make install
安装完成后,需要在QAT驱动的配置文件中调整实例数量。默认配置文件位于/etc/CFGM/xml目录下,其中每个加速实例对应一个可用的处理通道。对于CDN这种高并发场景,建议把Cy实例(加密实例)数量调高,让多个工作进程能够并行提交请求。修改完配置后执行adf_ctl restart使其生效。
在Nginx中启用QAT并验证效果
Nginx是自建CDN最常用的边缘节点软件,它基于OpenSSL构建TLS能力,因此启用QAT只需要让Nginx链接支持QAT Engine的OpenSSL版本,并通过环境变量启用引擎。编译Nginx时指定OpenSSL路径:
./configure \ --with-openssl=/usr/local/openssl \ --with-openssl-opt=-no-shared \ --with-http_ssl_module \ --with-http_v2_module make -j && make install
QAT Engine支持两种工作模式。一种是异步模式(QAT_ASYNC_MODE),依赖内核轮询驱动,卸载完全异步执行,性能最好,需要Nginx使用异步握手补丁。另一种是同步模式(QAT_SYNC_MODE),通过轮询方式检查完成状态,兼容性更好,适合不支持异步框架的场景。对于大多数CDN部署,建议优先使用异步模式。启用方式是在Nginx的环境变量中设置:
# 写入Nginx服务的环境配置 export OPENSSL_CONF=/usr/local/openssl/openssl.cnf export QAT_ENGINE_ENABLE=1 export QAT_ENGINE_MODE=ASYNC # openssl.cnf中追加引擎配置 openssl_conf = openssl_init [openssl_init] engines = engine_section [engine_section] qatengine = qat_section [qat_section] engine_id = qatengine dynamic_path = /usr/local/openssl/lib/engines-1.1/qatengine.so default_algorithms = ALL init = 1
配置完成后重启Nginx,通过openssl engine -t qatengine可以验证引擎是否加载成功。性能测试推荐使用支持TLS的工具进行压测,分别对比纯软件和QAT卸载两种模式下的每秒握手数和CPU占用。典型的测试结果是:在RSA-2048证书、100%新连接的场景下,启用QAT后单节点握手吞吐提升3到5倍,CPU利用率下降约40%到60%。如果是ECC证书,提升幅度相对小一些,但依然可观,因为ECDSA的软件实现在现代CPU上已经比较高效。
进阶调优与常见问题
第一点是NUMA亲和性。在双路服务器上,QAT设备挂载在特定的NUMA节点,如果Nginx工作进程运行在远端节点,跨NUMA访问会带来额外的内存传输延迟。建议用numactl把Nginx绑定到QAT所在的NUMA节点,同时开启QAT驱动的Instance-to-Process亲和绑定功能,让进程优先使用本地的加速实例。
第二点是连接复用策略。QAT卸载的收益主要体现在握手阶段,如果CDN通过会话票据或TLS 1.3的会话恢复把握手比例降到很低,那么QAT的收益也会随之下降。实际部署中应该结合业务连接模式评估:短连接、高频握手的场景收益最大,长连接大流量的场景则更应该关注对称加密和压缩卸载。另外,开启QAT的压缩卸载功能后,可以把gzip压缩也交给硬件处理,这对手Gzip、手Deflate等压缩运算也有明显减负效果。
第三点是稳定性排查。QAT Engine作为一个相对独立的软件层,偶尔会出现实例耗尽或句柄泄漏的问题,典型表现是握手延迟突然升高甚至超时。排查时可以用adf_ctl status查看实例状态,通过系统日志中的错误信息定位原因。建议在Nginx配置中保留SSL会话缓存,减少突发流量对QAT实例的冲击,并且对引擎版本和内核版本做充分测试后再上生产环境。
总体来看,QAT卸载是自建CDN在不增加服务器数量的前提下提升HTTPS承载能力的有效手段。它把最消耗CPU的TLS握手计算转移给专用硬件,让CPU资源回归业务本身。对于已经采购了支持QAT平台的团队来说,这几乎是一份免费的性能红利,值得认真挖掘。