提高NodeJS中SSL服务的性能


Posted in NodeJs onJuly 15, 2014

在浏览互联网时,我们都知道,通过SSL进行加密是非常重要的。在贝宝(PayPal),安全是我们的首要任务。我们使用端到端的加密,不仅只是我们的公共网站,对于我们的内部服务调用也同样如此。SSL加密技术将在很大程度上影响node.js的性能。我们已经花时间调整我们的对外服务,并充分地利用他们。下面是一些我们发现能显著地提高SSL对外性能的SSL配置调整清单。

SSL密码

开箱即用,Node.js 的SSL使用一组非常强大的密码算法。特别是,迪菲赫尔曼密钥交换和椭圆曲线算法是极其昂贵的。而且当你在默认配置中用了太多的对外SSL调用,Node.js的性能将从根本上得到削弱。为了得到它到底有多慢这个结论,这儿有个服务调用的CPU样本:

918834.0ms 100.0% 0.0 node (91770)
911376.0ms 99.1% 0.0  start
911376.0ms 99.1% 0.0  node::Start
911363.0ms 99.1% 48.0  uv_run
909839.0ms 99.0% 438.0  uv__io_poll
876570.0ms 95.4% 849.0   uv__stream_io
873590.0ms 95.0% 32.0    node::StreamWrap::OnReadCommon
873373.0ms 95.0% 7.0     node::MakeCallback
873265.0ms 95.0% 15.0     node::MakeDomainCallback
873125.0ms 95.0% 61.0     v8::Function::Call
873049.0ms 95.0% 13364.0    _ZN2v88internalL6InvokeEbNS0
832660.0ms 90.6% 431.0     _ZN2v88internalL21Builtin
821687.0ms 89.4% 39.0      node::crypto::Connection::ClearOut
813884.0ms 88.5% 37.0       ssl23_connect
813562.0ms 88.5% 54.0       ssl3_connect
802651.0ms 87.3% 35.0        ssl3_send_client_key_exchange
417323.0ms 45.4% 7.0         EC_KEY_generate_key
383185.0ms 41.7% 12.0        ecdh_compute_key
1545.0ms 0.1% 4.0          tls1_generate_master_secret
123.0ms 0.0% 4.0           ssl3_do_write
...

让我们重点关注一下密钥的生成:

802651.0ms 87.3% 35.0 ssl3_send_client_key_exchange
417323.0ms 45.4% 7.0 EC_KEY_generate_key
383185.0ms 41.7% 12.0 ecdh_compute_key

这个调用87%的时间都花在了生成密钥上!

这些密码能被改变以减少密集的计算。这个想法已经在https(或代理)得以实现了。例如:

var agent = new https.Agent({
  "key": key,
  "cert": cert,
  "ciphers": "AES256-GCM-SHA384"
});

上面的密钥已经没用昂贵的迪菲赫尔曼密钥交换。用相似的东西代替之后,在下面的样例中我们能看到显著的变化:

...
57945.0ms 32.5% 16.0 ssl3_send_client_key_exchange
28958.0ms 16.2% 9.0 generate_key
26827.0ms 15.0% 2.0 compute_key
...

通过OpenSSL文档,你可以学习更多关于密码串的东西。

SSL会话恢复
 
如果您的服务器支持SSL会话恢复,那么你可以通过https(或代理)来传递会话。你也可以将代理的createConnection函数包裹起来:

var createConnection = agent.createConnection;

agent.createConnection = function (options) {
  options.session = session;
  return createConnection.call(agent, options);
};

通过给连接增加简短的握手机制,会话恢复能降低连接数的使用。

保持活动
 
允许代理保持活动将缓和SSL握手。一个保持活动的代理,比如agentkeepalive可以修复结点保持活动的问题,但在Node0.12中它是非必须的。

另一个需要铭记在心的东西是代理的maxSockets,这个值高的话能对性能造成负面的影响。在你创建的对外连接数量的基础上控制你的maxSockets值。

Slab的大小
 
tls.SLAB_BUFFER_SIZE决定了被tls客户端(服务器)使用的slab缓冲区的分配大小。它的大小默认为10MB。

这些分配的区间将会扩展你的rss且会增加垃圾回收的时间。这意味着高容量将会影响到性能。把这个容量调整到一个比较低的值可以改善内存和垃圾收集的性能。在0.12 版本中,slab的分配已经得到改善了,没有必须再调整了。

SSL在0.12中近期的改变
 
测试Fedor的SSL增强版。

测试说明

运行一个作为SSL服务代理的http服务,全部运行在本机上。

v0.10.22

Running 10s test @ http://127.0.0.1:3000/
20 threads and 20 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 69.38ms 30.43ms 268.56ms 95.24%
Req/Sec 14.95 4.16 20.00 58.65%
3055 requests in 10.01s, 337.12KB read
Requests/sec: 305.28
Transfer/sec: 33.69KB

v0.11.10-pre (从主版本构建)

Running 10s test @ http://127.0.0.1:3000/
20 threads and 20 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 75.87ms 7.10ms 102.87ms 71.55%
Req/Sec 12.77 2.43 19.00 64.17%
2620 requests in 10.01s, 276.33KB read
Requests/sec: 261.86
Transfer/sec: 27.62KB

这没有太多的区别,但这应归于默认密码,所以让我们调整密码的代理选项。例如:

var agent = new https.Agent({
  "key": key,
  "cert": cert,
  "ciphers": "AES256-GCM-SHA384"
});

