当前位置: 首页 > 知识库问答 >
问题:

哪个更适合node.js?光纤上的并发任务?Web工作人员?还是线程?

锺离辰沛
2023-03-14

我被节点绊倒了。一段时间前的js,非常喜欢它。但很快我发现它严重缺乏执行CPU密集型任务的能力。于是,我开始在谷歌上搜索,找到了解决问题的答案:光纤、网络工作者和线程(thread-a-gogo)。现在使用哪一个是一个困惑,其中一个肯定需要使用-毕竟拥有一个只擅长IO而不擅长其他功能的服务器的目的是什么?需要建议!

更新:

我在想一个迟到的方法;只是需要一些建议。现在,我想到的是:让我们有一些线程(使用thread_a_gogo或网络工作者)。现在,当我们需要更多线程时,我们可以创建更多线程。但是创建过程会有一些限制。(系统没有暗示,但可能是因为开销)。现在,当我们超过限制时,我们可以分叉一个新节点,并开始在其上创建线程。这样,它就可以一直持续到我们达到某个限制(毕竟,进程也有很大的开销)。当达到这个限制时,我们开始排队任务。每当一个线程空闲时,它就会被分配一个新任务。这样,它就可以顺利进行。

所以,这就是我的想法。这个主意好吗?我对所有这些过程和线程的东西都有点陌生,所以在这方面没有任何专业知识。请分享你的观点。

谢谢。:)

共有1个答案

汪志业
2023-03-14

Node有一个完全不同的范式,一旦它被正确捕获,就更容易看到这种不同的解决问题的方式。您永远不需要在Node应用程序(1)中使用多个线程,因为您有不同的方式来做同样的事情。您创建多个进程;但它与Apache Web Server的Prefork mpm的做法非常不同。

现在,让我们认为我们只有一个CPU核心,我们将开发一个应用程序(以节点的方式)来做一些工作。我们的工作是逐字节处理一个运行在其内容上的大文件。对于我们的软件来说,最好的方法是从文件的开头开始工作,逐字节跟踪到最后。

--嘿,哈桑,我想你要么是个新手,要么是我祖父时代的老派!!!为什么不创建一些线程并使其更快呢?

--哦,我们只有一个CPU核心。

--那又怎样?创建一些线程,让它更快!

--它不是那样工作的。如果我创建线程,我会使它变慢。因为在线程之间切换时,我会给系统增加很多开销,试图给它们一点时间,在我的进程中,尝试在这些线程之间进行通信。除了所有这些事实之外,我还必须考虑如何将单个工作划分为多个可以并行完成的部分。

-好吧好吧,我看你很穷。让我们用我的电脑,它有32个内核!

--哇,你真棒,我亲爱的朋友,非常感谢你。我很感激!

然后我们回去工作。多亏了我们的有钱朋友,现在我们有了32个cpu核。我们必须遵守的规则刚刚改变。现在,我们想利用我们得到的所有财富。

要使用多核,我们需要找到一种方法,将我们的工作划分为可以并行处理的部分。如果不是节点,我们将为此使用线程;32个线程,每个cpu核一个线程。然而,由于我们有节点,我们将创建32个节点进程。

线程可以是节点进程的一种很好的替代方法,甚至可能是更好的方法;但是,只有在一种特定的工作中,工作已经定义,并且我们可以完全控制如何处理它。除此之外,对于任何其他类型的问题,如果作业来自外部,而我们无法控制,并且希望尽快回答,那么Node的方式无疑是优越的。

--嘿,哈桑,你还在用单线程吗?你怎么了,伙计?我刚刚给你提供了你想要的。你再也没有借口了。创建线程,使其运行更快。

-我已经将工作分成多个部分,每个过程都将并行处理其中一个部分。

--你为什么不创建线程?

--对不起,我认为它不可用。如果你愿意,你可以带上你的电脑?

--不,好吧,我很酷,我只是不明白你为什么不使用线程?

--谢谢你的电脑。:)我已经将工作划分为多个部分,并创建了并行处理这些部分的流程。所有CPU核心都将得到充分利用。我可以用线程而不是进程来实现这一点;但Node有这种方式,我的老板ParthThakkar希望我使用Node。

--好的,如果你需要另一台电脑,请告诉我p

如果我创建33个进程,而不是32个,操作系统的调度程序将暂停一个线程,启动另一个,在一些周期后暂停它,再次启动另一个...这是不必要的开销。我不想要它。事实上,在一个有32个内核的系统上,我甚至不想完全创建32个进程,31个可以更好。因为不仅仅是我的应用程序可以在这个系统上工作。为其他事情留一点空间可能很好,尤其是如果我们有32个房间。

