Nodejs密集型CPU解决方案

首先说一下nodejs单线程的优势:

高性能,与php相比,避免了频繁创建切换线程的开销,执行更加迅速,资源占用小。

线程安全,不用担心同一变量被多线程读写,造成程序崩溃。

单线程的异步和非阻塞,其实 nodejs底层访问I/O还是多线程的,阻塞/非阻塞与异步/同步是两个不同的概念,同步不代表阻塞,但是阻塞肯定就是同步;有点儿绕口,请听我举例,我去食堂打饭,我选择了A套餐,然后工作人员帮我去配餐,如果我就站在旁边,等待工作人员给我配餐,这种情况就称之为同步;若工作人员帮我配餐的同时,排在我后面的人就开始点餐,这样整个食堂的点餐服务并没有因为我在等待A套餐而停止,这种情况就称之为非阻塞。这个例子就简单说明了同步但非阻塞的情况。再如果我在等待配餐的时候去买饮料,等听到叫号再回去拿套餐,此时我的饮料也已经买好,这样我在等待配餐的同时还执行了买饮料的任务,叫号就等于执行了回调,就是异步非阻塞了。如果我在买饮料的时候,已经叫我的号让我去拿套餐,可是我等了好久才拿到饮料,所以我可能在大厅叫我的餐号之后很久才拿到A套餐,这也就是单线程的阻塞情况。

多线程:

线程是cpu调度的一个基本单位,一个cpu只能执行一个线程任务。

nodejs也可以执行多行程任务,例如引用TAGG/TAGG2模块,大家可以看一下我上一篇文章,里面有具体的使用方法。但是不论是tagg/tagg2都是利用pthread库和V8::Isolate类来实现js多线程功能的,根据规则我们在线程里执行的函数无法使用nodejs的核心api,例如fs,crypto模块,所以还是有很大的局限性。

多进程:

在支持html5的浏览器里,我们可以使用webworker来将一些耗时的计算丢入worker进程中执行,这样主进程就不会阻塞,用户也不会有卡顿的感觉。

这里我们需要利用nodejs的child_process模块,child_process提供了fork方法,可以启动一个nodejs文件,将它视作worker进程,worker 工作完毕后,会把结果send给主进程,然后worker自动退出,这样我们就利用了多进程解决了主线程阻塞的问题。

var express = require(‘express‘);
var fork = require(‘child_process‘).fork;
var app = express();
app.get(‘/‘, function(req, res){
  var worker = fork(‘./work.js‘) //创建一个工作进程
  worker.on(‘message‘, function(m) {//接收工作进程计算结果
          if(‘object‘ === typeof m && m.type === ‘fibo‘){
                   worker.kill();//发送杀死进程的信号
                   res.send(m.result.toString());//将结果返回客户端
          }
  });
  worker.send({type:‘fibo‘,num:~~req.query.n || 1});
  //发送给工作进程计算fibo的数量
});
app.listen(7878);

我们通过express监听7878端口,对每个用户的请求都会去fork一个子进程,通过调用worker.send方法将参数n传递给子进程,同时监听子进程发送消息的message事件,将结果响应给客户端。

下面是被fork的work.js文件内容:

var fibo = function fibo (n) {//定义算法
   return n > 1 ? fibo(n - 1) + fibo(n - 2) : 1;
}
process.on(‘message‘, function(m) {
//接收主进程发送过来的消息
          if(typeof m === ‘object‘ && m.type === ‘fibo‘){
                  var num = fibo(~~m.num);
                  //计算jibo
                  process.send({type: ‘fibo‘,result:num})
                  //计算完毕返回结果
          }
});
process.on(‘SIGHUP‘, function() {
        process.exit();//收到kill信息,进程退出
});

我们先定义函数fibo用来计算斐波那契数组,然后监听了主线程发来的消息,计算完毕之后将结果send到主线程。同时还监听process的SIGHUP事件,触发此事件就进程退出。

这里我们有一点需要注意,主线程的kill方法并不是真的使子进程退出,而是会触发子进程的SIGHUP事件,真正的退出还是依靠process.exit()。

总结:

使用child_process模块的fork方法确实可以让我们很好的解决单线程对cpu密集型任务的阻塞问题,同时又没有tagg包那样无法使用Node.js核心api的限制。

单线程异步的Node.js不代表不会阻塞,在主线程做过多的任务可能会导致主线程的卡死,影响整个程序的性能,所以我们要非常小心的处理大量的循环,字符串拼接和浮点运算等cpu密集型任务,合理的利用各种技术把任务丢给子线程或子进程去完成,保持Node.js主线程的畅通。

线程/进程的使用并不是没有开销的,尽可能减少创建和销毁线程/进程的次数,可以提升我们系统整体的性能和出错的概率。

时间: 2025-01-02 14:25:27

Nodejs密集型CPU解决方案的相关文章

Linux下高cpu解决方案