v0.10.22

Running 10s test @ http://localhost:3000/
20 threads and 20 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 59.85ms 6.77ms 95.71ms 77.29%
Req/Sec 16.39 2.36 22.00 61.97%
3339 requests in 10.00s, 368.46KB read
Requests/sec: 333.79
Transfer/sec: 36.83KB

v0.11.10-pre (从主版本构建)

Running 10s test @ http://localhost:3000/
20 threads and 20 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 38.99ms 5.96ms 71.87ms 86.22%
Req/Sec 25.43 5.70 35.00 63.36%
5160 requests in 10.00s, 569.41KB read
Requests/sec: 515.80
Transfer/sec: 56.92KB

正如我们所见,经过Fedor的修改,这有着巨大的区别:从0.10到0.12性能差不多差着2倍左右!

总结

有人可能会问“为什么不仅仅只是关掉SSL呢,关了之后它就会变得快起来”,且对于一些人来说这也是一种选择。实际上,当我问别人他们是如何解决SSL性能问题的时候这是比较有代表性的答案。但是,如果企业SSL要求的任何东西只增加不减少;且尽管已经做了很多来改善Node.js中的SSL,性能调整仍然还是需要的。我希望上述的一些技艺能够帮助你调整SSL用例性能。

NodeJs 相关文章推荐
Nodejs进程管理模块forever详解
Jun 01 NodeJs
Nodejs sublime text 3安装与配置
Jun 19 NodeJs
nodejs实现获取当前url地址及url各种参数值
Jun 25 NodeJs
nodejs爬虫抓取数据乱码问题总结
Jul 03 NodeJs
浅谈Nodejs中的作用域问题
Dec 26 NodeJs
NodeJs模拟登陆正方教务
Apr 28 NodeJs
nodejs之get/post请求的几种方式小结
Jul 26 NodeJs
nodejs async异步常用函数总结(推荐)
Nov 17 NodeJs
nodejs中密码加密处理操作详解
Mar 20 NodeJs
Nodejs处理异常操作示例
Dec 25 NodeJs
Nodejs让异步变成同步的方法
Mar 02 NodeJs
Nodejs封装类似express框架的路由实例详解
Jan 05 NodeJs
在NodeJS中启用ECMAScript 6小结(windos以及Linux)
Jul 15 #NodeJs
nodejs 实现模拟form表单上传文件
Jul 14 #NodeJs
14款NodeJS Web框架推荐
Jul 11 #NodeJs
基于promise.js实现nodejs的promises库
Jul 06 #NodeJs
我的NodeJs学习小结(一)
Jul 06 #NodeJs
nodejs中使用monk访问mongodb
Jul 06 #NodeJs
nodejs之请求路由概述
Jul 05 #NodeJs
You might like
php基础知识:函数基础知识
2006/12/13 PHP
使用php判断网页是否gzip压缩
2013/06/25 PHP
CodeIgniter框架URL路由总结
2014/09/03 PHP
tp5框架使用composer实现日志记录功能示例
2019/01/10 PHP
基于jquery的direction图片渐变动画效果
2010/05/24 Javascript
jQuery示例收集
2010/11/05 Javascript
阻止子元素继承父元素事件具体思路及实现
2013/05/02 Javascript
JavaScript获取和设置CheckBox状态的简单方法
2013/07/05 Javascript
JavaScript splice()方法详解
2020/09/22 Javascript
javascript向后台传送相同属性的参数即数组参数
2014/02/17 Javascript
nodejs中操作mysql数据库示例
2014/12/20 NodeJs
JavaScript使用push方法添加一个元素到数组末尾用法实例
2015/04/06 Javascript
jqGrid表格应用之新增与删除数据附源码下载
2015/12/02 Javascript
如何用原生js写一个弹窗消息提醒插件
2019/05/24 Javascript
微信提示 在浏览器打开 效果实现过程解析
2019/09/10 Javascript
[03:06]3分钟带你回顾DOTA2完美盛典&完美大师赛
2017/12/06 DOTA
如何解决django配置settings时遇到Could not import settings 'conf.local'
2014/11/18 Python
Python中的True,False条件判断实例分析
2015/01/12 Python
Python实现对excel文件列表值进行统计的方法
2015/07/25 Python
详解Python中的Descriptor描述符类
2016/06/14 Python
Python编程使用NLTK进行自然语言处理详解
2017/11/16 Python
python按行读取文件,去掉每行的换行符\n的实例
2018/04/19 Python
Pandas之排序函数sort_values()的实现
2019/07/09 Python
Python更新所有已安装包的操作
2020/02/13 Python
Python安装与卸载流程详细步骤(图解)
2020/02/20 Python
浅谈Pytorch torch.optim优化器个性化的使用
2020/02/20 Python
jupyter notebook oepncv 显示一张图像的实现
2020/04/24 Python
查看keras的默认backend实现方式
2020/06/19 Python
Python基于yaml文件配置logging日志过程解析
2020/06/23 Python
Pytest测试框架基本使用方法详解
2020/11/25 Python
保加利亚服装和鞋类购物网站:Bibloo.bg
2020/11/08 全球购物
大学生学习新党章思想汇报
2014/10/25 职场文书
2015年学校信息技术工作总结
2015/05/25 职场文书
2016先进工作者事迹材料
2016/02/25 职场文书
Nginx 根据URL带的参数转发的实现
2021/04/01 Servers
Python爬虫之爬取哔哩哔哩热门视频排行榜
2021/04/28 Python