概述

Node.js是什么

Node 是一个服务器端 JavaScript 解释器,用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞I/O 模型而得以轻量和高效,非常适合在分布式设备上运行数据密集型的实时应用。 
Node.js 是一个可以让 JavaScript 运行在浏览器之外的平台。它实现了诸如文件系统、模块、包、操作系统 API、网络通信等 Core JavaScript 没有或者不完善的功能。历史上将 JavaScript移植到浏览器外的计划不止一个,但Node.js 是最出色的一个。

什么是v8引擎

V8 JavaScript 引擎是 Google 用于其 Chrome 浏览器的底层 JavaScript 引擎。很少有人考虑 JavaScript 在客户机上实际做了些什么?实际上,JavaScript 引擎负责解释并执行代码。Google 使用 V8 创建了一个用 C++ 编写的超快解释器,该解释器拥有另一个独特特征;您可以下载该引擎并将其嵌入任何 应用程序。V8 JavaScript 引擎并不仅限于在一个浏览器中运行。因此,Node 实际上会使用 Google 编写的 V8 JavaScript 引擎,并将其重建为可在服务器上使用。

Node.js的作用

Node 公开宣称的目标是 “旨在提供一种简单的构建可伸缩网络程序的方法”。我们来看一个简单的例子,在 Java™ 和 PHP 这类语言中,每个连接都会生成一个新线程,每个新线程可能需要 2 MB 的配套内存。在一个拥有 8 GB RAM 的系统上,理论上最大的并发连接数量是 4,000 个用户。随着您的客户群的增长,如果希望您的 Web 应用程序支持更多用户,那么,您必须添加更多服务器。所以在传统的后台开发中,整个 Web 应用程序架构(包括流量、处理器速度和内存速度)中的瓶颈是:服务器能够处理的并发连接的最大数量。这个不同的架构承载的并发数量是不一致的。 
而Node的出现就是为了解决这个问题:更改连接到服务器的方式。在Node 声称它不允许使用锁,它不会直接阻塞 I/O 调用。Node在每个连接发射一个在 Node 引擎的进程中运行的事件,而不是为每个连接生成一个新的 OS 线程(并为其分配一些配套内存)。

Node.js能做什么

借用一句经典的描述Node.js的话:正如 JavaScript 为客户端而生,Node.js 为网络而生。 
使用Node.js,你可以轻易的实现:

  • 具有复杂逻辑的网站;
  • 基于社交网络的大规模 Web 应用;
  • Web Socket 服务器;
  • TCP/UDP 套接字应用程序;
  • 命令行工具;
  • 交互式终端程序;
  • 带有图形用户界面的本地应用程序;
  • 单元测试工具;
  • 客户端 JavaScript 编译器。

什么是事件驱动编程

在我们使用Java,PHP等语言实现编程的时候,我们面向对象编程是完美的编程设计,这使得他们对其他编程方法不屑一顾。却不知大名鼎鼎Node使用的却是事件驱动编程的思想。那什么是事件驱动编程。 
事件驱动编程,为需要处理的事件编写相应的事件处理程序。代码在事件发生时执行。 
为需要处理的事件编写相应的事件处理程序。要理解事件驱动和程序,就需要与非事件驱动的程序进行比较。实际上,现代的程序大多是事件驱动的,比如多线程的程序,肯定是事件驱动的。早期则存在许多非事件驱动的程序,这样的程序,在需要等待某个条件触发时,会不断地检查这个条件,直到条件满足,这是很浪费cpu时间的。而事件驱动的程序,则有机会释放cpu从而进入睡眠态(注意是有机会,当然程序也可自行决定不释放cpu),当事件触发时被操作系统唤醒,这样就能更加有效地使用cpu。 
来看一张简单的事件驱动模型(uml):

