本次是对一个模块进行压测,该模块对外提供 https 接口,具体功能不用关注,本文主要是介绍整个压测过程当中发现的性能优化点和优化思路。先会把压测结果抛出来,本身先思考为何,因此把分析放在后面。nginx
本次压测主要是对 CPU 进行压测,由于在过程当中发现内存的波动和占用并不大。算法
火焰图工具:go-torchjson
https抓包工具:ssldump缓存
压测工具:ab安全
// 服务最高可用内存为2000Mi,最高可用CPU为4核
limits:
cpu: "4"
memory: 2000Mi
requests:
cpu: "2"
memory: 1000Mi
复制代码
在链接数量极少的状况下,性能消耗主要是在json的序列化和反序列化。以下图:性能优化
(1) 压测命令 此时的qps为500bash
ab -n 100000 -c 100 host
复制代码
(2) 火焰图 从下图能够看出,此时 json 的性能损毁也已经能够忽略不计,主要是在 https 的彻底握手上了。网络
通过上面的分析,咱们大体知道了是由于 https 致使的性能损耗,如今我把服务接口改为 http,再次进行压测,看看结果如何。session
跟上面的同样,性能损耗都是在 json 上。分布式
(1) 压测命令 此时的qps为8000
ab -n 100000 -c 100 host
复制代码
(2) 火焰图 从下图能够看出,此时 json 的性能损毁也已经能够忽略不计,性能主要消耗在网络资源获取,以及一些系统调用:gc,poll等。
在继续往下看以前,但愿你对 https 握手过程已经有了必定的理解。
一次完整的 https 握手,主要的计算点有:
从上面的火焰图咱们能够看到,主要的性能消耗是在彻底握手上,即非对称密钥交换过程,咱们看看该过程为何消耗这么大。 这里盗了个 ECDHE_RSA 密钥交换算法性能图
能够看到,ServerKeyExchange 用了2.4毫秒的时间, ServerKeyExchange 主要是将接下来要使用的密钥交换算法的参数进行签名,因为 RSA 算法会进行不少次的运算,对 CPU 消耗大。
使用 ssldump 抓包发现协商后的算法套件确实为:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
优化思路有两种,一种是减小密钥交换时间的时间,一种是减小握手的次数。
这个是为了减小握手的时间,目前这块咱们线上使用的也是QAT加速卡来加速计算,把计算部分用专门的硬件加速卡来支持,减小CPU的计算量。这块不展开,详情可看intel QAT
server 端会在收到 client hello 后生成一个 sessionID 发给 client 并缓存在本地(会加剧 server 的负担),后续的 SSL 握手,client 在发送 client hello 时候能够带上,server 会进行查找,若是命中则说明可信任。可是目前咱们都是多个 nginx,下一次的请求不必定能落到上一次的 nginx 上,因此可以使用分布式 session cache 来支持。
在彻底握手结束前,server 会给 client 发送一个session ticket,由 client 端进行保存,下次握手时候可带上,若是 server 可以正确解密,则说明能够复用。可是这样在多个 nginx 的场景下,须要多个 nginx 使用相同的私钥。
其实从http的时候的压测过程来看,此时gc已经占到必定的比重了,并且经过监控gc数据可知道,在压测过程gc每分钟达到70次,虽然每次gc耗时很短。这主要是由于使用了大量的临时对象致使的。后续的优化会使用对象池和选择合适GOGC参数。gc日志以下图,有兴趣的能够分析下