1、单线程

在Java、PHP或者.net等做事器端措辞中,会为每一个客户端连接创建一个新的线程。
而每个线程须要耗费大约2MB内存。
也便是说,理论上,一个8GB内存的做事器可以同时连接的最大用户数为4000个旁边。
要让Web运用程序支持更多的用户,就须要增加做事器的数量,而Web运用程序的硬件本钱当然就上升了。

Node.js不为每个客户连接创建一个新的线程,而仅仅利用一个线程。
当有用户连接了,就触发一个内部事宜,通过非壅塞I/O、事宜驱动机制,让Node.js程序宏不雅观上也是并行的。
利用Node.js,一个8GB内存的做事器,可以同时处理超过4万用户的连接。

jspnet的背景宁波上元教导Nodejs 三年夜特色详解 Angular

其余,单线程带来的好处,操作系统完备不再有线程创建、销毁的韶光开销。

坏处,便是一个用户造成了线程的崩溃,全体做事都崩溃了,其他人也崩溃了。

2、非壅塞I/O

例如,当在访问数据库取得数据的时候,须要一段韶光。
在传统的单线程处理机制中,在实行了访问数据库代码之后,全体线程都将停息下来,等待数据库返回结果,才能实行后面的代码。
也便是说,I/O壅塞了代码的实行,极大地降落了程序的实行效率。

由于Node.js中采取了非壅塞型I/O机制,因此在实行了访问数据库的代码之后,将立即转而实行其后面的代码,把数据库返回结果的处理代码放在回调函数中,从而提高了程序的实行效率。

当某个I/O实行完毕时,将以事宜的形式关照实行I/O操作的线程,线程实行这个事宜的回调函数。
为了处理异步I/O,线程必须有事宜循环,不断的检讨有没有未处理的事宜,依次予以处理。

壅塞模式下,一个线程只能处理一项任务,要想提高吞吐量必须通过多线程。
而非壅塞模式下,一个线程永久在实行打算操作,这个线程的CPU核心利用率永久是100%。
以是,这是一种特殊有哲理的办理方案:与其人多,但是好多人闲着;还不如一个人玩命,往去世里干活儿。

3、事宜驱动 event-driven

在Node中,客户端要求建立连接,提交数据等行为,会触发相应的事宜。
在Node中,在一个时候,只能实行一个事宜回调函数,但是在实行一个事宜回调函数的中途,可以转而处理其他事宜(比如,又有新用户连接了),然后返回连续实行原事宜的回调函数,这种处理机制,称为“事宜环”机制。

Node.js底层是C++(V8也是C++写的)。
底层代码中,近半数都用于事宜行列步队、回调函数行列步队的构建。
用事宜驱动来完成做事器的任务调度,这是鬼能力力想到的。
针尖上的舞蹈,用一个线程,担负起了处理非常多的任务的义务。

单线程,单线程的好处,减少了内存开销,操作系统的内存换页。

如果某一个事情,进入了,但是被I/O壅塞了,以是这个线程就壅塞了。

非壅塞I/O, 不会傻等I/O语句结束,而会实行后面的语句。

非壅塞就能办理问题了么?比如实行着小红的业务,实行过程中,小刚的I/O回调完成了,此时怎么办??

事宜机制,事宜环,不管是新用户的要求,还是老用户的I/O完成,都将以事宜办法加入事宜环,等待调度。

说是三个特点,实际上是一个特点,离开谁都弗成,都玩儿不转了。

Node.js很像抠门的餐厅老板,只聘请1个做事员,做事很多人。
结果,比很多做事员效率还高。

Node.js中所有的I/O都是异步的,回调函数,套回调函数。

Node.js 适宜开拓什么?

Node.js适宜用来开拓什么样的运用程序呢?

长于I/O,不长于打算。
由于Node.js最善于的便是任务调度,如果你的业务有很多的CPU打算,实际上也相称于这个打算壅塞了这个单线程,就不适宜Node开拓。

当运用程序须要处理大量并发的I/O,而在向客户端发出相应之前,运用程序内部并不须要进行非常繁芜的处理的时候,Node.js非常适宜。
Node.js也非常适宜与web socket合营,开拓长连接的实时交互运用程序。

