阅读更多



【译注】:LinkedIn 最近从 Rails转移到 Node.js 获得了巨大的成功,它砍掉了之前90%的服务器,并使性能提升了20倍。这个消息令很多人把 Node.js 看成了葵花宝典一样的神功,可是练习神功也不是一朝一夕的事,光练招式没有内功也是不成的,更何况还得…那啥…总之不容易啊!那么除了Node.js,LinkedIn 的性能提升还有什么秘密?LinkedIn 的软件工程师 Shravya Garlapati 写的这篇文章可以给我们一些启示。

以下是译文:

在之前的文章里,我们讨论了我们如何测试LinkedIn的移动服务集群,包括我们的 Node.js 移动端服务器。今天,我们想给你们说说我们是如何让这个服务器快速运行的。这里就是我们在 Node.js 上的十大性能提升秘籍:

1. 避免同步的代码

Node.js 从一开始的设计就是单线程的。要让一个线程处理很多并发请求,你就永远不要让这个线程在阻塞、同步或运行时间很长的操作中等待。Node.js的一个超凡脱俗的特性就是它从上到下都是设计和实现为异步模式。这使它对事件驱动的应用是绝配。

不幸的是,在Node.js里进行同步/阻塞式的调用还是有可能的。例如,很多文件系统操作都提供了异步和同步版本,例如writeFile和writeFileSync。即便你在自己的代码里避免了同步方法,却有可能漫不经心地引入了一个外部库,而在该库中使用了阻塞式调用。当你这么做了之后,它对性能的影响是巨大的。

// Good: write files asynchronously
fs.writeFile('message.txt', 'Hello Node', function (err) {
  console.log("It's saved and the server remains responsive!");
});
 
// BAD: write files synchronously
fs.writeFileSync('message.txt', 'Hello Node');
console.log("It's saved, but you just blocked ALL requests!");


我们最初的日志实现就偶然性地引入了一个写入磁盘的同步调用。在我们进行性能测试之前,没人注意到它的存在。当我们在一台开发机上对比单个Node.js服务器性能的时候,这一个同步调用导致性能从每秒处理1000个请求下降到几十个!

2. 关闭socket池

Node.js的http模块会自动使用socket池,缺省是每台主机限制为5个socket。虽然这种socket复用方式可能对控制资源增长的速度有利,但如果你需要处理很多同时需要从同一台主机获取数据的并发请求,这个socket池会成为严重的性能瓶颈。在这种情况下,好的办法是增大maxSockets参数或者干脆把socket池disable掉。

// Disable socket pooling
 
var http = require('http');
var options = {.....};
options.agent = false;
var req = http.request(options)


3. 不要用Node.js处理静态资源

对于静态资源,例如CSS和图像,使用标准的web服务器而不是Node.js来处理。例如,LInkedIn mobile使用nginx。我们还利用内容分发网络(CDN),它能把静态资源复制到分布在全世界的很多服务器上。这样做有两大益处:①减少了Node.js服务器的负载,②CDN能让静态内容从离用户比较近的服务器上传输过去,这样减少了延迟。

4. 在客户端渲染页面

让我们快速比较一下服务器端渲染和客户端渲染页面。如果我们让Node.js在服务器端渲染,我们会对所有请求发回一个类似于本文的HTML页面。

<!-- An example of a simple webpage rendered entirely server side -->
 
<!DOCTYPE html>
<html>
  <head>
    <title>LinkedIn Mobile</title>
  </head>
  <body>
    <div class="header">
      <img src="http://mobile-cdn.linkedin.com/images/linkedin.png" alt="LinkedIn"/>
    </div>
    <div class="body">
      Hello John!
    </div>
  </body>
</html>


请注意,在这个页面上,除了用户名之外,所有内容都是静态的:也就是说,对于每个用户和每次刷新都是完全相同的。所以更有效率的方法是让Node.js只以JSON格式返回页面所需的动态数据。

{"name": "John"}


页面的其他部分,也就是所有的静态HTML标记,可以放到一个JavaScript模板里(例如一个underscore.js模板)。

<!-- An example of a JavaScript template that can be rendered client side -->
 