我相信我们现在在充分利用处理器来执行CPU密集型任务方面意见一致。

--嗯,哈桑,很抱歉我有点嘲笑你。我相信我现在更了解你了。但是,我仍然需要解释一下:运行数百个线程的嗡嗡声是什么?我到处都读到,线程的创建速度要比分叉进程快得多,而且很愚蠢?您分叉进程而不是线程,并且您认为这是使用节点可以获得的最高值。那么Node是否不适合这种工作?

--别担心,我也很酷。每个人都会说这些话,所以我想我已经习惯了听这些话。

--所以呢?节点不适合此操作?

--节点在这方面非常好,即使线程也可以很好。线程/进程创建开销;对于你经常重复的事情,每毫秒都很重要。然而,我只创建了32个进程,只需要很少的时间。它只会发生一次。这不会有任何区别。

--那么,我想什么时候创建数千个线程呢?

--您永远不想创建数千个线程。然而,在一个正在做来自外部的工作的系统上,比如处理HTTP请求的web服务器;如果您为每个请求使用一个线程,那么您将创建很多线程,其中很多。

--但节点不同?正当

--是的,没错。这就是Node真正闪耀的地方。就像线程比进程轻得多一样,函数调用也比线程轻得多。节点调用函数,而不是创建线程。在web服务器的示例中,每个传入的请求都会导致函数调用。

--嗯,很有趣;但如果不使用多个线程,则只能同时运行一个函数。当大量请求同时到达web服务器时,这如何工作?

--关于函数如何运行,你是完全正确的,一次一个,永远不要两个并行。我的意思是在单个进程中,一次只运行一个范围的代码。操作系统调度程序不会来暂停这个函数并切换到另一个,除非它暂停进程以给另一个进程留出时间,而不是我们进程中的另一个线程。(2)

--那么一个进程如何一次处理2个请求呢?

--只要我们的系统有足够的资源(RAM、网络等),一个进程一次可以处理数万个请求。这些函数的运行方式是关键区别。

--嗯,我现在应该兴奋吗?

--可能:)节点在队列上运行循环。在此队列中是我们的作业,即我们开始处理传入请求的调用。这里最重要的一点是我们设计函数运行的方式。我们没有开始处理请求并让调用者等到完成任务,而是在完成了可接受的工作量后快速结束函数。当我们需要等待另一个组件完成一些工作并返回一个值时,我们不需要等待,只需完成将其余工作添加到队列中的函数即可。

--听起来太复杂了?

不,不,我可能听起来很复杂;但是这个系统本身非常简单,而且非常有意义。

现在,我想停止引用这两个开发人员之间的对话,在最后一个简单的示例之后完成我的回答,说明这些函数是如何工作的。

通过这种方式,我们正在做OS Scheduler通常会做的事情。我们在某个时候暂停我们的工作,让其他函数调用(如多线程环境中的其他线程)运行,直到我们再次轮到我们。这比将工作留给OS Scheduler要好得多,后者试图只给系统上的每个线程时间。我们比OS Scheduler更清楚我们在做什么,并且我们应该在应该停止时停止。

下面是一个简单的示例,我们打开一个文件并读取它以对数据进行一些工作。

同步方式:

Open File
Repeat This:    
    Read Some
    Do the work

异步方式:

Open File and Do this when it is ready: // Our function returns
    Repeat this:
        Read Some and when it is ready: // Returns again
            Do some work

如您所见,我们的函数要求系统打开一个文件,而不是等待它被打开。它通过在文件准备好后提供下一步来完成自己。当我们返回时,Node在队列上运行其他函数调用。在运行所有函数后,事件循环移动到下一个回合...

总之,Node与多线程开发具有完全不同的范式;但这并不意味着它缺少东西。对于同步作业(我们可以在其中决定处理的顺序和方式),它与多线程并行性一样有效。对于一个来自外部的作业,比如对服务器的请求,它简直就是优越的。

(1) 除非您正在用其他语言(如C/C)构建库,在这种情况下,您仍然不会创建用于分割作业的线程。对于这种工作,您有两个线程,其中一个线程将继续与节点通信,而另一个线程将执行实际工作。

(2) 事实上,每个节点进程都有多个线程,原因与我在第一个脚注中提到的相同。然而,这与1000个线程做类似的工作不同。这些额外的线程用于接受IO事件和处理进程间消息传递。

