node读书小记

一 node概述:

    node可以通过以下方式来充分利用cpu:① 编写c/c++模块扩展的方式 ② 通过子进程的方式,将计算与IO分离。

    js的问题:没有模块系统;标准库较少;没有标准接口;缺乏包管理。

二 node的模块实现:

     node的模块分为两类:

                 node提供的模块,核心模块:在node源代码编译的过程中,编译进了二进制执行文件。在node进程启动时,部分核心模块被直接加载进内存中。这部分模块省去了文件定位和编译执行这两步。是最快的。node对引入过得模块会进行缓存,以减少了二次引入的开销。不同得是浏览器缓存文件,而node缓存的是编译和执行之后的对象。核心模块在编译成可执行文件的过程中被编译进了二进制文件。核心模块其实分为c和c++编写的和js编写的两部分。有些全部由c和c++编写(内建模块),有些则由c和c++完成核心。脚本语言的开发速度优于静态语言,但是性能弱于静态语言。js核心模块的作用:一类式作为c和c++内建模块的封装层和桥接层,供文件模块使用;一类式纯粹的功能模块。不需要和底层打交道。

                  用户编写的模块,文件模块。主要由第三方编写,包括普通的js模块和c扩展模块,方向为,普通js模块调用扩展模块。

     在node中引入模块时经历了一下三个步骤:

     ① 路径分析:

                 模块标识符分析:fs,http,path等核心模块;.或者..开始的绝对路径模块;/开始的绝对路径文件模块。核心模块的优先级次于缓存加载。自定义模块的查找类似作用域链,依次查找node_module目录。

     ② 文件定位:

                 文件扩展名分析:CommonJS规范容许在标识符中不包含文件扩展名,这是node会按js,json,node的次序补足扩展名,依次尝试,所以为了提高速度最好带上扩展名。

                  目录分析和包:分析扩展名后可能没有找到文件,但得到一目录,node会将此目录当做一个包来处理。在其中查找package。json,从中取出main属性指定的文件名定位。如果不行,则会将index当做默认文件。

      ③ 编译执行:

          这是引入文件的最后一个阶段。先载入在编译,载入方法有所不同:js文件,用fs同步读取文件后编译执行。node结尾的文件(c和c++编写的扩展文件)用dlopen方法加载最后编译生成的文件。json文件用fs同步读取后用JSON.parse解析返回结果。每个编译成功的模块都会将文件路径作为索引缓存在Module.——cache对象上。

          (1)js模块的编译:node对读取到的js文件内容进行了头尾的包装,这样每个模块都进行了作用域的隔离。返回一个具体的function对象后,将5个参数传入function执行。执行之后exports属性返回给了调用方。

          (2)c和c++模块的编译:不同得平台通过libuv进行封装,使用process的dlopen方法进行加载和执行。

           (3)以上是文件模块的,对于核心模块:js核心模块:需要将js模块文件编译为c和c++代码,通过process的binding(‘native’)方法取出。编译成功的核心模块缓存到NativeModule._cache对象上,文件模块则缓存到Module._cache对象上

     ④ c和c++扩展模块

        js的一个典型弱点是位运算,js的位运算是模仿java的,java在int基础上进行的,而js只有double型,所以要先转为int再进行运算。

         在应用中会频繁出现位运算的需求:转码、编码等,这时候可以用c和c++的扩展模块来实现。表面是.node的形式,实质是.dll或者.so

三 异步IO

        php全部是同步阻塞的方式实现的,小规模站点中不存在问题。Nginx由c编写,面向客户端管理连接的能力强大,但是它背后依然受限于同步方式的编程语言。适合用作web服务器,用于反向代理和负载均衡等服务,在处理具体业务方面较为欠缺。

        多线程的代价在于创建线程和执行期线程上下文切换的开销较大。在复杂业务中多线程编程经常面临锁,状态同步等问题。但是对cpu的利用率的优势是不用质疑的。

        node的单线程只是js执行在单线程中罢了,在node中,linux或者windows内部完成io另有线程池。

        事件循环是典型的生产者和消费者模型,异步io,网络请求是事件的生产者,这些事件被传递到观察者那里,事件循环从观察者那里取出事件并处理。

四 异步编程的优势与难点

        难点:1 异常处理;2函数嵌套过深;3阻塞代码;4多线程编程;5异步转同步

        异步编程解决方案:事件发布和订阅模式;Promise/Deferred;流程控制库。

五 内存控制

           查看垃圾回收日志的主要方式在启动时添加--trace_gc参数。可以了解垃圾回收的运行状况,找出出发原因和比较耗时的阶段。

            通过node启动时使用--prof参数,得到v8的性能分析数据,包含了垃圾回收执行时占用的时间。

            查看内存:process.memoryUsage():查看node进程的内存占用。os模块中的totalmem()和freemem()可以查看操作系统的内存使用情况。

           node的内存构成:不是通过v8分配的内存(堆外内存)即node自行分配的内存,和通过v8分配的内存。

           内存泄露:实质只有一个就是该回收的对象出现意外没有被回收。

            原因有:缓存、队列消费不及时、作用域未释放。

                            ① 缓存可以有效的节约资源,一次命中,就可以节省一次io的时间。js开发者喜欢用键值对来缓存东西,但是没有完善的过期策略,与严格意义上的缓存有区    别。解决方案:采用进程外的缓存,进程自身不存储状态,外部缓存有良好的过期策略和内存管理,不影响node进程的性能。比如使用redis和memcached。

                            ②队列在消费者生产者模型中充当中间产物。比如采用数据库来记录日志,写入效率低时导致写入堆积,消费速度低于生产速度。解决方案:换用消费速度更高的技术。

            内存泄露的排查:v8对内存泄露很铭感,有很多工具可以定位node应用的内存泄露:v8-profiler、node-heapdump等。一般是对堆内存抓起快照。

            大内存的应用可以使用stream模块。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值