美文网首页
《深入浅出nodejs》读书笔记

《深入浅出nodejs》读书笔记

作者: Lisa_Guo | 来源:发表于2020-06-11 10:32 被阅读0次

I/O设备:与计算机进行输入输出数据传输的硬件设备(机械部分)
设备控制器:控制IO设备与CPI的通信的电子设备
IO设备 <-> 设备控制器 <-> CPU


设备控制器的组成

第5章

5.1 V8的内存限制

what: 只能使用部分内存,不能使用计算机的全部内存。(64位里为1.5G,32位里为0.7G)
why:因V8的垃圾回收机制的性能较低,采取了限制内存的方式避免因内存回收引发的性能问题

V8 将对象分为新生代对象老生代对象,不同类型的对象采用不同的垃圾回收机制
新生代对象:存活时间短
老生代对象:存活时间长

5.2 提升垃圾回收效率

  1. 主动释放变量 - delete, 变量赋空值
    delete foo
    foo = undefined (推荐)
  2. 尽量少使用
    闭包内无法释放的变量、全局变量,存活周期长,无法及时回收内存,要预防此类变量的不当或过多使用
  3. 使用堆外内存 - Buffer, Stream
    Node的对象一般通过V8在堆内进行内存分配,使用堆外内存就可以扩展Node的内存空间。
    Buffer,Stream等类型变量不是通过V8分配,故不受内存限制
$ node
> process.memoryUsage()  // 查看堆内存情况
{ rss: 13852672,  // Node进程的常驻总内存
heapTotal: 6131200,   // 堆内存总量
heapUsed: 2757120 }  // 当前堆内存使用量
> os.totalmem()  // 查看系统总内存

5.3 内存泄露的预防

通常,造成内存泄露的原因大概有:

    1. 缓存
      通过key/value等形式的变量在内存中直接缓存
      模块是被缓存的常驻对象,所以它的exports出的变量可能存在泄露隐患
      解决方法: 限制缓存使用的大小; 外部缓存,如 redis(推荐)
    1. 队列消费不及时
      队列的消费速度低于生产速度时,会出现泄露情况
      解决方案:队列超长时预警;异步要包含超时机制
    1. 作用域未释放
      特例:

5.4 内存泄露排查

通过三方工具对堆内存使用情况分析

第6章 Buffer

Buffer用于处理量大的数据。由Node的C++模块负责,故而具备高性能,且不受V8引擎内存限制。其类似Array类型,元素为0到255的16进制数的两位数

Buffer与String转换

new Buffer(str, [encoding])
buffer.toString([encoding, start, end])

支持的编码方式:

  • ASCII
  • UTF-8
  • UTF-16LE/UCS-2
  • Base64
  • Binary
  • Hex

Buffer字符串拼接问题

用buffer.tostring进行类型转换时,如果是中文等非英文类,会出现乱码。

乱码的解决方案:

  1. 转换时设置encoding
    buffer.tostring(encoding)
    但Node默认支持的编码方式有限
  2. 三方转码工具
    将buffer缓存到数组,之后用iconv-lite等三方解码
var chunks = [];
var size = 0;
res.on('data', function (chunk) {
   chunks.push(chunk);
   size += chunk.length;
});
res.on('end', function () {
   var buf = Buffer.concat(chunks, size);
   var str = iconv.decode(buf, 'utf8');
   console.log(str);
});

第8章 WEB应用

请求

请求头 request header
Node的http模块接收到请求后,通过http_parser将以下HTTP请求头提取后附加在req对象上。如:req.method, req.url

> GET /path?foo=bar HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8r zlib/1.2.5
> Host: 127.0.0.1:1337
> Accept: */*
>

请求体 request body
而HTTP的请求体,则需要业务代码自行提取。通过header中Content-Type判断当前提交数据的格式。

application/x-www-form-urlencoded:表单数据,请求体数据格式为key=value&key=value
application/json: 请求体为JSON数据格式
multipart/form-data:包含文件等复杂数据类型,请求头Content-Type中会包含一个boundary的分隔符字符串,把数据按分隔符分成多部分传输

Content-Type: multipart/form-data; boundary=AaB03x
Content-Length: 18231

Express有自带中间件express.urlencoded()express.json()将转换后的Object值附加在req.body
有三方插件,如multer,可将含文件数据的form-data转换成可用对象,req.body为普通数据,req.file为文件数据

缓存

  1. 客户端询问是否使用缓存
    请求报文包含If-Modified-Since(时间戳)询问服务器文件有无更新。如没有,服务器返回304 not modified,若更改,返回新文件,并在响应头中增加Last-Modified
    If-Modified-Since以时间戳方式标记不够准确,估引入ETag,是由服务器根据文件内容生成的散列值。ETag用到的请求和响应头分别是If-None-Match/ETag
  2. 客户端直接缓存
    上面的缓存机制,客户端仍旧要发送一个请求。如果能直接使用缓存,就可以减少请求。为达到此目的,服务器可以在响应头中设置ExpiresCache-Control,客户端则根据这个字段直接缓存文件。
    Expires 设置一个时间戳,表明在此时间前文件都有效。
    Cache-Control 使用max-age等多个字段值的方式,能更精准的描述缓存时间限制,而不受客户端服务器端时间不同步的缺陷影响

在资源url中增加版本号或hash值,可使客户端及时请求到最新资源,避免因缓存造成的同步问题

身份认证

请求报文中增加authentication认证信息,此值由前后端协商认证方式和加密生成。

$ curl -v "http://user:pass@www.baidu.com/"
> GET / HTTP/1.1
> Authorization: Basic dXNlcjpwYXNz
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8r zlib/1.2.5
> Host: www.baidu.com
> Accept: */*

