xml地图|网站地图|网站标签 [设为首页] [加入收藏]

美高梅游戏网站

当前位置:美高梅游戏网站 > 美高梅游戏网站 > Node.js初体验(1)

Node.js初体验(1)

来源:http://www.gd-chuangmei.com 作者:美高梅游戏网站 时间:2019-09-03 22:14

最近写的文章收到许多朋友的反馈,感谢大家的支持和建议,让我对坚持写博客充满热情,一个月一篇文章确实有点少,所以以后尽力多做分享,做好的分享,希望能对朋友们有用。

服务器端 JS 情缘
在校期间我学会了JavaScript和Java,当时我就在考虑JS有没有类似JSP一样的服务器端程序,名字应该是JSSP(JavaScript Server Page),可以在 HTML 中嵌入 JS。Google了一圈发现IIS支持用JScript代替VBScript做ASP开发,另外SourceForge上真有个叫JSSP的项目,以及今天的主角Node.js。当时的Node.js刚起步,首页背景还是黑乎乎的(不晓得其他童鞋是否也有印象)。经过一圈比较,我最终选择使用Rhino——一个纯Java实现的JS引擎,它吸引我的地方是能直接调用Java类库。
Node.js
最近关注Node.js人变多了。在长期与一堆厚重的Java框架、类库为伍之后,我也想看看外面的世界。Node.js最为人所津津乐道的就是异步加回调机制以及良好的性能。我想知道它和我熟悉的Java有何不同。
Node.js 要解决的问题
在使用Java开发的过程里,经常会有与下面类似的代码:
[java] 
// block A 
// do something 
 
// block B 
// on Database 
ResultSet rs = dbo.executeQuery("Query Statement"); 
 
