提高NodeJS中SSL服务的性能

在浏览互联网时,我们都知道,通过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用例性能。

(0)

相关推荐

  • 我的NodeJs学习小结(一)

    这第一篇就谈谈NodeJs的一些编程细节吧. 1.遍历数组 for (var i=0, l=arr.length; i<l; i++) 这样写的一个好处就是让每次循环少一步获取数组对象长度的操作,数组长度越长,价值越明显. 2.判断变量的真假 if (a) {...} //a='', a='0', a=[], a={} if条件判断的结果分别是:false, true, true, true.这个结果和PHP的结果是不同的,不要混淆.还需要区分它和非恒等判断相似的情况. 3.0值非恒等判断 1

  • nodejs文件操作模块FS(File System)常用函数简明总结

    件系统操作相关的函数挺多的.首先可以分为两大类. 一类是异步+回调的. 一类是同步的. 在这里只对异步的进行整理,同步的只需要在函数名称后面加上Sync即可 1. 首先是一类最常规的读写函数,函数名称和形式,应该是起源于C语言的. 复制代码 代码如下: fs.open(文件路径,读写标识,[文件mode值,666],回调函数(err,文件句柄fd));          fs.read(文件句柄fd,被写入的buffer,offset,length,position,回调函数(err, byte

  • Nodejs sublime text 3安装与配置

    1) 下载sublime并安装,下载列表:http://www.jb51.net/softs/132432.html 2) 下载sublime的nodejs插件,需是集成Nodejs插件到sublime中,下载地址:https://github.com/tanepiper/SublimeText-Nodejs 3)   解压zip文件, 并重命名文件夹"Nodejs" 4)   打开sublime,操作"preference" --> "Browse

  • Node.js(安装,启动,测试)

    概念 Node.js 是构建在Chrome javascript runtime之上的平台,能够很容易的构建快速的,可伸缩性的网络应用程序.Node.js使用事件驱动,非阻塞I/O 模式,这使它能够更轻量,高效且完美的适用于运行在分布式设备之间的数据密集型实时应用程序. 安装 这里主要介绍基于windows平台上最简单方便的安装方式,我们首先直接访问node.js官方网站http://www.nodejs.org/,直接点击Install按钮开始下载安装. 点击Run按钮开始运行 继续点击Nex

  • 如何正确使用Nodejs 的 c++ module 链接到 OpenSSL

    事情的起因是这样的, 因为某些原因, 最近在写 Nodejs 的 c++ module, 然后在js这边调用.  网络通信自然离不开ssl, 于是需要链接到Openssl的库. 我们本来的期望是,需要用户安装有Openssl的运行库, 然后我们的c++ module 动态链接到Openssl的so库上来运行. 起初一切看起来还不错,直到我们发现这个openssl的函数不能工作: PKCS7_sign() PKCS7_sign ( ) 我们发现: 如果我们的 c++ 模块与Openssl库动态链接

  • nodejs的10个性能优化技巧

    下面是我们使用Node.js时遵循的10个性能规则: 1. 避免使用同步代码 在设计上,Node.js是单线程的.为了能让一个单线程处理许多并发的请求,你可以永远不要让线程等待阻塞,同步或长时间运行的操作.Node.js的一个显著特征是:它从上到下的设计和实现都是为了实现异步.这让它非常适合用于事件型程序. 不幸的是,还是有可能会发生同步/阻塞的调用.例如,许多文件系统操作同时拥有同步和异步的版本,比如writeFile和writeFileSync.即使你用代码来控制同步方法,但还是有可能不注意

  • 提高NodeJS中SSL服务的性能

    在浏览互联网时,我们都知道,通过SSL进行加密是非常重要的.在贝宝(PayPal),安全是我们的首要任务.我们使用端到端的加密,不仅只是我们的公共网站,对于我们的内部服务调用也同样如此.SSL加密技术将在很大程度上影响node.js的性能.我们已经花时间调整我们的对外服务,并充分地利用他们.下面是一些我们发现能显著地提高SSL对外性能的SSL配置调整清单. SSL密码 开箱即用,Node.js 的SSL使用一组非常强大的密码算法.特别是,迪菲赫尔曼密钥交换和椭圆曲线算法是极其昂贵的.而且当你在默

  • 用 FieldMask 提高 C# gRpc 的服务性能

    目录 前言: 一.FieldMask 二.Demo ​1.定义.proto文件​ ​2.实现服务端​ ​3.实现客户端​ ​4.修改服务端​ 前言: 想象一下,有一个服务提供个多个客户端调用,但不是所有客户端都需要全部的返回参数: ​比如商品列表服务返回商品的所有信息,而订单服务调用商品列表服务,但它其实只需要商品的编码和名称就够了.​ 当然,我们可以为这个需求单独创建一个服务,但是这样不太灵活,比如又需要商品的编码和分类的时候怎么办? 但是,大而全的服务方法会导致计算和传输成本可能很高,如果我

  • Nodejs中koa2连接mysql的实现示例

    目录 将查询结果转为对象或者数组 mysql2的使用 Prepared Statement(预处理语句) Connection Pools(连接池) Promise方式 sequelize Sequelize的使用 Sequelize的单表操作 Sequelize的一对多操作 Sequelize的多对多操作 将查询结果转为对象或者数组 在真实开发中,实际上某些查询结果应该放入到一个对象中 JSON_OBJECT:()中是key-value的形式 SELECT products.id as id,

  • nodejs中使用多线程编程的方法实例

    在以前的博文别说不可能,nodejs中实现sleep中,我向大家介绍了nodejs addon的用法.今天的主题还是addon,继续挖掘c/c++的能力,弥补nodejs的弱点. 我曾多次提到过nodejs的性能问题.其实就语言本身而言,nodejs的性能还是很高的,虽然不及大多部静态语言,但差距也并不大:相对其他动态语言而言,速度优势非常明显.但为什么我们常常说nodejs不能胜任CPU密集型场景呢?因为由于其单线程特性,对于CPU密集型场景,它并不能充分利用CPU.计算机科学中有一个著名的A

  • 基于Nuxt.js项目的服务端性能优化与错误检测(容错处理)

    nuxt.js 是一个基于 Vue.js 的服务端渲染应用框架,使用nuxt.js在做同构项目开发时,需要考虑的一些点总结如下: 一.node服务端性能优化(提高node应用程序处理高流量的能力) 基于nuxt.js的服务端渲染项目我们能做的服务端性能优化有以下几点(需要注意的是持久化缓存不应该在本地开发环境去做,这样在缓存期间不会暴露本地开发中代码的问题) 优化点 参考文档及思路 优化场景/条件 特别说明 检测方法 1. 页面缓存 vue官方文档 页面内容不是用户特定(即对于相同的 URL,总

  • nodejs中的读取文件fs与文件路径path解析

    目录 什么是nodejs? global模块-全局变量 fs模块 读取文件 写文件 追加文件 文件同步与异步的说明 path模块 路径操作的问题 path模块的常用方法 什么是nodejs? Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,nodejs允许javascript代码运行在服务端 1. nodejs不是一门新的编程语言,nodejs是在服务端运行javascript的运行环境 2. 运行环境:写得程序想要运行必须要有对应的运行环境 php代码必

  • nodejs中art-template模板语法的引入及冲突解决方案

    使用Webstorm创建nodejs express应用时,默认使用的是jade或者ejs模板,对于不习惯这两种模板语法的人来说确实不是很方便.没关系,这里我们使用art-template模板引擎,使用后可以直接使用html模板: 1.安装art-template npm install art-template 2.修改app.js文件,添加如下代码: // view engine setup app.set('views', path.join(__dirname, 'views')); v

  • Nodejs中 npm常用命令详解

    npm是什么 NPM的全称是Node Package Manager,是随同NodeJS一起安装的包管理和分发工具,它很方便让JavaScript开发者下载.安装.上传以及管理已经安装的包. npm是一个node包管理和分发工具,已经成为了非官方的发布node模块(包)的标准.有了npm,可以很快的找到特定服务要使用的包,进行下载.安装以及管理已经安装的包. 1.npm install moduleNames:安装Node模块 安装完毕后会产生一个node_modules目录,其目录下就是安装的

  • nodejs中向HTTP响应传送进程的输出

    废话不多说了,直接给大家贴代码了,具体代码如下所述: var spawn = require('child_process').spawn; require('http').createServer(function(req, res) { var child = spawn('tail', ['-f', '/var/log/system.log']);//当有一个新的请求出现时,就通过执行 tail -f /var/log/system.log命令启动一个新的进程 child.stdout.p

  • Nodejs之TCP服务端与客户端聊天程序详解

    TCP是用来计算机之间进行通信的,通过编写客户端和服务端聊天的代码,对于服务器与客户端的工作步骤有了深刻的了解,在这里根据了不起的Node.js一书来总结一下. TCP聊天程序需要用到Nodejs中的net模块,net模块是对TCP的封装,用于创建TCP服务端与客户端的. 服务器端 count:连接的客户端个数: users:用于存储客户端用户昵称的对象,对象值都为该客户端的Socket,Socket是一个接口,用于服务端与客户端通信. net.createServer:是用来创建TCP服务器,

随机推荐