Node.js is a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.
我们在银行排队办理业务
(1)系统线程模型:
这种模型的问题显而易见,服务端只有一个线程,并发请求(用户)到达只能处理一个。
其余的要先等待,这就是阻塞,正在享受服务的请求阻塞后面的请求了
这个模型已经比上一个有所进步,它调节服务端线程的数量来提高对并发请求的接收和响应,但并发量高的时候,请求仍然需要等待,它有个更严重的问题:
回到代码层面上来讲,我们看看客户端请求与服务端通讯的过程:
服务端与客户端每建立一个连接,都要为这个连接分配一套配套的资源,主要体现为系统内存资源,以PHP为例,维护一个连接可能需要20M的内存
这就是为什么一般并发量一大,就需要多开服务器
3. 异步、事件驱动模型
基于这样的机制,理论上陆续有用户请求连接,NodeJS都可以进行响应,因此NodeJS能支持比Java、PHP程序更高的并发量
维护事件队列也需要成本,再由于NodeJS是单线程,事件队列越长,得到响应的时间就越长,并发量上去还是会力不从心
更改连接到服务器的方式,每个连接发射(emit)一个在NodeJS引擎进程中运行的事件(Event),放进事件队列当中,而不是为每个连接生成一个新的OS线程(并为其分配一些配套内存)
// get the profile
$profile = $userProfile->getProfile($_userid);
// get the timeline
$timeline = $userTimelineModel->getTimeline($_userid);
// Todo
// ...
echo $return;
假如获取profile和timeline操作各需要1S
那么串行获取就需要2S
var proxy = new EventProxy();
proxy.all('profile', 'timeline', function (profile, timeline) {
// todo
});
api.getUser('username', function (profile) {
proxy.emit('profile', profile);
});
api.getTimeline('username', function (timeline) {
proxy.emit('timeline', timeline);
})
两个动作并行执行,假如各需要1S
那么总的时间也就是1S
Java、PHP也有办法实现并行请求(子线程),但NodeJS通过回调函数(Callback)和异步机制会做得很自然
解决方案:分解大型运算任务为多个小任务,使得运算能够适时释放,不阻塞I/O调用的发起;
一旦代码某个环节崩溃,整个系统都崩溃
解决方案:
(1)Nnigx反向代理,负载均衡,开多个进程,绑定多个端口;
(2)开多个进程监听同一个端口,使用cluster模块;
这是NodeJS最理想的应用场景,可以处理数万条连接,本身没有太多的逻辑,只需要请求API,组织数据进行返回即可。
它本质上只是从某个数据库中查找一些值并将它们组成一个响应。
由于响应是少量文本,入站请求也是少量的文本,因此流量不高,一台机器甚至也可以处理最繁忙的公司的API需求。
目前MVC的架构,在某种意义上来说,Web开发有两个UI层,一个是在浏览器里面我们最终看到的,另一个在server端,负责生成和拼接页面。