• NodeJS概述


    NodeJS中文API

    一.概述

    Node.js 是一种建立在Google Chrome’s v8 engine上的 non-blocking (非阻塞), event-driven (基于事件的) I/O平台.

    以事件驱动为核心,单线程,单进程。Node.js 最大的特点就是采用异步式 I/O 与事件驱动的架构设计。对于高并发的解决方案,传统的架构是多线程模型,也就是为每个业务逻辑提供一个系统线程,通过系统线程切换来弥补同步式 I/O 调用时的时间开销。Node.js 使用的是单线程模型,对于所有 I/O 都采用异步式的请求方式,避免了频繁的上下文切换。Node.js 在执行的过程中会维护一个事件队列,程序在执行时进入事件循环等待下一个事件到来,每个异步式 I/O 请求完成后会被推送到事件队列,等待程序进程进行处理。事件驱动机制是Node.js通过内部单线程高效率地维护事件循环队列来实现的,没有多线程的资源占用和上下文切换,这意味着面对大规模的http请求,Node.js凭借事件驱动搞定一切。因为Node是基于事件驱动和无阻塞的,所以非常适合处理并发请求。可以通过运行多个Node.js进程的方式来有效利用多个CPU。

     

    二.Node.js选择的异步I/O方案

    1.在Linux下,node.js靠libev和libeio配合使用来实现异步I/O。

    (1).什么是libev?

    • libev是一个事件驱动库,提供高性能事件循环

    • 主要用于事件驱动的网络编程

    (2).什么是libeio?

    libeio为C提供异步版本的POSIX API

    • 主要提供文件I/O操作

    • 异步操作通过线程实现

    • libeio仅依赖pthread,跨平台能力非常好

    • 可以和任何事件库配合使用,比如libev 。

    (3).为什么不用libev实现异步文件操作?

    对于Regular File 来说,是不能够用采用 poll/epoll 的,即O_NOBLOCK 方式对于传统文件句柄是无效的,也就是说我们的 open ,read, mkdir 之类的Regular File操作必定会导致阻塞.

     

    2.Windows有一种独有的内核异步IO方案:IOCP。IOCP的思路是真正的异步I/O方案,调用异步方法,然后等待I/O完成通知。IOCP内部依旧是通过线程实现,不同在于这些线程由系统内核接手管理。IOCP的异步模型与Node.js的异步调用模型已经十分近似。

         

    3.由于Windows平台和*nix平台的差异,Node.js提供了libuv来作为抽象封装层,使得所有平台兼容性的判断都由这一层次来完成,保证上层的Node.js与下层的libeio/libev及IOCP之间各自独立。Node.js在编译期间会判断平台条件,选择性编译unix目录或是win目录下的源文件到目标程序中。

    对于 POSIX①操作系统,libuv 通过封装 libev 和 libeio 来利用 epoll 或 kqueue。而在 Windows 下,libuv 使用了 Windows 的 IOCP(Input/Output Completion Port,输入输出完成端口)机制,以在不同平台下实现同样的高性能。

    ① POSIX(Portable Operating System Interface)是一套操作系统 API 规范。一般而言,遵守 POSIX 规范的操作系统指的是 UNIX、Linux、Mac OS X 等。

    arch

     

    下面是Node.JS架构示意图

    1-2

     

    三.异步式 I/O 与事件驱动

    Node.js 的异步机制是基于事件的,所有的磁盘 I/O、网络通信、数据库查询都以非阻塞的方式请求,返回的结果由事件循环来处理。图1-1 描述了这个机制。Node.js 进程在同一时刻只会处理一个事件,完成后立即进入事件循环检查并处理后面的事件。这样做的好处是,CPU 和内存在同一时间集中处理一件事,同时尽可能让耗时的 I/O 操作并行执行。对于低速连接攻击,Node.js 只是在事件队列中增加请求,等待操作系统的回应,因而不会有任何多线程开销,很大程度上可以提高 Web 应用的健壮性,防止恶意攻击。

    1-1

    图1-1 事件循环

     

    以在Windows平台下的实现中,启动Node.js时,便创建了一个基于IOCP的事件循环loop,并一直处于执行状态。

    uv_run(uv_default_loop());

    每次循环中,它会调用IOCP相关的GetQueuedCompletionStatus方法检查是否线程池中有执行完的请求,如果存在,poll操作会将请求对象加入到loop的pending_reqs_tail属性上。 另一边这个循环也会不断检查loop对象上的pending_reqs_tail引用,如果有可用的请求对象,就取出请求对象的result属性作为结果传递给oncomplete_sym执行,以此达到调用JavaScript中传入的回调函数的目的。 至此,整个异步I/O的流程完成结束。

    事件循环和请求对象构成了Node.js的异步I/O模型的两个基本元素,这也是典型的消费者生产者场景。在Windows下通过IOCP的GetQueuedCompletionStatus、PostQueuedCompletionStatus、QueueUserWorkItem方法与事件循环实。对于*nix平台下,这个流程的不同之处在与实现这些功能的方法是由libeio和libev提供。

     

    四.多线程阻塞服务器 vs 事件驱动、无阻塞服务器

    clipboard

    clipboard[1]

    坚持,坚持,再坚持。
  • 相关阅读:
    优化SQL查询:如何写出高性能SQL语句
    动态库与静态库
    多线程程序中fork导致的一些问题
    合理的使用size_t可以提高程序的可移植性和代码的可读性,让你的程序更高效。
    linux下C++ STL hash_map的使用以及使用char *型变量作为Key值的一大“坑”
    阅读腾讯编程规范的笔记
    2、vector的实现
    linux下C++对线程的封装
    1、空间配置器
    SQL Server三种表连接原理
  • 原文地址:https://www.cnblogs.com/walk-the-Line/p/4900350.html
Copyright © 2020-2023  润新知