事件驱动模型主要包含3个对象:事件源、事件和事件处理程序。

  • 事件源:产生事件的地方(html元素)
  • 事件:点击/鼠标操作/键盘操作等等
  • 事件对象:当某个事件发生时,可能会产生一个事件对象,该时间对象会封装好该时间的信息,传递给事件处理程序
  • 事件处理程序:响应用户事件的代码 
    其实我们使用的window系统也算得上是事件驱动了。我们来看一个简单的事例:监听鼠标点击事件,并能够显示鼠标点击的位置x,y。
    1. <html>
    2. <head>
    3. <script>
    4. function test1(e){
    5. window.alert("x="+e.clientX+"y="+e.clientY);
    6. }
    7. </script>
    8. </head>
    9. <body onmousedown="test1(event)">
    10. </body>
    11. </html>

Node.js运行原理分析

当我们搜索Node.js时,夺眶而出的关键字就是 “单线程,异步I/O,事件驱动”,应用程序的请求过程可以分为俩个部分:CPU运算和I/O读写,CPU计算速度通常远高于磁盘读写速度,这就导致CPU运算已经完成,但是不得不等待磁盘I/O任务完成之后再继续接下来的业务。 
所以I/O才是应用程序的瓶颈所在,在I/O密集型业务中,假设请求需要100ms来完成,其中99ms化在I/O上。如果需要优化应用程序,让他能同时处理更多的请求,我们会采用多线程,同时开启100个、1000个线程来提高我们请求处理,当然这也是一种可观的方案。 
但是由于一个CPU核心在一个时刻只能做一件事情,操作系统只能通过将CPU切分为时间片的方法,让线程可以较为均匀的使用CPU资源。但操作系统在内核切换线程的同时也要切换线程的上线文,当线程数量过多时,时间将会被消耗在上下文切换中。所以在大并发时,多线程结构还是无法做到强大的伸缩性。 
那么是否可以另辟蹊径呢?!我们先来看看单线程,《深入浅出Node》一书提到 “单线程的最大好处,是不用像多线程编程那样处处在意状态的同步问题,这里没有死锁的存在,也没有线程上下文切换所带来的性能上的开销”,那么一个线程一次只能处理一个请求岂不是无稽之谈,先让我们看张图: 
 
Node.js的单线程并不是真正的单线程,只是开启了单个线程进行业务处理(cpu的运算),同时开启了其他线程专门处理I/O。当一个指令到达主线程,主线程发现有I/O之后,直接把这个事件传给I/O线程,不会等待I/O结束后,再去处理下面的业务,而是拿到一个状态后立即往下走,这就是“单线程”、“异步I/O”。 
I/O操作完之后呢?Node.js的I/O 处理完之后会有一个回调事件,这个事件会放在一个事件处理队列里头,在进程启动时node会创建一个类似于While(true)的循环,它的每一次轮询都会去查看是否有事件需要处理,是否有事件关联的回调函数需要处理,如果有就处理,然后加入下一个轮询,如果没有就退出进程,这就是所谓的“事件驱动”。这也从Node的角度解释了什么是”事件驱动”。 
在node.js中,事件主要来源于网络请求,文件I/O等,根据事件的不同对观察者进行了分类,有文件I/O观察者,网络I/O观察者。事件驱动是一个典型的生产者/消费者模型,请求到达观察者那里,事件循环从观察者进行消费,主线程就可以马不停蹄的只关注业务不用再去进行I/O等待。

Node.js的简单实践

关于node的环境搭建这里就不说明了node入门。这里为了方便大家理解,我们写一个简单的登录实例。 
这里为了方便前端小白的理解,新增一个小节,如何使用Node搭建一个新的项目。 
## 使用Node创建项目 
安装Express

  1. npm install -g express
  2. npm install -g express-generator

新建项目

  1. express -t ejs newsproject

按照提示进入项目目录,运行npm安装

  1. cd newsprojec
  2. npm install

运行项目

  1. node app.js

浏览器访问:http://127.0.0.1:3000/即可见nodejs站点页面即可。 
接下来我们写一个简单的例子,来看一下效果图: 
 
整个目录如下:

  1. 根目录--------------
  2. |-package.json
  3. |-test.js
  4. |-public
  5. |-main.html
  6. |-next.html