昨天搞定了一个十万火急的issue,客户抱怨产品升级后系统会变慢和CPU使用率相当高,客户脾气很大,声称不尽快解决这个问题就退货,弄得我们 R&D压力很大,解决这个issue的任务分给了我,客户是南非的一个公司,由于时差问题,我只好在家远程解决问题,晚上8点半用 gotomeeting远程到客户电脑查看我们的系统,折腾了四个多小时,终于在凌晨时reproduce了这个high CPU,赶紧抓Log,用wireshark抓包,用gcore,gstack,strace和top保存了系统的相关输出.在

Linux下高cpu解决方案(转载)

昨天搞定了一个十万火急的issue,客户抱怨产品升级后系统会变慢和CPU使用率相当高,客户脾气很大,声称不尽快解决这个问题就退货,弄得我们 R&D压力很大,解决这个issue的任务分给了我,客户是南非的一个公司,由于时差问题,我只好在家远程解决问题,晚上8点半用 gotomeeting远程到客户电脑查看我们的系统,折腾了四个多小时,终于在凌晨时reproduce了这个high CPU,赶紧抓Log,用wireshark抓包,用gcore,gstack,strace和top保存了系统的相关输出.在

VsCode的rg.exe占用Cpu解决方案

选择   文件->首选项->设置 然后使用检索 search.followSymlinks 将其勾选去掉,亲测有效,如果版本不同,可以检索到当前选项 将其修改为false即可!! 原文地址:https://www.cnblogs.com/dream0530/p/9903362.html

[转载]服务器管理模块forever——Nodejs中间件系列

从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发.Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎.chrome浏览器就基于V8,同时打开20-30个网页都很流畅.Nodejs标准的web开发框架Express,可以帮助我们迅速建立web站点,比起PHP的开发效率更高,而且学习曲线更低.非常适合小型网站,个性化网站,我们自己的Geek网站!! 关于作者 张丹(Conan), 程序员Java,R,PHP,Java

墙上时钟时间 ,用户cpu时间 ,系统cpu时间

一. 墙上时钟时间 ,用户cpu时间 ,系统cpu时间定义与联系 时钟时间(墙上时钟时间wall clock time):从进程从开始运行到结束,时钟走过的时间,这其中包含了进程在阻塞和等待状态的时间. 用户CPU时间:就是用户的进程获得了CPU资源以后,在用户态执行的时间. 系统CPU时间:用户进程获得了CPU资源以后,在内核态的执行时间. 进程的三种状态为阻塞.就绪.运行. 时钟时间 = 阻塞时间 + 就绪时间 +运行时间 用户CPU时间 = 运行状态下用户空间的时间 系统CPU时间 =  

线程池大小设置,CPU的核心数、线程数的关系和区别,同步与堵塞完全是两码事

线程池应该设置多少线程合适,怎么样估算出来.最近接触到一些相关资料,现作如下总结. 最开始接触线程池的时候,没有想到就仅仅是设置一个线程池的大小居然还有这么多的学问,汗颜啊. 首先,需要考虑到线程池所进行的工作的性质: IO密集型 CPU密集型 简单的分析来看,如果是CPU密集型的任务,我们应该设置数目较小的线程数,比如CPU数目加1.如果是IO密集型的任务,则应该设置可能多的线程数,由于IO操作不占用CPU,所以,不能让CPU闲下来.当然,如果线程数目太多,那么线程切换所带来的开销又会对系统的

优酷、YouTube、Twitter及JustinTV视频网站架构设计

优酷视频网站架构 一.网站基本数据概览 据2010年统计,优酷网日均独立访问人数(uv)达到了8900万,日均访问量(pv)更是达到了17亿,优酷凭借这一数据成为google榜单中国内视频网站排名最高的厂商.     硬件方面,优酷网引进的戴尔服务器主要以 PowerEdge 1950与PowerEdge 860为主,存储阵列以戴尔MD1000为主,2007的数据表明,优酷网已有1000多台服务器遍布在全国各大省市,现在应该更多了吧. 二.网站前端框架 从一开始,优酷网就自建了一套CMS来解决前

MIS性能优化常见问题与方案(辅助项目组性能优化的总结贴)

最近帮忙公司的几个项目组进行了不同方面的性能优化,发现几个项目都出现了一些共性的问题.这里写一篇文章,总结一下这几类问题,以及其对应的解决方案.方便其它项目组参考.   常见问题一:打开页面非常慢,有的项目打开一个页面竟然要 20 多秒. 优化步骤: 降低每一个页面的请求数:使用浏览器跟踪打开页面后所有的请求,并逐一排查,把没有必要向服务端发起的请求优化掉,减少 Round Trip 次数. 针对每一个请求进行优化:对请求逐一排查,看看分别是哪些请求占用了较多的时间. 如果该请求是 JS 文件,

网站框构分析 一

Facebook用户量大的问题由它的分布式缓存系统主要解决,剩下的自然是开源的mysql更合适了 <img src="https://pic2.zhimg.com/c6d403f1e89fa46c5567e0cbcbb024ad_b.jpg" data-rawwidth="1310" data-rawheight="333" class="origin_image zh-lightbox-thumb" width