@Mark,谢谢你的建设性批评。在Node的范例中,你永远不应该有需要太长时间来处理的函数,除非队列中的所有其他调用都被设计为一个接一个地运行。在计算成本高昂的任务的情况下,如果我们完整地查看图片,我们会发现这不是一个“我们应该使用线程还是进程?”的问题,而是一个“我们如何才能以良好平衡的方式将这些任务划分为子任务,我们可以使用系统上的多个CPU内核并行运行它们?”假设我们将在一个具有8个内核的系统上处理400个视频文件。如果我们想一次处理一个文件,那么我们需要一个系统来处理同一个文件的不同部分,在这种情况下,也许多线程单进程系统会更容易构建,甚至更高效。我们仍然可以通过运行多个进程并在需要状态共享/通信时在它们之间传递消息来使用Node。正如我之前所说,在这种任务中,使用Node的多进程方法与多线程方法一样;但仅此而已。同样,正如我之前所说,Node闪耀的情况是当我们将这些任务作为来自多个来源的系统输入时,因为与每个连接的线程或每个连接的进程系统相比,Node中并发保持许多连接要轻得多。

至于设置超时(…,0)调用;有时,可能需要在耗时的任务期间Rest一下,以允许队列中的调用共享处理。以不同的方式划分任务可以避免这些问题;但这并不是真正的黑客行为,它只是事件队列的工作方式。此外,使用过程。nextTick(下一步)对于这一目标来说要好得多,因为当您使用setTimeout(设置超时)时,在处理过程中需要计算和检查经过的时间。下一步就是我们真正想要的:“嘿,任务,回到队列的末尾,你已经用完了你的份额!”

 类似资料:
  • 问题内容: 我前一段时间偶然发现了node.js,非常喜欢。但是很快我发现它严重缺乏执行CPU密集型任务的能力。因此,我开始进行谷歌搜索,并找到了解决这些问题的答案:光纤,Webworkers和线程(thread- a-gogo)。现在使用哪个是一个混乱的问题,肯定要使用其中一个-毕竟,拥有一台只擅长IO且无其他优点的服务器的目的是什么?需要建议! 更新: 我在想一种落后的方法。只是需要建议。现在

  • 问题内容: 现在,每当我要将node.js服务器部署到生产服务器时,都需要更改与数据库和外部API的各种连接的所有IP / DNS /用户名/密码。 这个过程很烦人,有没有办法验证当前正在运行的node.js实例是否在cloud9ide或实际上是我生产的快乐智能机中? 如果能够(在运行的代码中)确定node.js实例在哪台服务器上运行,我将添加一个条件,将值设置为prod或dev。 谢谢 问题答案

  • 问题内容: 此问题适用于Win10上的Python 3.6.3,bs4和Selenium 3.8。 我正在尝试使用动态内容抓取页面。我试图抓取的是数字和文本(例如,来自http://www.oddsportal.com)。以我的理解,使用请求+美丽的汤将无法完成任务,因为动态内容将被隐藏。因此,我必须使用其他工具,例如selenium webdriver。 然后,假设我仍将使用Selenium W

  • 本文向大家介绍光纤和铜线的比较,包括了光纤和铜线的比较的使用技巧和注意事项,需要的朋友参考一下 由于与传统的铜线相比具有许多优点,因此光缆的使用量正在增加。但是,其用法也有一些缺点。 光纤电缆比铜线的优势 光纤电缆传输数据的速度远高于铜线。这是因为光的速度大于电子的速度。 与铜线的10 Gbps带宽相比,光缆的带宽更大,超过60 Tbps。 光纤电缆的衰减非常低。中继器仅需每50公里添加一次,而铜

  • 我在分布式模式下使用 Kafka Connect。我现在多次观察到的一个奇怪行为是,一段时间后(可能是几个小时,可能是几天),似乎发生了平衡错误:相同的任务被分配给多个工人。因此,它们同时运行,并且根据连接器的性质,失败或产生“不可预测”的输出。 我能够用来重现该行为的最简单配置是:两个 Kafka Connect 工作线程,两个连接器,每个连接器只有一个任务。Kafka Connect 已部署到

  • 问题内容: 如果您的目标是测试MySQL列中是否存在字符串(类型为’varchar’,’text’,’blob’等),那么以下哪一项是更快/更有效/更好地使用,为什么? 或者,还有其他方法可以胜任这些方法吗? 与 问题答案: 正如kibibu在上述评论中指出的,FULLTEXT搜索绝对会更快。 但是 : 在我的测试中,它们的表现完全相同。它们都不区分大小写,并且通常会执行全表扫描,这在处理高性能M