整个目录包含三个文件,test.js(作为控制文件)、main.html和next.html作为页面的显示文件。 
来看一下代码: 
test.js(作为控制文件)

  1. // file name :test.js
  2. var express = require('express');
  3. var app = express();
  4. var bodyParse = require('body-parser')
  5. var cookieParser = require('cookie-parser') ;
  6. app.use(cookieParser()) ;
  7. app.use(bodyParse.urlencoded({extended:false})) ;
  8.  
  9. // 处理根目录的get请求
  10. app.get('/',function(req,res){
  11. res.sendfile('public/main.html') ;
  12. console.log('main page is required ');
  13. }) ;
  14.  
  15. // 处理/login的get请求
  16. app.get('/add', function (req,res) {
  17. res.sendfile('public/add.html') ;
  18. console.log('add page is required ') ;
  19. }) ;
  20.  
  21. // 处理/login的post请求
  22. app.post('/login',function(req,res){
  23. name=req.body.name ;
  24. pwd=req.body.pwd ;
  25. console.log(name+'--'+pwd) ;
  26. res.status(200).send(name+'--'+pwd) ;
  27. });
  28.  
  29. // 监听3000端口
  30. var server=app.listen(3000) ;

main.html的代码

  1. <html>
  2.  
  3. <link rel="stylesheet" type="text/css" href="http://fonts.useso.com/css?family=Tangerine|Inconsolata|Droid+Sans">
  4.  
  5. <style>
  6. div#test{
  7. font-family: 'Tangerine',serif;
  8. font-size: 48px;
  9. }
  10. p#link1{
  11. font-family: 'Tangerine',serif;
  12. }
  13.  
  14. </style>
  15.  
  16. <script src="//cdn.bootcss.com/jquery/2.2.1/jquery.min.js"></script>
  17.  
  18. </head>
  19. <body>
  20.  
  21. <div id="test">
  22. <h1>Main Page</h1>
  23. </div>
  24. <p>Register & Login</p>
  25. <form action="test.jsp" method="post">
  26. 账号 :
  27. <input type="text" id="name" />
  28. <br/><br/>
  29. 密码 :
  30. <input type="text" id="pwd" />
  31. <br/><br/>
  32. &nbsp&nbsp&nbsp&nbsp&nbsp
  33. <div><a href="/add" id="add">EXTRA</a></div>
  34. <input type="button" value="Submit" id="x">
  35. </form>
  36.  
  37. </body>
  38.  
  39. <script type="text/javascript">
  40.  
  41. var after_login=function(data,status){
  42. if (status=='success'){
  43. alert(data+'--'+status) ;
  44. }
  45. else alert('login refused') ;
  46.  
  47. }
  48.  
  49. $(document).ready(function(){
  50. $("#x").click(function(){
  51. var name = $("#name").val() ;
  52. var pwd = $("#pwd").val() ;
  53. $.post('http://127.0.0.1:3000/login',
  54. {
  55. name : name ,
  56. pwd : pwd
  57. },
  58. // function(data,status){
  59. // alert(data+'--'+status) ;
  60. // }
  61. after_login
  62. );
  63. // $.get('add',function(data,status){
  64. // document.write(data) ;
  65. // }) ;
  66. });
  67. });
  68. </script>
  69. </html>

next.html的代码

  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title>第二页面</title>
  6. </head>
  7. <body>
  8. <h1>This is an additional web page</h1>
  9. <p>just for test</p>
  10. </body>
  11. </html>

  

 

本文摘自:https://blog.csdn.net/xiangzhihong8/article/details/53954600

原创作者:xiangzhihong8