<!DOCTYPE html>
<html>
  <head>
    <title>LinkedIn Mobile</title>
  </head>
  <body>
    <div class="header">
      <img src="http://mobile-cdn.linkedin.com/images/linkedin.png" alt="LinkedIn"/>
    </div>
    <div class="body">
      Hello <%= name %>!
    </div>
  </body>
</html>


性能的受益是这么来的:根据秘籍3,静态JavaScript模板可以从你的web服务器(例如nginx)或者CDN获取。而且,JavaScript模板可以缓存在客户端或保存在本地存储,这样初始加载页面之后,唯一需要传给客户端的就是动态JSON数据,这是最高效率的做法。该方法极大地减少了Node.js服务器上占用的CPU, IO和负载。

5. 使用gzip压缩

大部分服务器和客户端都支持gzip压缩请求和响应的数据。一定要在对客户端发送响应和对远程服务器发送请求时利用它。



6. 并行

尽量让你所有的阻塞式操作(比如,对远程服务的请求,数据库调用,和文件系统访问)并发进行。这样会把总延迟减少为最慢的哪个阻塞式操作的时间,而不是每个操作顺序进行的延迟总和。为了保持回调函数和错误处理整洁清楚,我们使用了Step来进行流程控制。



7. 避免使用session

LinkedIn mobile使用Express框架来管理请求/响应循环。

app.use(express.session({ secret: "keyboard cat" }));


缺省情况下,session数据是保存在内存里的,这样会给服务器增加相当大的开销,特别是在用户数增长的情况下。你可以改用外部session存储,例如MongoDB或Redis,可是这样每个请求又增加了获取session数据的远程调用的开销。在可能的情况下,最好的办法是根本就不在服务器端保存状态信息。通过去掉Express里类似于 “app.use(express.session()); ” 的配置,实现无session后,你会看到更好的性能。(【译者注】原文缺了具体配置,这条是译者自己琢磨着加的)

8. 使用已编译的模块

尽可能使用已编译的模块而不是JavaScript模块。例如,当我们把SHA模块从一个用JavaScript写的版本转到一个包含在Node.js里的已编译版本,我们看到了一个巨大的性能飞跃。

// Use built in or binary modules
var crypto = require('crypto');
var hash = crypto.createHmac("sha1",key).update(signatureBase).digest("base64");


9. 使用标准V8 JavaScript而不是客户端的库

大部分JavaScript库是做出来用在web浏览器上的。而在浏览器上JavaScript环境真是千差万别:例如,某个浏览器可能支持类似于forEach, map/reduce这样的功能,而其他浏览器却不支持。结果,客户端的库通常包含了很多低效率的代码来克服浏览器带来的差别。另一方面,在Node.js里,你能明确知道有哪些JavaScript函数,因为支撑Node.js的V8 JavaScript引擎是按第5版 ECMA-262 标准描述的ECMAScript标准实现的。通过直接使用标准的V8函数而不是客户端库里的东西,你可以看到相当大的性能改进。

10. 保持你的代码小规模、轻量级

在设备慢、延迟高的移动客户端环境下工作,你会学着保持代码的小规模和轻量级。把这个思路也带到你服务器端的代码中去。经常重新思考你的决定,问自己一些问题,例如:“我们真的需要这个模块吗?”,“我们为啥要用这个框架?与其产生的开销相比它是否值得用?”,“我们能不能用更简单的方式来做这件事?”。更小,更轻量的代码总是会更有效率,也会更快。

英文原文:LinkedIn,编译:@老码农的自留地
译文链接:http://blog.jobbole.com/40135/
  • 大小: 9.6 KB
来自: 伯乐在线
3
0
评论 共 5 条 请登录后发表评论
5 楼 wangguo 2013-05-28 09:39
hantsy 写道
原文有大量的代码说明。

并且有配图说明其 Node.js server 和 Backend Servers 之间的交互。

已在文中添加上了
4 楼 hantsy 2013-05-28 07:48
原文有大量的代码说明。

并且有配图说明其 Node.js server 和 Backend Servers 之间的交互。
3 楼 hantsy 2013-05-28 07:41
文不对题,译注完全是误导读者。

原文是针对 Linkedin Mobile。。。http://engineering.linkedin.com/nodejs/blazing-fast-nodejs-10-performance-tips-linkedin-mobile