目前更多的方案是在api调用时传递有效token

请求安全性

为方式数据上传是造成大量数据推向服务器,造成内存泄露,可通过限制上传数据大小的方式。当数据量达到阈值时禁止上传
为了防止CSRF(跨域请求伪造)造成对服务器的恶意攻击,可在请求和响应中加上一个随机数,来校验请求来源的合法性

其他

路由解析:https://www.jianshu.com/p/4d0512cd0a80
中间件:https://www.jianshu.com/p/724418fee5fb
页面渲染:https://www.jianshu.com/p/141c58b8cc0b

第9章 进程

服务器架构模式

  • 单进程同步:所有请求由同一个进程响应,纯同步模式。已被废弃。
  • 多进程:每个进程负责响应一个请求。但进程的花销比较大
  • 多线程:每个线程负责响应一个请求,花销较小且进程内能通信。
  • 事件驱动(单线程单进程):单进程单线程,基于事件的异步响应模式。但无法充分利用多核cpu,且健壮性低(一旦出错整个程序崩溃)

子进程

Node为解决无法充分利用CPU这个缺陷,提供了child_process子进程功能,该模块提供四个不同的接口来启动子进程来执行程序。

var cp = require('child_process');
cp.spawn('node', ['worker.js']);
cp.exec('node worker.js', function (err, stdout, stderr) {
// some code
});
cp.execFile('worker.js', function (err, stdout, stderr) {
// some code
// javascript文件第一行必须添加:#!/usr/bin/env node 表明执行环境
});
cp.fork('./worker.js');

子进程通信
通常会创建一个或多个子进程去处理计算量大或IO操作,由一个主进程来管理和控制这些子进程

进程间关系

进程间通过message消息传递消息

send() -> 发送消息
on('message', callback) -> 接收消息

Node的父子进程间通过IPC实现进程间通信,具体采用的是管道技术。由libuv实现平台无关的封装,windows由命名管道实现,*nix由Domain Socket实现。通信为双向通信,在系统内核里实现。


IPC进程通信

相关文章

  • 常用链接

    html内容转换jade模版 用户脚本(浏览器插件) Tampermonkey 深入浅出Nodejs读书笔记 s...

  • 2018 第一本书

    阿啦嘞:《深入浅出nodejs》《JS promise迷你书》 不折腾:[ √ ] 《王小波系列》 llp:《皮...

  • 闲聊c/c++ 4: 征服优雅、高效的Libuv库之初识篇

    这一系列文章主要分析nodejs中的核心库Libuv。 我的参考书: 朴灵的深入浅出nodejs Jeffrey ...

  • 深入浅出Nodejs读书笔记

    Node简介 这一章简要介绍了Node,从中可以了解Node的发展历程及其带来的影响和价值。为什么叫Node?起初...

  • 深入浅出Nodejs读书笔记

    转载自:http://web.jobbole.com/86489/ 今天终于把朴灵老师写的《深入浅出Node.js...

  • 读书笔记-深入浅出NodeJS

    Node简介这一章简要介绍了Node,从中可以了解Node的发展历程及其带来的影响和价值。为什么叫Node?起初,...

  • 《深入浅出nodejs》读书笔记

    I/O设备:与计算机进行输入输出数据传输的硬件设备(机械部分)设备控制器:控制IO设备与CPI的通信的电子设备IO...

  • 浅谈node.js模块引入机制

    原文链接 之前笔者对nodejs中的模块是如何引入的也是一头雾水,读了一本《深入浅出nodejs》,加上自己工作时...

  • 近期学习规划

    读完nodejs深入浅出 读完图解HTTP 了解 CommonJS,AMD 规范 学习函数式编程,这个时候可以不局...

  • 深入浅出nodejs

    1.node特点 高性能web服务器的要点:事件驱动、非阻塞I/O 单线程单线程的优点在于:不用在意状态同步问题没...

网友评论

      本文标题:《深入浅出nodejs》读书笔记

      本文链接:https://www.haomeiwen.com/subject/bgkvchtx.html