while (rs.next()) { 
    // block C 
    // parse the result 

 
// block D 
// do something  
代码块A先处理一些任务;代码块B发送查询语句到数据库,等待返回数据集;代码块C处理返回结果;代码块D继续做其他事情。执行时序图如下:

到新公司的这段时间学到了很多新东西,有好多东西需要去总结去探索,不过事情得一件一件来,今天咱们先从Node开始。注:以后出现的Node即node.js。

容易看出,在等待代码块B时,整个程序都暂停了,中间有一大段空闲时间没有处理任何任务。从依赖关系上说,代码块C必须在代码块B成功执行后才能执行;但代码块D对前面的B、C并没有依赖关系。因此,如果在等待期间先执行代码块D,直到代码块B执行完毕再触发代码块C。如下图所示:

先搞点前戏热热场 - 为什么写这篇文章:

假设每个代码块所需的执行时间是5秒,那第一种方案需要20秒,而第二种只需要15秒。Node.js要做的事情就是使用第二种方案取代第一种方案以获得性能的提升。
回调函数队列
情理之中意料之外,Node.js实现的方式是单进程且单线程。它内部维护着一个回调函数队列,遵循先到先处理的原则逐个执行。让我联想到[[] ,任务一个接一个地执行,没有抢占并享有所有系统资源。Node.js回调机制所做的事情就是把相应的代码块塞到队尾。
比如上一节的例子中的方法二,执行过程就变成:代码块A被塞到队列中;数据库查询语句注册了一个事件并绑定代码块C为回调函数;代码块D被塞到队尾;此时代码块B执行完成并触发事件,把代码块C塞到队尾。因此,依次执行的是A、D、C(注:B是数据库服务器上的查询操作,并不是Node.js中执行的代码),期间并无间歇。
考虑下面的代码,就遵循上述的代码模式:
代码块A:请求计数以及记录请求开始处理的时间(不是到达时间)。
代码块B:此处用setTimeout做了5秒延迟,模拟外部程序处理五秒钟。
代码块C:记录回调函数被调用的时间,睡5秒来模拟服务器运算,并记录结束时间。
代码块D:记录响应的时间(即用户收到回馈的时间)。
[javascript] 
var http = require('http'); 
var count = 0; 
 
http.createServer(function(request, response) { 
    // block A 
    count++; 
    var id = count; 
 
    var start = new Date(); 
    var reply; 
 
    // block B 
    setTimeout(function() { 
        // block C 
        var called = new Date(); 
        var end; 
 
        do { 
            end = new Date(); 
        } while (end.getTime() - called.getTime() < 5000); 
 
        console.log(id + ' start @ ' + start); 
        console.log(id + ' reply @ ' + reply); 
        console.log(id + ' called @ ' + called); 
        console.log(id + ' end @ ' + end); 
    }, 5000); 
 
    // block D 
    response.writeHead(200, {'Content-Type': 'text/html'}); 
    response.end(); 
    reply = new Date(); 
}).listen(80); 
在我的机器上执行结果如下:
[plain]
λ sudo node main.js  
1 start @ Fri Sep 21 2012 19:12:35 GMT+0800 (CST) 
1 reply @ Fri Sep 21 2012 19:12:35 GMT+0800 (CST) 
1 called @ Fri Sep 21 2012 19:12:40 GMT+0800 (CST) 
1 end @ Fri Sep 21 2012 19:12:45 GMT+0800 (CST) 
和预期的一样:请求在19:12:35时开始处理,并且没有被阻塞,而是在同一时间就返回了;5秒后回调函数开始被处理;又过了5秒回调函数执行完毕,整个过程结束。
我们来数数上面这段代码总共有几个显眼的回调函数:
整段代码/文件是一个回调函数,在程序启动时被塞到队列中并立即执行了;
createServer 中注册的回调函数,在收到用户请求后被触发(塞到队列,不一定马上执行);
setTimeout 中注册的回调函数,在延迟5后才被塞到队列。
单线程的问题
Node.js采用单进程+单线程的其中一个原因是避免系统频繁开辟线程带来的开销。网络上说开启一个线程要使用2M的内存(有这么多?),我没去验证过具体数值,但至少是有一些开销的,当请求量大是的确会成为瓶颈。上节提到Node.js的处理任务的方式类似批处理操作系统,因此它在规避线程开销的同时也完全继承了批处理方式的缺陷——交互不友好。我指的交互是后面的请求会被回调函数队列中前面的任务阻塞住,从接受到回馈耗费很长的时间等待。
用下面代码分别在第0秒、第1秒、第7秒发送一个请求,并记录每个请求从发出到收到回馈的时间:
[plain] 
#!/bin/bash 
 
date 
time curl  
sleep 1 
date 
time curl  
sleep 6 
date 
time curl  
date 
执行结果如下:
19:16:36 发送第一个请求,几乎马上收到回馈;
等待1秒后发送第二个请求,同样马上收到回馈;
继续等待6秒发送第三个请求,耗时8秒后猜收到回馈!
[plain]
$ ./submit.sh  
2012年 09月 21日 星期五 19:16:36 CST 
 
real    0m0.018s 
user    0m0.004s 
sys     0m0.008s 
2012年 09月 21日 星期五 19:16:37 CST 
 
real    0m0.015s 
user    0m0.012s 
sys     0m0.000s 
2012年 09月 21日 星期五 19:16:43 CST 
 
real    0m7.982s 
user    0m0.000s 
sys     0m0.004s 
2012年 09月 21日 星期五 19:16:51 CST 
相信第三次请求的用户会极其不满,来看看Node.js执行时的快照:
[plain] 
1 start @ Fri Sep 21 2012 19:16:36 GMT+0800 (CST) 
1 reply @ Fri Sep 21 2012 19:16:36 GMT+0800 (CST) 
1 called @ Fri Sep 21 2012 19:16:41 GMT+0800 (CST) 
1 end @ Fri Sep 21 2012 19:16:46 GMT+0800 (CST) 
2 start @ Fri Sep 21 2012 19:16:37 GMT+0800 (CST) 
2 reply @ Fri Sep 21 2012 19:16:37 GMT+0800 (CST) 
2 called @ Fri Sep 21 2012 19:16:46 GMT+0800 (CST) 
2 end @ Fri Sep 21 2012 19:16:51 GMT+0800 (CST) 
3 start @ Fri Sep 21 2012 19:16:51 GMT+0800 (CST) 
3 reply @ Fri Sep 21 2012 19:16:51 GMT+0800 (CST) 
3 called @ Fri Sep 21 2012 19:16:56 GMT+0800 (CST) 
3 end @ Fri Sep 21 2012 19:17:01 GMT+0800 (CST) 
下表中A1表示第一次请求中的代码块A,其他以此类推。假定代码块A、B、D都是瞬间完成,只有C耗时5秒。从表中可知,第三次请求是在第15钟才开始被处理。根据测试脚本的输出可知,第三次请求其实在第7秒就已经发出了,但由于是那时队列中还有C1、C2在处理,因此等待了8秒钟!假设队列的平均长度是100,那每个请求平均的等待时间就是 (100 / 4 - 1) * (A+B+C+D),即要等前面24个请求处理完。这还仅仅是请求得到回馈的时间,该请求对应回调函数被执行的时间还要更久。
当前时间 当前队列
0 A1 B1 D1
1 A2 B2 D1
5 C1
6 C1 C2
7 C1 C2 A3 B3 D3
10 C2 A3 B3 D3
15 A3 B3 D3
20 C3
25 
适用场景
通过上面的研究,我觉得Node.js并不适合需要与用户实时交互的系统;它适合集中处理用户发来的大规模“指令”,即不需要及时看到结果的请求。比如微博系统,用户发表一条微博,可能需要在服务器上排队1分钟才能最终保存到数据库。在这一分钟里,用户更多地是看看别人发表的微博,并不十分迫切地想看到自己那条微博。如果希望有更好的体验,其实可以用DOM直接把用户发表的微博先更新到当前页面,同时使用Ajax异步请求保存这条数据。

1.前段时间单位有新项目启动,服务端要做的工作不多也不算麻烦,就是处理一些中间层的服务,而且我们团队里面个个都会JavaScript,领导就决定试试服务器端的JavaScript,结果本人有幸被派去研究了几天Node,怀着鸡冻的心情开始了node.js的篇章,这篇文章也就是为这几天研究的总结。

JS 情缘 在校期间我学会了JavaScript和Java,当时我就在考虑JS有没有类似JSP一样的服务器端程序,名字应该是JSSP(JavaScript Server Pa...

2.一个JavaScript工程师如果没听过node.js那么我想你是不是错过了什么,每个优秀的前端工程师都有必要去了解后台处理流程,那么如果又能从JavaScript出发,岂不是一件很美妙的事么。

3.互联网的火热使得JavaScript风光无限,且服务端的JavaScript也并不是什么新技术了,相关的框架也有不少,只是node.js的成功让他爆发式的出现在我们的视线中,让很多前端工程师看到了从前端写到后端的另一种实现希望。注:node.js 是一个允许开发人员使用 JavaScript 语言编写服务器端代码的框架。

4.今年8月曾在某大公司最后一轮(第五轮)的面试被问到Node.js的问题,相对应的回答那是相当之糟糕,结果怎样你们懂的,感觉这个问题是导致没有通过的关键点之一...那家公司是我在读大学的时候就无比向往的公司,现在回想起那次经历和过程,谈不上惋惜,毕竟我真的尽力了

  • 其实这篇文章更多的也是为了完成自己一个小小的心结...好吧,又扯远了。

5.欢迎各种转载,不过请注明出处,谢谢。

Node是个啥?

写个东西还是尽量面面俱到吧,所以有关基本概念的东西我也从网上选择性的拿了些下来,有些地方针对自己的理解有所改动,对这些概念性的东西有过了解的可选择跳过这段。

1.Node 是一个服务器端JavaScript 解释器,可是真的以为JavaScript不错的同学学习Node就能轻松拿下,那么你就错了,总结:水深不深我还不知道,不过确实不浅。

2.Node 的目标是帮助程序员构建高度可伸缩的应用程序,编写能够处理数万条同时连接到一个物理机的连接代码。处理高并发和异步I/O是Node受到开发人员的关注的原因之一。

3.Node 本身运行Google V8 JavaScript引擎,所以速度和性能非常好,看chrome就知道,而且Node对其封装的同时还改进了其处理二进制数据的能力。因此,Node不仅仅简单的使用了V8,还对其进行了优化,使其在各种环境下更加给力。(什么是V8 JavaScript 引擎?请“百度知道”)

4.第三方的扩展和模块在Node的使用中起到重要的作用。下面也会介绍下载npm,npm就是模块的管理工具,用它安装各种 Node 的软件包(如express,redis等)并发布自己为Node写的软件包 。

安装Node

在这简单说说在window7和linux两种环境下安装Node。安装的时候一定要注意Python的版本,多次因为Python版本的问题安装失败,建议2.6+的版本,低版本会出现Node安装错误,查询Python版本可在终端中输入:pyhton -v

1.先介绍linux下的安装吧,Node在Linux环境下的安装和使用都非常方便,建议在Linux下运行Node,^_^...我使用的是Ubuntu11.04

a.安装依赖包:50-100kb/s大概每个包一分钟就能下载安装完成

 sudo apt-get install g++ curl libssl-dev apache2-utils    sudo apt-get install git-core 

b.在终端一步步运行一下命令:

git clone git://github.com/joyent/node.git     cd node  ./configure  make     sudo make install 

安装顺利的话到这一步Node就算安装成功了,2M的网络用了共计12分钟。

注:如果不用git下载也可以直接下载源码,不过这样下载安装需要注意Node版本问题。使用git下载安装是最方便的,所以推荐之。

2.在Windows下使用Cygwin安装Node,这个方式不太推荐,因为真的需要较长时间和较好的人品。我的系统是 win7旗舰版

Cygwin是一个在windows平台上运行的unix模拟环境,下载地址:

下载好Cygwin后开始安装,步骤:

a.选择下载的来源 - Install from Internet

b.选择下载安装的根目录

c.选择下载文件所存放的目录

d.选择连接的方式

本文由美高梅游戏网站发布于美高梅游戏网站,转载请注明出处:Node.js初体验(1)

关键词:

上一篇:Node.js + MongoDB 后端学习笔记

下一篇:没有了