我个人记得 Linkedin 网站的技术架构是从 Rails 转换到 Java(Spring,Scala 等)。
2 楼 clxy 2013-05-27 18:01
引用
避免使用session

怎么做到的呢?
1 楼 elgs 2013-05-27 16:10
Good article!

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • 列传行sql

    1 select u.userid , (select jueseid from view_user_juese v1 where v1.userid=u.userid and jueseid=1) as jbr, (select jueseid from view_user_juese v1 where v1.userid=u.userid and jueseid=2) as fhr,

  • 理解结构体

    /成员名};//这样使用是没有意义的,因为struct student是结构类型,这个地方缺少一个变量//成员名//这里的struct student和stu都是结构类型,这里的stu就不属于结构变量了,也就是说需要定义结构变量stu stt;//定义结构变量,结构变量为stt//和上面的定义效果一样}

  • javascript基础

    复习 输出语句 document.write(arg); 在页面输出 arg(参数,可以是: 直接量 1 “abc” a 2+1 5&gt;3 ) 变量 定义 程序在执行的过程中值可以被改变的量,一个变量在同一时刻只能保存一个值,它是保存数据信息的空间. 数学: m = 5 n = 6 m+n=? 程序 m = 5 把m称作变量 使用一个变量我们需要声明 并且赋值后才可以使用. var a = 6 ; 声明了一个变量并且给它赋值为6,第一次赋值被称为初始化. 数据类型 文本 – 字符串,需

  • Java中8.1 / 3 = 2.7?

    8.1 / 3 !=2.7, 而是一个无线逼近2.7的值,idea运行结果为:2.6999999999999997

  • @Value设置默认值以及为static变量赋值

    @Value设置默认值以及为static变量赋值

  • python3 华为机考

    描述计算字符串最后一个单词的长度,单词以空格隔开,字符串长度小于5000。(注字符串末尾不以空格为结尾)输入描述输入一行,代表要计算的字符串,非空,长度小于5000。输出描述输出一个整数,表示输入字符串最后一个单词的长度。示例1输入输出8说明最后一个单词为nowcoder,长度为8代码。...............

  • 《华为机试》刷题之HJ76 尼科彻斯定理

    一、题目 二、示例 三、代码 while True: try: m = int(input()) result = [str(i) for i in range(m*(m-1)+1,m*(m+1)) if i%2 !=0] print('+'.join(result)) except: break 四、算法说明 整数m的立方等于m × (m - 1) + 1和m × (m + 1)之间的奇数相加。 胡萝卜 2022年3月

  • 华为机试题:HJ76 尼科彻斯定理(python)

    (1) 举例说明:若list中包含数字,则不能直接转化成字符串,否则系统报错。输入一个正整数m(m≤100),将m的立方写成m个连续奇数之和的形式输出。(2)举例说明:若list中包含数字,将list中的所有元素转换为字符串。(1)65036 除 16,商4064,余数 12(十六进制C)(2)4064 除 16,商254,余数 0(十六进制0)(3)254 除 16,商15,余数 14(十六进制E)备注:前闭后开[A,B),即可以取到A值,但取不到B值。(4)15除16,商0,余数 15(十六进制F)。

  • 昆仑通态TPC7022Nt物联网屏试用

    **1. 目标:PC远程监控画面。**测试结果可远程监控画面 a. 安装MCGS调试助手。 双击“MCGS调试助手_V1.5”文件,按顺序安装 b. 安装后打开MCGS调试助手。 保证触摸屏与PC在同一局域网内(设置为200.200.200.110),进入MCGS调试助手登录界面,选择“本地调试”,输入触摸屏在局域网内的IP地址(200.200.200.190),点击“连接”。可以看大可连接设备列表; 连接成功后,可对连接的触摸屏进行VNC浏览 c. 联机设备。根据设备名称或设备ID,选中设备,点击 “联机

  • Chu-Ren Huang 黃 居 仁(computational linguistics)

    http://cwn.ling.sinica.edu.tw/huang/huang.htmAffiliation / 現職中央研究院語言學研究所 研究員Research Fellow, Institute of Linguistics, Academia Sinica.   計算語言學與中文語言處理國際研究生學程 召集人 Director, CLCL

  • 大规模特征向量检索算法总结 (LSH PQ HNSW)

    大规模特征向量检索算法总结 (LSH PQ HNSW) 向量检索基本概念 向量从表现形式上就是一个一维数组。我们需要解决的问题是使用下面的公式度量距离寻找最相似的 K 个向量。 欧式距离: 两点间的真实距离,值越小,说明距离越近; 余弦距离:就是两个向量围成夹角的 cosine 值,cosine 值越大,越相似; 汉明距离:一般作用于二值化向量,二值化的意思是向量的每一列只有 0 或者 1 两种取值。 汉明距离的值就两个向量每列数值的异或和,值越小说明越相似,一般用于图片识别; 杰卡.

  • NLP | 自然语言处理 - 语法解析(Parsing, and Context-Free Grammars)

    在自然语言学习过程中,每个人一定都学过语法,例如句子可以用主语、谓语、宾语来表示。在自然语言的处理过程中,有许多应用场景都需要考虑句子的语法,因此研究语法解析变得非常重要。语法解析有两个主要的问题,其一是句子语法在计算机中的表达与存储方法,以及语料数据集;其二是语法解析的算法。这也是本章将要讨论的内容。

  • 自然语言处理(十一)——产生式模型和判别式模型

    前言 产生式模型和判别式模型的区别,下面会用一个天气判断的案例来解释。首先我们需要了解一下什么是分类器,用数学的符号来描述分类器就是:输入x以及分类变量y,求p(y | x)。例如,x是云量、气温、湿度。y是天气状况(下雨?不下雨?)。分类器的作用就是分析云量等这些指标,来得出下雨或者不下雨的概率。 一、两种模型的思想 到底怎么计算下雨的概率,产生式模型和判别式模型有不同的计算思想。产生式模...

  • 关于自然语言处理(NLP)的个人学习资料

    个人研究的各种乱七八糟无聊资料~: 深入看过的论文: 链接:https://pan.baidu.com/s/19mlS8eSY8vbzr96FPYfOvw 提取码:vy3o   期待深入看的论文 链接:https://pan.baidu.com/s/1-OT3c-xdKvxQGe_n8pMT7A 提取码:kc1n   BERT官方demo数据: 链接:https://pan.b...

  • 深度学习(Deep Learning),自然语言处理(NLP)及其表达(Representation)

    深度学习(Deep Learning),自然语言处理(NLP)及其表达(Representation)简介过去几年中,深度神经网络在模式识别领域占据着统治地位。他们在诸多计算机视觉任务领域,将之前的最好算法彻底击败。语言识别也正朝着这个方向发展。 They blew the previous state of the art out of the water for many computer

  • 百度自然语言接口调用

    百度自然语言接口调用 一、应用创建 百度自然语言提供词法分析:提供分词、词性标注、命名实体识别三大功能,等一系列其他功能; 下面记录一下百度自然语言接口调用: 1.首先需要登陆自己百度云账号进入百度云管理中心 2.由于百度自然语言调用根据自己需求创建一个应用,根据此应用的key来调用接口 点击创建应用,进入应用创建界面,填写必选项选择需要调用的服务,我这里用到了分词因此选择自然语言处理的默认接口...

  • 自然语言处理基础技术之组合范畴文法

    声明:转载请注明出处,谢谢:https://blog.csdn.net/m0_37306360/article/details/84712213 另外,更多实时更新的个人学习笔记分享,请关注: 知乎:https://www.zhihu.com/people/yuquanle/columns 公众号:StudyForAI 之前在读论文的时候看到CCG这个概念,所以之查阅学习了一波~~ 定义: ...

  • 自然语言处理(NLP)入门指南资料

    作者:Melanie Tosik  翻译:闵黎  校对:丁楠雅 Melanie Tosik目前就职于旅游搜索公司WayBlazer,她的工作内容是通过自然语言请求来生产个性化旅游推荐路线。回顾她的学习历程,她为期望入门自然语言处理的初学者列出了一份学习资源清单。 displaCy网站上的可视化依赖解析树 https://demos.explosion.ai/d

Global site tag (gtag.js) - Google Analytics