比如:

● 用户表单网络

● 考试系统

● 谈天室

● 图文直播

● 供应JSON的API(为前台Angular利用)

Node.js 与 PHP、JSP的不同

Node.js不是一种独立的措辞,与PHP、JSP、Python、Perl、Ruby的“既是措辞,也是平台”不同,Node.js的利用JavaScript进行编程,运行在JavaScript引擎上(V8)。

与PHP、JSP等比较(PHP、JSP、.net都须要运行在做事器程序上,Apache、Naginx、Tomcat、IIS),Node.js跳过了Apache、Naginx、IIS等HTTP做事器,它自己不用培植在任何做事器软件之上。
Node.js的许多设计理念与经典架构(LAMP = Linux + Apache + MySQL + PHP)有着很大的不同,可以供应强大的伸缩能力。
Node.js没有web容器。

示例一:页面显示\"大众Hello World!\"大众

JS代码:

//require表示引包,引包便是引用自己的一个分外功能var http = require('http');//创建做事器,参数便是一个回调函数,表示如果有要求进来,要做什么var server = http.createServer(function(req, res){ //req表示要求, request;res表示相应,response //设置HTTP头部,状态码是200, 文件类型是html。
字符编码格式是 UTF-8 res.writeHead(200, {'Content-Type':'text/html; charset= UTF-8; '}); res.end('Hello World!');});//运行做事器,监听8083端口server.listen(8083, '127.0.0.1');

打开浏览器,输入 127.0.0.1:8083

示例二:Node.js没有Web容器

在利用Apache做事器时,我们常常可以看到在 htdocs目录中有各种子文件夹,我们要访问指定页面,只须要在浏览器地址栏中输入 127.0.0.1:80/app/index.html 类似这样的构造

但是,Node.js 由于没有Web容器,以是在url 地址后面在输入 /xx.xx 时并不能正常显示

有这么一个文件目录构造:

fang.html 里面是一个 赤色的、正方形的div,yuan.html 里面是一个 绿色的、圆形的div

现在新建一个 noWebContainer.js,看能否在url中输入 fang.html 打开页面

//require表示引包,引包便是引用自己的一个分外功能var http = require('http');var fs = require('fs');//创建做事器,参数是一个回调函数,表示如果有要求进来,要做什么var server = http.createServer(function(req, res){ res.writeHead(200,{\"大众Content-type\"大众:\公众text/html;charset=UTF-8\"大众}); res.end(\公众Hello World!\"大众); });//运行做事器,监听4000端口(端口号可以任改)server.listen(4000,\"大众127.0.0.1\公众);

运行 127.0.0.1:4000,并在url后面加上 /fang.html,创造完备没用

现在初步对“Node.js没有web容器”这句话有了一点印象了,那想要打开fang.html,怎么办呢?

//require表示引包,引包便是引用自己的一个分外功能var http = require('http');var fs = require('fs');//创建做事器,参数是一个回调函数,表示如果有要求进来,要做什么var server = http.createServer(function(req, res){ if(req.url=='/fang'){ fs.readFile('./fang.html', function(err,data){ //req表示要求,request; res表示相应,response //设置HTTP头部,状态码是200,文件类型是html,字符集是utf8 res.writeHead(200, {'Content-type':'text/html;charset=UTF-8'}); res.end(data); }) }else{ res.writeHead(200,{\公众Content-type\"大众:\"大众text/html;charset=UTF-8\"大众}); res.end(\"大众Hello World!\"大众); }});//运行做事器,监听4000端口(端口号可以任改)server.listen(4000,\公众127.0.0.1\公众);

也便是说,如果 要求的url 里面包含了 /fang,就读取当前目录下(./ ---> 表示当前目录)的 fang.html,否则,就只显示 Hello World

同理,我也可以 输入 /yuan,显示 yuan.html

