提高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批量修改文件编码格式
Jan 22 NodeJs
nodeJS代码实现计算交社保是否合适
Mar 09 NodeJs
实例详解Nodejs 保存 payload 发送过来的文件
Jan 14 NodeJs
nodejs中使用HTTP分块响应和定时器示例代码
Mar 19 NodeJs
nodejs入门教程五:连接数据库的方法分析
Apr 24 NodeJs
nodejs制作爬虫实现批量下载图片
May 19 NodeJs
nodejs操作mongodb的填删改查模块的制作及引入实例
Jan 02 NodeJs
nodejs使用redis作为缓存介质实现的封装缓存类示例
Feb 07 NodeJs
nodejs连接mysql数据库及基本知识点详解
Mar 20 NodeJs
nodeJS模块简单用法示例
Apr 21 NodeJs
详解nodejs解压版安装和配置(带有搭建前端项目脚手架)
Dec 06 NodeJs
监控Nodejs的性能实例代码
Jul 02 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入门学习知识点三 PHP上传
2011/07/14 PHP
Linux fgetcsv取得的数组元素为空字符串的解决方法
2011/11/25 PHP
支持中文字母数字、自定义字体php验证码代码
2012/02/27 PHP
php访问数组最后一个元素的函数end()用法
2015/03/18 PHP
php5.5使用PHPMailer-5.2发送邮件的完整步骤
2018/10/14 PHP
Jquery ajax不能解析json对象,报Invalid JSON错误的原因和解决方法
2010/03/27 Javascript
jQuery对象与DOM对象之间的转换方法
2010/04/15 Javascript
jquery二级导航内容均分的原理及实现
2013/08/13 Javascript
js的.innerHTML = ""IE9下显示有错误的解决方法
2013/09/16 Javascript
jQuery窗口、文档、网页各种高度的精确理解
2014/07/02 Javascript
微信小程序 合法域名校验出错详解及解决办法
2017/03/09 Javascript
Node.JS利用PhantomJs抓取网页入门教程
2017/05/19 Javascript
Kindeditor单独调用多图上传实例
2017/07/31 Javascript
利用纯js + transition动画实现移动端web轮播图详解
2017/09/10 Javascript
详解Javascript 中的 class、构造函数、工厂函数
2017/12/20 Javascript
vue iview组件表格 render函数的使用方法详解
2018/03/15 Javascript
基于vue实现web端超大数据量表格的卡顿解决
2019/04/02 Javascript
Vue keepAlive 数据缓存工具实现返回上一个页面浏览的位置
2019/05/10 Javascript
layui上传图片到服务器的非项目目录下的方法
2019/09/26 Javascript
Vue项目结合Vue-layer实现弹框式编辑功能(实例代码)
2020/03/11 Javascript
Python中非常实用的一些功能和函数分享
2015/02/14 Python
Python中将字典转换为列表的方法
2016/09/21 Python
windows下python安装小白入门教程
2018/09/18 Python
基于Python实现定时自动给微信好友发送天气预报
2018/10/25 Python
使用Python获取网段IP个数以及地址清单的方法
2018/11/01 Python
python类的实例化问题解决
2019/08/31 Python
对Python 字典元素进行删除的方法
2020/07/31 Python
建设单位项目负责人任命书
2014/06/06 职场文书
高中综合实践活动总结
2014/07/07 职场文书
学校领导班子对照检查材料
2014/08/28 职场文书
幼儿园迎国庆65周年活动策划方案
2014/09/16 职场文书
授权委托书
2015/01/28 职场文书
领导视察通讯稿
2015/07/18 职场文书
2016年毕业实习心得体会范文
2015/10/09 职场文书
创业计划书之DIY自助厨房
2019/09/06 职场文书
分享Python获取本机IP地址的几种方法
2022/03/17 Python