一、node是如何处理web请求的

浏览器中的js是单线程的,node也是单线程的。这个单线程相当于一个大管家,一切大小事务都要经过他的手才能办成,它总是把IO任务放入到任务池中。
虽然说是单线程,但是node也有一个线程池专门负责执行任务池中的任务,它们把任务完成之后会告知主线程以接下来利用CPU完成处理。
关键在于理清哪些任务是主线程做的,哪些任务是线程池做的。
对于IO操作(例如文件读取、数据库读取、网络请求等),基本全部是线程池完成的(IO操作也有阻塞式的写法);对于计算任务,都是主线程完成的。
不要小看IO操作占用的时间,node的重要优势就是把IO操作放到了主线程之外,从而让主线程腾出手来去处理更多的请求。
node的线程池基于libuv这个库。

node技术的底层依赖:

  • V8:Google 推出的 Javascript VM,也是 Node.js 为什么使用的是 Javascript的关键,它为 Javascript提供了在非浏览器端运行的环境,它的高效是 Node.js 之所以高效的原因之一。
  • Libuv:它为 Node.js 提供了跨平台,线程池,事件池,异步 I/O 等能力,是 Node.js 如此强大的关键。
  • C-ares:提供了异步处理 DNS 相关的能力。
  • http_parser、OpenSSL、zlib 等:提供包括 http 解析、SSL、数据压缩等其他的能力。

二、其它语言是如何处理web请求的

以python为例,gunicorn服务器可以指定worker数,表示可以同时处理的任务数。即便这些任务都是CPU密集型操作,gunicorn也能够最多支持和worker数相等的请求。而node最多只能支持一个CPU密集型任务。
简言之,node相当于一个worker,但是这个worker效率比较高(因为把IO和计算分离开了)。
实际上,node可以通过开很多个进程,通过nginx负载均衡来实现多个worker,这样完全可以达到和其它语言相同的效果。
简言之,开多个worker谁都会。node的优势在于这个优秀的单线程。
开多个worker应该是优化的最后一步,是实在想不出更好办法之后的办法。node的创新之处就在于IO和计算分离,从而将并发量提高了许多。
IO和计算分离是一种思想,并非只能用js实现,其它语言也可以借鉴。

三、node的优势和劣势

  • node擅长执行IO密集型任务,不善于执行CPU密集型任务。
  • node的效率比传统阻塞式web服务高,为啥以前没有想到使用事件驱动模型把IO和计算进行分离?因为分离是有代价的,node异步模式带来了大量的回调,回调一旦太深,代码可读性极差。
  • node的主线程不能崩,主线程一崩整个服务全挂掉。因此一定要接住异常,这个问题不算劣势,因为很容易解决。

四、node如何实现多个worker

cluster模块已经成为node的标准模块了,这个模块赋予了node多worker的能力。使用nginx+多个实例的方法需要占用多个端口,cluster则能够让多个worker共用同一端口。
原来的单线程模型处理计算密集型任务的线程只有一个,即主线程;处理IO的线程有多个。现在cluster通过开辟多个处理计算密集型任务的线程实现了多worker。

参考资料

一篇cluster的详细讲解
https://blog.csdn.net/leohzj/article/details/50462231

