Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 354|回复: 0

node.js入门 - 7.异常处理与多进程开发

[复制链接]
  • TA的每日心情
    奋斗
    4 天前
  • 签到天数: 802 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726006
    发表于 2021-5-27 16:43:37 | 显示全部楼层 |阅读模式

      1.异常处理

      在我们进行代码开发的时候,异常的捕获处理是一个不能忽略的话题,那么怎么才能捕获到node中的异常呢?或许你最先想到的是try/catch的使用,如下例:

    var http = require('http')
    var opts = {
      host: 'sfnsdkfjdsnk.com',
      port: 80,
      path: '/'
    }
    try {
      http.get(opts, function(res) {
        console.log('Will this get called?')
      })
    }
    catch (e) {
      console.log('Will we catch an error?')
    }
    

      在回答上面代码是否能完成任务之前,我们先做个分析。node采用的是非堵塞的I/O操作,在上面的代码中我调用http.get(),向他传入了一个回调函数,当I/O操作完成的时候回调函数将会被触发。然而,http.get()触发一个回调函数之后就会成功的返回,在执行GET操作过程中的异常是不能被try/catch捕获到的。因为在node中产生了异常向外报告的时候,我们已经离开了javascript的调用堆栈,javascript已经去处理别的事件去了。说的简单点,上面的try/catch是为http.get()准备的,不是为他里面的function(res){}回调函数准备的。然而http.get()是不会发生异常的,他只负责触发function(res){}回调函数,但是回调函数的执行域已经超出了try/catch。

      那么有办法捕获到回调函数里面的异常吗?答案是使用异常事件。

    var http = require('http')
    var opts = {
      host: 'dskjvnfskcsjsdkcds.net',
      port: 80,
      path: '/'
    }
    var req = http.get(opts, function(res) {
      console.log('This will never get called')
    })
    req.on('error', function(e) {
      console.log('Got that pesky error trapped')
    })
    

      

      2.多进程开发

      在前面的课程中,我们已经了解到node是单线程的,他只使用一个cpu去工作。但是现在多核的处理器那么多,合理的利用多个cpu工作可以大大提高程序的效率,要是不能有效利用服务器资源那不是很可惜。那有没有办法让node也利用服务器上的多个cpu呢,答案是可以使用集群(cluster)技术把多个工作委托给多个子进程去做。node会在其他进程创建当前程序的拷贝。每一个子进程都有些特殊的能力,比如可以和其他进程共享一个socket连接。在使用集群技术的时候,需要创建一个主进程和多个子进程,主进程不负责对具体请求的处理,他只负责工作任务的分配,具体的工作都是交给子进程去处理的。

      让我们来看一个例子:

    var cluster = require('cluster');
    var http = require('http');
    var numCPUs = require('os').cpus().length;
    if (cluster.isMaster) {
      // Fork workers.
      for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
      }
      cluster.on('death', function(worker) {
        console.log('worker ' + worker.pid + ' died');
        cluster.fork();   }); } else {   // Worker processes have a http server.   http.Server(function(req, res) {     res.writeHead(200);     res.end("hello world\n");   }).listen(8000); }

      通过上面代码,我们使用os模块获取cpu的个数,使用cluster模块创建一个master进程,根据cpu的个数使用cluster.fork()创建相应个数的工作进程,工作进程共享同一个http服务。一个工作进程的错误,不会影响其他工作进程的正常工作。我们使用cluster.on('death', function(worker){},检测工作进程的消亡,一个工作进程消亡以后创建一个全新的工作进程。

     

      在学会使用cluster创建主进程和工作进程之后,我们来学习如何实现他们之间的通信。看下例:

    var cluster = require('cluster');
    var http = require('http');
    var numCPUs = require('os').cpus().length;
    var rssWarn = (12 * 1024 * 1024), heapWarn = (10 * 1024 * 1024);
    if(cluster.isMaster) {
      for(var i=0; i<numCPUs; i++) {
        var worker = cluster.fork();
        worker.on('message', function(m) {
          if (m.memory) {
            if(m.memory.rss > rssWarn) {
              console.log('Worker ' + m.process + ' using too much memory.')
            }
          }
        })
      }
    } else {
      //Server
      http.Server(function(req,res) {
        res.writeHead(200);
        res.end('hello world\n')
      }).listen(8000)
      //Report stats once a second   setInterval(function report(){     process.send({memory: process.memoryUsage(), process: process.pid});   }, 1000) }

      主进程中,使用worker.on('message', function(m) {...})来监听来自工作进程传递的信息。工作进程使用setInterval函数间隔性的调用process.send(),向主进程汇报之间的情况。

       如果一些工作进程耗时太长,或者已经没有响应,我们如何关闭它呢,来看下例:

    var cluster = require('cluster');
    var http = require('http');
    var numCPUs = require('os').cpus().length;
    var rssWarn = (50 * 1024 * 1024), heapWarn = (50 * 1024 * 1024);
    var workers = {}
    if(cluster.isMaster) {
      for(var i=0; i<numCPUs; i++) {
        createWorker()
      }
      setInterval(function() {
        var time = new Date().getTime()
        for(pid in workers) {
          if(workers.hasOwnProperty(pid) && workers[pid].lastCb + 5000 < time) {
            console.log('Long running worker ' + pid + ' killed')
            workers[pid].worker.kill()
            delete workers[pid]
            createWorker()
          }
        }
      }, 1000)
    } else {
      //Server
      http.Server(function(req,res) {
        //mess up 1 in 200 reqs
        if (Math.floor(Math.random() * 200) === 4) {
          console.log('Stopped ' + process.pid + ' from ever finishing')
          while(true) { continue }
        }
        res.writeHead(200);
        res.end('hello world from ' + process.pid + '\n')
      }).listen(8000)
      //Report stats once a second   setInterval(function report(){     process.send({cmd: "reportMem", memory: process.memoryUsage(), process: process.pid})   }, 1000) }
    function createWorker() {   var worker = cluster.fork()   console.log('Created worker: ' + worker.pid)   //allow boot time   workers[worker.pid] = {worker:worker, lastCb: new Date().getTime()-1000}   worker.on('message', function(m) {     if(m.cmd === "reportMem") {       workers[m.process].lastCb = new Date().getTime()       if(m.memory.rss > rssWarn) {         console.log('Worker ' + m.process + ' using too much memory.')       }     }   }) }

      答案就是需要我们在主线程中去关闭它。

      上面的例子中,我们故意用下面的代码

    if (Math.floor(Math.random() * 200) === 4) {
        console.log('Stopped ' + process.pid + ' from ever finishing')
        while(true) { continue }
    }
    

    让程序有机会堵塞工作进程,这样主进程就有机会得到一个超时的工作进程,从而关闭它了。

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-11-15 13:03 , Processed in 0.159168 second(s), 27 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表