node.js基本工作原理及流程的更多相关文章

  1. Linux可插拔认证模块(PAM)的配置文件、工作原理与流程

    PAM的配置文件: 我们注意到,配置文件也放在了在应用接口层中,他与PAM API配合使用,从而达到了在应用中灵活插入所需鉴别模块的目的.他的作用主要是为应用选定具体的鉴别模块,模块间的组合以及规定模 ...

  2. 深入研究Node.js的底层原理和高级使用

    深入研究Node.js的底层原理和高级使用

  3. Java 详解 JVM 工作原理和流程

    Java 详解 JVM 工作原理和流程 作为一名Java使用者,掌握JVM的体系结构也是必须的.说起Java,人们首先想到的是Java编程语言,然而事实上,Java是一种技术,它由四方面组成:Java ...

  4. FastDFS tracker storage 的工作原理及流程

    FastDFS tracker storage 的工作原理及流程 2013 年 3 月 11 日 – 09:22 | 1,409 views | 收藏  (No Ratings Yet) FastDF ...

  5. ARKit从入门到精通(2)-ARKit工作原理及流程介绍

    转载:http://blog.csdn.net/u013263917/article/details/73038519 1.1-写在前面的话 1.2-ARKit与SceneKit的关系 1.3-ARK ...

  6. 第四次作业 描述HDFS体系结构、工作原理与流程

    1.用自己的图,描述HDFS体系结构.工作原理与流程. 读数据的流程 2.伪分布式安装Hadoop.

  7. Node.js异步IO原理剖析

    为什么要异步I/O? 从用户体验角度讲,异步IO可以消除UI阻塞,快速响应资源 JavaScript是单线程的,它与UI渲染共用一个线程.所以在JavaScript执行的时候,UI渲染将处于停顿的状态 ...

  8. “Ceph浅析”系列之五——Ceph的工作原理及流程

    本文将对Ceph的工作原理和若干关键工作流程进行扼要介绍.如前所述,由于Ceph的功能实现本质上依托于RADOS,因而,此处的介绍事实上也是针对RADOS进行.对于上层的部分,特别是RADOS GW和 ...

  9. SSH三大框架的工作原理及流程

    Hibernate工作原理及为什么要用? 原理:1.通过Configuration().configure();读取并解析hibernate.cfg.xml配置文件2.由hibernate.cfg.x ...

随机推荐

  1. 跟着百度学PHP[17]-PHP扩展CURL的用法详解

    实现的功能: 1.实现远程获取和采集内容2.实现PHP 网页版的FTP上传下载3.实现模拟登陆:去一个邮件系统,curl可以模拟cookies4.实现接口对接(API),数据传输等:通过一个平台发送短 ...

  2. VM下redhat9.0不能上网

    近期本人在学习linux时,安装Red Hat Linux9后,可是上不了网,弄得查资料还得切换到虚拟机上去,特耗时间.还好没有疯掉! 首先,测试下你的linux看是否是这类问题,输入ping www ...

  3. a5调试

    1 generating rsa key...[    4.452000] mmc0: error -110 whilst initialising SD card[    5.602000] mmc ...

  4. Generating SSH Keys on windows

    two ways here I provide: use openSSH command line on git bash(such as msysgit bash) ls -al ~/.ssh ss ...

  5. C#中oracle数据库的连接方法

    C#中oracle数据库的连接方法 一.关于数据库的操作 1.数据库连接      有2种:      第一种:古老的方法(较为死板,不利于灵活操作),即用OracleConnection的类来连接 ...

  6. Jmeter实现对字符串加密

    最近测试移动端接口,但是请求内容是用MD5加密的,所以要先对请求内容进行加密,Jmeter内置的没有MD5加密方法,所以自己从网上copy了一份,实现了加密功能,以下是具体操作: 1.从网上copy了 ...

  7. 日历类Calendar

    在早期的JDK版本中,日期(Date)类附有两大功能:(1)允许用年.月.日.时.分.秒来解释日期:(2)允许对表示日期的字符串进行格式化和句法分析.在JDK1.1中提供了类Calendar来完成第一 ...

  8. ProtocolBuffer在Android端的解析

    开题篇 近期公司在使用Protocol Buffer替代原先的json作为移动端的数据交互格式.虽然服务端和CTO把这项新技术吹的天花乱坠,说什么体积小,不易被破解乱七八糟的.可是作为Android端 ...

  9. (转)SQL执行顺序

    SQL语句理解:http://blog.jobbole.com/55086/ 窗口函数/分析函数:http://blog.csdn.net/mfkpie/article/details/1636451 ...

  10. 【Python】求素数-稍加优化

    print 'Find prime number smaller then input number \n' print 'Please input a number:' import datetim ...