Node单线程高并发原理的更多相关文章

  1. 理论铺垫:阻塞IO、非阻塞IO、IO多路复用/事件驱动IO(单线程高并发原理)、异步IO

    完全来自:http://www.cnblogs.com/alex3714/articles/5876749.html 同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同 ...

  2. MySQL InnoDB 实现高并发原理

    MySQL 原理篇 MySQL 索引机制 MySQL 体系结构及存储引擎 MySQL 语句执行过程详解 MySQL 执行计划详解 MySQL InnoDB 缓冲池 MySQL InnoDB 事务 My ...

  3. nodejs 单线程 高并发

    nodejs为什么是单线程且支持高并发的脚本语言呢? 1.node的优点:I/O密集型处理(node的I/O请求都是异步的,如:sql查询.文件流操作.http请求……):异步I/O?顾名思义就是异步 ...

  4. 协程--gevent模块(单线程高并发)

    先恶补一下知识点,上节回顾 上下文切换:当CPU从执行一个线程切换到执行另外一个线程的时候,它需要先存储当前线程的本地的数据,程序指针等,然后载入另一个线程的本地数据,程序指针等,最后才开始执行.这种 ...

  5. nginx、swoole高并发原理初探

    阅前热身 为了更加形象的说明同步异步.阻塞非阻塞,我们以小明去买奶茶为例. 同步与异步 同步与异步的重点在消息通知的方式上,也就是调用结果通知的方式. 同步:当一个同步调用发出去后,调用者要一直等待调 ...

  6. InnoDB高并发原理

    一.并发控制 为啥要进行并发控制? 并发的任务对同一个临界资源进行操作,如果不采取措施,可能导致不一致,故必须进行并发控制(Concurrency Control). 技术上,通常如何进行并发控制? ...

  7. 【多线程与高并发原理篇:4_深入理解synchronized】

    1. 前言 越是简单的东西,在深入了解后发现越复杂.想起了曾在初中阶段,语文老师给我们解说<论语>的道理,顺便给我们提了一句,说老子的无为思想比较消极,学生时代不要太关注.现在有了一定的生 ...

  8. Proactor设计模式:单线程高并发

    Boost::Asio为同步和异步操作提供了并行支持,异步支持基于前摄器模式,这种模式的优点和缺点可能比只同步或反应器方法要低. 让我们检查一下Boost::Asio是如何实现前摄器模式的,没有引用基 ...

  9. Netty高并发原理

        Netty是一个高性能 事件驱动的异步的非堵塞的IO(NIO)框架,用于建立TCP等底层的连接,基于Netty可以建立高性能的Http服务器.支持HTTP. WebSocket .Protob ...

随机推荐

  1. html与css架构的一点体验

    css本身,可以说是一门非常简单而容易入门的语言.制作一个页面,或者制作一个小企业站,对于css的要求都是非常低的.只要熟悉语法,通过英文单词的含义猜,都基本可以拼出一套样式.更何况市面上还有各种各样 ...

  2. extern外部方法使用C#简单例子

    外部方法使用C#简单例子 1.增加引用using System.Runtime.InteropServices; 2.声明和实现的连接[DllImport("kernel32", ...

  3. 关于UITableView的黑线条

    这里採用分组形式.底色可用图片覆盖,设置为cell(是一个view)的子视图,并把cell'的颜色设置为底色 当UITableView的cell没有满屏显示时,就会出现黑线条.我们仅仅需在初始化时,加 ...

  4. MongoDB分页的Java实现和分页需求的思考

    前言 传统关系数据库中都提供了基于row number的分页功能,切换MongoDB后,想要实现分页,则需要修改一下思路. 传统分页思路 假设一页大小为10条.则 //page 1 1-10 //pa ...

  5. MySQL在线大表DDL操作 (转)

    http://www.cnblogs.com/janehoo/p/5382474.html 线大表DDL操作的方法: 1.主从架构轮询修改 需要注意: a.主库会话级别的记录binglog的参数关闭 ...

  6. 【转】vim中多标签和多窗口的使用

    原文:https://my.oschina.net/kutengshe/blog/464602 ---------------------------------------------------- ...

  7. error MSB6006: "CL.exe" exited with code -1073741819.

    编译一个c++项目的时候,会报如下的错误,总是无法编译,是怎么回事? error MSB6006: "CL.exe" exited with code -1073741819. 搜 ...

  8. Uniform and Interpolator Packing的作用

    All of the packing that is done is completely transparent to the user of the OpenGL ES Shading Langu ...

  9. 基于PHP构建OAuth 2.0 服务端 认证平台

    OAuth2.0 认证服务 安装 你可以在github上下载OAuth Server PHP,也可以用下列命令下载,不过内容都是一样的 mkdir my-oauth2-walkthrough cd m ...

  10. C#.NET常见问题(FAQ)-构造器constructor有什么用

    所谓的构造器constructor,就是声明类的时候定义一个public 类名的方法,这个方法不需要传递任何数据,这样的话在声明任何类的实例的时候都会无条件执行里面的方法   析构器只在程序销毁的时候 ...