一直以来被node的神秘深深吸引,于是在2020年七夕节,想要和node关系更进一步,开始揭开他神秘的面纱~
1.what:什么是node?
官方给出答案:
Node.js 就是运行在服务端的 JavaScript。
Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台。
Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好
其实我还是不懂。但是继续往下学习。。。。万一某个瞬间 就懂了呢
2 what:node有什么特点?
1.异步io 2.事件和回调函数 3.单线程:保持了js单线程特点 4.跨平台:基于libuv实现跨平台
3.why:什么场景适合用node?
io密集型:node利用事件循环处理能力,而不是启动每一个线程为每一个请求服务,资源占用极少 cpu密集型:v8的执行效率非常高,
总的来说 高并发、I/O密集、少量业务逻辑的场景。
1.node用来做什么? 搜索引擎优化,网页首屏加速 = 服务端渲染
4.how:怎么使用node?
1.创建一个http服务
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
2.模块化
Nodejs端是使用CommonJS规范的,前端浏览器一般使用AMD、CMD、ES6等定义模块化开发的
1>commont.js 是通过module.exports定义的,在前端浏览器里面并不支持module.exports,通过node.js后端使用的。
输出方式有2种:默认输出---module export 和带有名字的输出---exports.area
exports.area = function(r){
return Math.PI*r*r;
};
2>CMD 同步 在依赖的部分 cmd支持动态引入,
于AMD相比,amd需要在声明模块的时候指定所有的依赖,通过形参传递依赖熬模块内容中:
amd:
define(['dep1', 'dep2'], function (dep1, dep2) {
return function () {};
});
cmd:
define(function(require, exports, module) {
// The module code goes here
});
require, exports, module 通过形参传递给模块,在需要依赖模块时,随时调用require()引入即可。 3>AMD 异步
eg如下: 他的模块id和依赖是可选的。
与node相似的地方:factory 的内容就是实际代码的内容。 不同地方:AMD 模块需要用define来明确定义一个模块,而在node实现中是隐式包装的,他的目的是进行作用域的隔离,仅在需要的时候被引入,避免掉过去那种通过全局变量或全局命名空间的方式,以免变量污染和不小心修改,内容需要通过返回的方式导出。
define(id?, dependencies?, factory);
define(function() {
var exports = {};
exports.sayHello = function() {
alert('Hello from module: ' + module.id);
};
return exports;
});
3.node操控文件系统(原生)
对于绝大多数的pi来说,node都提供了相同功能的俩个版本: 同步版本/异步版本
同步和异步在命名上存在以下规则:
xxx 异步/xxxsync 同步
尽最大可能使用异步版本
若 文件内容多,则用 fs.createWriteStream(path[, options]) 和fs.createReadStream(path[, options]),具体事例参考官方node api
eg:
const fs = require('fs')
fs.rename('before.json', 'after.json', err => {
if (err) {
return console.error(err)
}
//完成
})
const fs = require('fs')
try {
fs.renameSync('before.json', 'after.json')
//完成
} catch (err) {
console.error(err)
}
4.buffer
Buffer是一个像Array的对象,但他主要用于操作字节 所有的数据传输到最底层,全是二进制,在传输的过程中,字符也就是01这类编码是一个一个被从一个地方取出来又放到另一个地方去的,没有缓冲的话,只有一个字符被发送者发出后才能取到,一旦发送和取出的速度不一致,就会出现数据传输卡顿甚至断流, 所以加了缓冲器,发送者把数据全部放在缓冲期里,接受者去里面取,这样只要缓冲器里还有数据,接受者接收数据就不会卡顿,甚至发送者突然卡死,接受者也可以拿到数据。不会出现数据卡顿。只要在接受者取完缓冲器里的数据之前,发送者可以继续存放,数据就依然正常传输,视频里的缓存就是这个效果
5.建立udp服务
udp服务端
dgram = require("dgram");
var server = dgram.createSocket("udp4"); // 创建一个udp套接字
server.on("message", function (msg, rinfo) {
console.log("server got: " + msg + " from " +
rinfo.address + ":" + rinfo.port);
});
server.on("listening", function () {
var address = server.address();
console.log("server listening " +
address.address + ":" + address.port);
});
server.bind(41234);
客户端
var dgram = require('dgram');
var message = new Buffer("ศ入റ出Node.js");
var client = dgram.createSocket("udp4");
client.send(message, 0, message.length, 41234, "localhost", function(err, bytes) {
client.close();
});
socket.send(buf, offset, length, port, address, [callback]) 这些参数分别要发送buffer, buffer偏移,buffer长度,目标端口,目标地址,发送完成后的回调
6.建立tcp服务
通过net.createServer(listener)创建一个tcp服务器,listener是连接事件connection的侦听器,也可以用如下方式进行侦听:var server = net.createServer(); server.on('connection', function (socket) { // ႎ的接 }); server.listen(8124);
tcp服务端
var net = require('net');
var server = net.createServer(function (socket) {
// ႎ的接
socket.on('data', function (data) {
socket.write("ేࡻ");
});
socket.on('end', function () {
console.log('接开');
});
socket.write("࣌ᆓ࠼ଣĖศ入റ出Node.jsė๖૩:\n");
});
server.listen(8124, function () {
console.log('server bound');
});
客户端
var net = require('net');
var client = net.connect({port: 8124}, function () { //'connect' listener
console.log('client connected');
client.write('world!\r\n');
});
client.on('data', function (data) {
console.log(data.toString());
client.end();
});
client.on('end', function () {
console.log('client disconnected');
});
tcp:传输控制协议,osi模型中分为7层(物理层,数据链结层,网络层,网络层,传输层,会话层,表示层,应用层),属于传输层。tcp是面向连接的协议,特征:在传输之前要进行3次握手形成会话,会话行成之后,客户端和服务端能相互发送数据。在服务端和客户端分别提供一个套接字。tcp连接一旦建立,所有会话都基于连接完成。
udp:用户数据包协议,和tcp一样属于网络传输层。和tcp最大的不同,udp不是面向连接的,一个套接字可以与多个UDP服务通信,它虽然提供面向事物的简单不可靠信息传输服务。在网络差的情况下存在丢包严重的问题,但是由于它无需连接,资源消耗低,处理快速且灵活,所以常常应用到 丢一两个数据包也不会产生重大影响的场景。比如(音频 视频),udp应用很广泛,dns是基于它实现的。
http:超文本传输协议,http构建在tcp之上,属于应用层协议
https:
websocket:实现了客户端与服务端的长连接,而node事件驱动的方式十分擅长与大量的客户端保持高并发连接,相比较tcp,他是双向通信。 主要分为握手和数据传输。一旦握手成功,服务端和客户端会呈现对等的效果,都能发送和接收消息。
网络服务和安全:ssl 安全协议,他在传输层提供对网络连接加密的功能。对于应用层而言 他是透明的。
7.建立socket.io服务(客户端/服务端)
8.异步io与线程池
io:即input/output,一个系统的输入和输出
阻塞io和非阻塞io区别:系统接收输入再到输出期间,能不能接收其他输入
如何理解 阻塞io和非阻塞io:1》先确定一个进行input/output系统2》思考在I/O过程中能不能进行其他I/O
同步阻塞io:就是cpu既要监控数据是否就绪,还要负责数据的读取
同步非阻塞io:就是等数据就绪后,会有人通知我去读取数据
异步io:就更骚操作了,等数据读取好了后,再告诉我
事件循环:
异步编程解决方案: 1、事件发布/订阅模式 2、promise/deferred模式 3、流程控制库
异步编程: 1.callback() 2.promise 3.async/await 4.Generator
9.连接数据库
10.连接redis
11.子进程与主子进程通信
12.内存控制
内存泄漏的原因:1.缓存 2.队列消费不及时 3.作用域未释放
闭包:在js'中,实现外部作用域访问内部作用域中变量的方法就是闭包
排查内存泄漏的原因,主要是通过对堆内存进行分析而找到node-heapdump和node-memwatch各有所长
集群 分布式
集群 就是派多个一样的人干同一个活
分布式就是把一个活分工分成不同任务,找不同的人干
业务复杂的时候用分布式,任务量大的时候用集群
备注:
BFF层 backend for Frontend
使用后端的RPC服务 对用户侧提供http服务
npm包是什么? node.js的包管理工具。 包是什么? 别人写的node.js模块。