//require表示引包,引包便是引用自己的一个分外功能var http = require('http');var fs = require('fs');//创建做事器,参数是一个回调函数,表示如果有要求进来,要做什么var server = http.createServer(function(req, res){ if(req.url=='/fang'){ fs.readFile('./fang.html', function(err,data){ //req表示要求,request; res表示相应,response //设置HTTP头部,状态码是200,文件类型是html,字符集是utf8 res.writeHead(200, {'Content-type':'text/html;charset=UTF-8'}); res.end(data); }) }else if(req.url=='/yuan'){ fs.readFile('./yuan.html', function(err,data){ res.writeHead(200, {'Content-type':'text/html;charset=UTF-8'}); res.end(data); }) }else{ res.writeHead(200,{\"大众Content-type\公众:\公众text/html;charset=UTF-8\"大众}); res.end(\"大众Hello World!\"大众); }});//运行做事器,监听4000端口(端口号可以任改)server.listen(4000,\公众127.0.0.1\"大众);

进一步,在 fang.html 中添加一个图片,从上面的目录构造中可以看到,图片的路径是完备精确的

<img src=\"大众yule.png\"大众 alt=\"大众图片\"大众>

运行 127.0.0.1:4000/fang,却创造图片破了,解释路径不对。
但事实上,我们可以看到,这个路径是一点问题都没有的呀,那怎么办呢?

又回到了那句话,“Node.js没有web容器”,以是,还是要用前面的方法处理一下图片

//require表示引包,引包便是引用自己的一个分外功能var http = require('http');var fs = require('fs');//创建做事器,参数是一个回调函数,表示如果有要求进来,要做什么var server = http.createServer(function(req, res){ if(req.url=='/fang'){ fs.readFile('./fang.html', function(err,data){ //req表示要求,request; res表示相应,response //设置HTTP头部,状态码是200,文件类型是html,字符集是utf8 res.writeHead(200, {'Content-type':'text/html;charset=UTF-8'}); res.end(data); }) }else if(req.url=='/yuan'){ fs.readFile('./yuan.html', function(err,data){ res.writeHead(200, {'Content-type':'text/html;charset=UTF-8'}); res.end(data); }) }else if(req.url=='/yule.png'){ fs.readFile('./yule.png', function(err,data){ res.writeHead(200, {\"大众Content-type\"大众:\"大众image/jpg\"大众}); res.end(data); }) }else{ res.writeHead(200,{\公众Content-type\"大众:\"大众text/html;charset=UTF-8\公众}); res.end(\"大众Hello World!\"大众); }});//运行做事器,监听4000端口(端口号可以任改)server.listen(4000,\"大众127.0.0.1\"大众);

再次运行,图片可正常显示

现在新建一个 yellow.css 样式表,让 yuan.html 引入这个css 文件

yellow.css

body{background:yellow;}

但是,页面的背景颜色没有发生任何改变

看来 “Node.js没有web容器”这句话是无处不在呀,同样须要对 css 文件做处理

//require表示引包,引包便是引用自己的一个分外功能var http = require('http');var fs = require('fs');//创建做事器,参数是一个回调函数,表示如果有要求进来,要做什么var server = http.createServer(function(req, res){ if(req.url=='/fang'){ fs.readFile('./fang.html', function(err,data){ //req表示要求,request; res表示相应,response //设置HTTP头部,状态码是200,文件类型是html,字符集是utf8 res.writeHead(200, {'Content-type':'text/html;charset=UTF-8'}); res.end(data); }) }else if(req.url=='/yuan'){ fs.readFile('./yuan.html', function(err,data){ res.writeHead(200, {'Content-type':'text/html;charset=UTF-8'}); res.end(data); }) }else if(req.url=='/yule.png'){ fs.readFile('./yule.png', function(err,data){ res.writeHead(200, {\"大众Content-type\"大众:\"大众image/jpg\"大众}); res.end(data); }) }else if(req.url=='/yellow'){ fs.readFile('./yellow.css', function(err,data){ res.writeHead(200, {\"大众Content-type\"大众:\"大众text/css\"大众}); res.end(data); }) }else{ res.writeHead(200,{\"大众Content-type\"大众:\"大众text/html;charset=UTF-8\公众}); res.end(\"大众Hello World!\公众); }});//运行做事器,监听4000端口(端口号可以任改)server.listen(4000,\"大众127.0.0.1\"大众);

再次运行代码,创造页面背景颜色变成了黄色