1. node的单缓存
    民主化是两个具有很大分立功能的流程在两个统计数据K568的一次静态继续执行的过程,是作业控制系统进行天然分权和运维的两个分立基层单位,是应用流程运转的媒介。
    缓存是流程继续执行中两个单个的顺序控制流,它存有于民主化之中,是比民主化更小的能分立运转的基本上基层单位。
    早期在R5 CPU 的控制系统中,为的是实现虚拟化的运转,导入了民主化的基本上概念,不同的流程运转在统计数据与命令互相隔绝的民主化中,通过天数片Tiruvanamalai运维继续执行,虽然 CPU 天数片转换与继续执行很快,因此看起来像在同一个天数运转了数个流程。
    虽然民主化转换时需要留存相关硬体当晚、民主化控制块等信息,因此控制系统开支较大。为的是不断提高控制系统林宏吉率,在同一个民主化继续执行时更充分的借助 CPU 资源,导入了缓存的基本上概念。缓存是作业控制系统运维继续执行的最轻基层单位,它们依附民主化中,共享资源同一个民主化中的天然资源,基本上不保有或者只保有小量控制系统天然资源,转换开支很小。
    Node是如前所述V8发动机其内构筑的,决定了他与应用程序的机制很类似。
    两个node民主化根本无法借助两个核,而且node根本无法运转在单缓存中,严苛意义上,node绝非真正的单缓存构架,即两个民主化内能有数个缓存,即使node自己还有很大的i/o缓存存有,那些I/O缓存由下层的libuv处理,但那些缓存对node开发人员而言是完成透明化的,只有在C++扩充TNUMBERV12V4会加进,这里他们就过滤下层的技术细节,专门探讨他们所要关注的。
    node的构架层次单缓存的益处是:流程状态单个,在没多缓存的情况下,没锁、缓存并行问题,作业控制系统在运维时,也即使极少的语句的转换,能较好地提高CPU的使用量。然而R5单缓存也有相应的优点:
那个缓存读出来后整个流程就会读出来;无法充分借助多核天然资源两个CPU运转到死,其他的CPU在看着2. node多民主化的建立
    node提供更多child_process组件,那个组件中,提供更多了数个方法来建立子民主化。
    const { spawn, exec, execFile, fork } = require(child_process);
    
    这4个方法都能建立子民主化,不过使用方法还是稍微有点区别。他们以建立两个子民主化计算斐波那契数列数列为例,子民主化的文件(worker.js):
    // worker.jsconst fib = (num) => {
        if (num === 1 || num === 2) {
        return num;
        }
        let a = 1, b = 2, sum = 0;
        for (let i = 3; i <= num; i++) {
        sum = a + b;
        a = b;
        b = sum;
        }
        return sum;
        }
        const num = Math.floor(Math.random() * 10) + 3;
        const result = fib(num);
        console.log(num, result, process.pid); // process.pid表示当前的民主化id
        
    
    在master.js中如何调用那些方法建立子民主化呢?
    命令使用方法解析spawnspawn(node, [worker.js])启动两个字民主化来继续执行命令execexec(node worker.js, (err, stdout, stderr) => {})启动两个子民主化来继续执行命令,有回调execFileexexFile(worker.js)启动两个子民主化来继续执行可继续执行的文件
    (头部要添加#!/usr/bin/env node)forkfork(worker.js)与spawn类似,不过这里只需要自定js文件组件即可
    以fork命令为例:
    const { fork } = require(child_process);
        const cpus = require(os).cpus();
        for(let i=0, len=cpus.length; i<len; i++) {
        fork(./worker.js);
        }
    
    3. 多民主化之间的通信
    node中民主化的通信主要在主从(子)民主化之间进行通信,子民主化之间无法直接通信,若要互相通信,则要通过主进程进行信息的转发。
    主民主化和子民主化之间是通过IPC(Inter Process Communication,民主化间通信)进行通信的,IPC也是由下层的libuv根据不同的作业控制系统来实现的。
    他们还是以计算斐波那契数列数列为例,在这里,他们用cpu个数减1个的民主化来进行计算,剩余的那两个用来输出结果。这就需要负责计算的子民主化,要把结果传给主民主化,再让主民主化传给输出进行,来进行输出。这里他们需要3个文件:
master.js:用来建立子民主化和子民主化间的通信;fib.js:计算斐波那契数列;log.js:输出斐波那契数列计算的结果;主民主化:
    // master.js
        
        const { fork } = require(child_process);
        const cpus = require(os).cpus();
        const logWorker = fork(./log.js);
        for(let i=0, len=cpus.length–1; i<len; i++) {
        const worker = fork(./fib.js);
        worker.send(Math.floor(Math.random()*10 + 4)); // 要计算的num
         worker.on(message, (data) => { // 计算后返回的结果
         logWorker.send(data); // 将结果发送给输出民主化
         })
        }
    
    计算民主化:
    // fib.js
        const fib = (num) => {
        if (num===1 || num===2) {
        return num;
        }
        let a=1, b=2, sum=0;
        for(let i=3; i<num; i++) {
        sum = a + b;
        a = b;
        b = sum;
        }
        return sum;
        }
        process.on(message, num => {
        const result = fib(num);
        process.send(JSON.stringify({
        num,
        result,
        pid: process.pid
        }))
        })
    
    输出民主化:
    process.on(message, data => {
        console.log(process.pid, data);
        })
    
    当他们运转master时,就能看到各个子民主化计算的结果:
    多进程的斐波那契数列输出结果第1个数字表示当前输出子民主化的编号,后面表示在各个子民主化计算的统计数据。
    同理,他们在进行http服务日志记录时,也能采用类似的思路,数个子民主化承担http服务,剩下的子民主化来进行日志记录等操作。
    当我想用子民主化建立服务器时,采用上面类似斐波那契数列的思路,将fib.js改为httpServer.js:
    // httpServer.js
        const http = require(http);
        http.createServer((req, res) => {
        res.writeHead(200, {
        Content-Type: text/html
        });
        res.end(Math.random()+);
        }).listen(8080);
        console.log(http server has started at 8080, pid: +process.pid);
    
    结果却出现错误了,提示8080端口已经被占用了:
    Error: listen EADDRINUSE: address already in use :::8080
    这是即使:在TCP端socket套接字监听端口有两个文件描述符,每个民主化的文件描述符都不相同,监听相同端口时就会失败。
    解决方案有两种:首先最简单的就是每个子民主化都使用不同的端口,主民主化将循环的标识给子民主化,子民主化通过那个标识来使用相关的端口(例如从8080+传入的标识作为当前民主化的端口号)。
    第二种方案是,在主民主化进行端口的监听,然后将监听的套接字传给子民主化。
    将套接字socket发送给子民主化主民主化:
    // master.js
        const fork = require(child_process).fork;
        const net = require(net);
        const server = net.createServer();
        const child1 = fork(./httpServer1.js); // randomconst child2 = fork(./httpServer2.js); // now
        
        server.listen(8080, () => {
        child1.send(server, server);
        child2.send(server, server);
        server.close();
        })
    
    httpServer1.js:
    const http = require(http);
        const server = http.createServer((req, res) => {
        res.writeHead(200, {
        Content-Type: text/plain
        });
        res.end(Math.random()+, at pid:  + process.pid);
        });
        process.on(message, (type, tcp) => {
        if (type===server) {
        tcp.on(connection, socket => {
        server.emit(connection, socket)
        })
        }
        })
    
    httpServer2.js:
    const http = require(http);
        const server = http.createServer((req, res) => {
        res.writeHead(200, {
        Content-Type: text/plain
        });
        res.end(Date.now()+, at pid:  + process.pid);
        });
        process.on(message, (type, tcp) => {
        if (type===server) {
        tcp.on(connection, socket => {
        server.emit(connection, socket)
        })
        }
        })
    
    他们的2个server,两个是输出随机数,两个是输出当前的天数戳,能发现这两个server都能正常的运转。同时,即使那些民主化服务是抢占式的,哪个民主化抢到连接,就哪个民主化处理请求。
    他们也应当知道的是:
每个民主化之间的内存统计数据是不互通的,若他们在某一民主化中使用变量缓存了统计数据,另两个民主化是读取不到的。4. 多民主化的守护者
    刚才他们在第3部分建立的多民主化,解决了多核CPU借助率的问题,接下来要解决民主化稳定的问题。
    每个子民主化退出时,都会触发exit事件,因此他们通过监听exit事件来获知有民主化退出了,这时,他们就能建立两个新的民主化来替代。
    const fork = require(child_process).fork;
        const cpus = require(os).cpus();
        const net = require(net);
        const server = net.createServer();
        const createServer = () => {
        const worker = fork(./httpServer.js);
        worker.on(exit, () => {
        // 当有民主化退出时,则建立两个新的民主化
         console.log(worker exit:  + worker.pid);
        createServer();
        });
        worker.send(server, server);
        console.log(create worker: + worker.pid);
        }
        server.listen(8080, () => {
        for(let i=0, len=cpus.length; i<len; i++) {
        createServer();
        }
        })
    
    cluster组件
    在多民主化守护者这块,node也推出了cluster组件,用来解决多核CPU的借助率问题。同时cluster中也提供更多了exit事件来监听子民主化的退出。
    两个经典的案例:
    const cluster = require(cluster);
        const http = require(http);
        const cpus = require(os).cpus();
        if (cluster.isMaster) {
        console.log(`主民主化 ${process.pid} 正在运转`);
        // 衍生工作民主化。
         for (let i = 0, len=cpus.length; i < len; i++) {
        cluster.fork();
        }
        cluster.on(exit, (worker) => {
        console.log(`工作民主化 ${worker.process.pid} 已退出`);
        cluster.fork();
        });
        } else {
        http.createServer((req, res) => {
        res.writeHead(200);
        res.end(Math.random()+ , at pid:  + process.pid);
        }).listen(8080);
        console.log(`工作民主化 ${process.pid} 已启动`);
        }
    
    5. 总结
    node虽然是单缓存运转的,但他们能通过建立数个子民主化,来充分借助多核CPU天然资源,通过能监听民主化的一些事件,来感知每个民主化的运转状态,来提高他们项目整体的稳定性。
    我是蚊子,更多的内容还能关注我的公众号:蚊子的博客。
    蚊子的博客