什么时候使用线程池? [英] When is the thread pool used?

查看:549
本文介绍了什么时候使用线程池?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我了解了Node.js的工作原理:它有一个侦听器线程,接收一个事件,然后将它委派给一个工作池。工作线程在完成工作后通知侦听器,然后侦听器将响应返回给调用者。

So I have an understanding of how Node.js works: it has a single listener thread that receives an event and then delegates it to a worker pool. The worker thread notifies the listener once it completes the work, and the listener then returns the response to the caller.

我的问题是:如果我站起来一个HTTP服务器在Node.js中,并在我的路由路径事件之一(例如/ test / sleep)上调用sleep,整个系统停止。即使是单听者线程。但是我的理解是这个代码正在工作池上发生。

My question is this: if I stand up an HTTP server in Node.js and call sleep on one of my routed path events (such as "/test/sleep"), the whole system comes to a halt. Even the single listener thread. But my understanding was that this code is happening on the worker pool.

相比之下,当我使用Mongoose与MongoDB交谈时,DB读取是一个昂贵的I / O操作。节点似乎能够将工作委托给线程,并在完成后接收回调;从DB加载的时间似乎没有阻止系统。

Now, by contrast, when I use Mongoose to talk to MongoDB, DB reads are an expensive I/O operation. Node seems to be able to delegate the work to a thread and receive the callback when it completes; the time taken to load from the DB does not seem to block the system.

Node.js如何决定使用线程池线程与侦听器线程?为什么我不能写入睡眠并且只阻止线程池线程的事件代码?

How does Node.js decide to use a thread pool thread vs the listener thread? Why can't I write event code that sleeps and only blocks a thread pool thread?

推荐答案

您对节点工作原理的理解不正确但是这是一个常见的误解,因为现实情况实际上是相当复杂的,而且通常会被简化为一个简单的例子,比如节点是单线程,这样就能简化了事情。

Your understanding of how node works isn't correct... but it's a common misconception, because the reality of the situation is actually fairly complex, and typically boiled down to pithy little phrases like "node is single threaded" that over-simplify things.

目前,我们将通过集群 webworker-threads ,只是谈论典型的非线程节点。

For the moment, we'll ignore explicit multi-processing/multi-threading through cluster and webworker-threads, and just talk about typical non-threaded node.

节点运行在单个事件循环中。它是单线程,你只有一个线程。你写的所有javascript都是在这个循环中执行的,如果该代码发生了阻塞操作,那么它会阻塞整个循环,直到完成之后才会发生。这是您听到的节点的典型单线程性质。但是,这不是整个图片。

Node runs in a single event loop. It's single threaded, and you only ever get that one thread. All of the javascript you write executes in this loop, and if a blocking operation happens in that code, then it will block the entire loop and nothing else will happen until it finishes. This is the typically single threaded nature of node that you hear so much about. But, it's not the whole picture.

通常用C / C ++编写的某些功能和模块支持异步I / O。当您调用这些函数和方法时,它们在内部管理将调用传递给工作线程。例如,当您使用 fs 模块请求文件时, fs 模块将该调用传递给工作人员线程,并且该工作者等待其响应,然后它回到事件循环,而在此期间没有它。所有这一切都从您,节点开发人员抽象出来,其中一些通过使用 libuv

Certain functions and modules, usually written in C/C++, support asynchronous I/O. When you call these functions and methods, they internally manage passing the call on to a worker thread. For instance, when you use the fs module to request a file, the fs module passes that call on to a worker thread, and that worker waits for its response, which it then presents back to the event loop that has been churning on without it in the meantime. All of this is abstracted away from you, the node developer, and some of it is abstracted away from the module developers through the use of libuv.

如Denis Dollfus在评论中所指出的(从这个答案到一个类似的问题),libuv用来实现异步I / O的策略并不总是线程池,具体在在这个时候,似乎使用了一个不同的策略, http 模块的情况。为了我们这里的目的,主要重要的是要注意异步上下文是如何实现的(通过使用libuv),并且由libuv维护的线程池是该库提供的实现异步的多种策略之一。

As pointed out by Denis Dollfus in the comments (from this answer to a similar question), the strategy used by libuv to achieve asynchronous I/O is not always a thread pool, specifically in the case of the http module a different strategy appears to be used at this time. For our purposes here it's mainly important to note how the asynchronous context is achieved (by using libuv) and that the thread pool maintained by libuv is one of multiple strategies offered by that library to achieve asynchronicity.

在大部分相关的切线上,对节点如何实现异步性以及一些相关的潜在问题以及如何处理它们有更深入的分析,在这个优秀的文章。其中大部分内容都以上述内容为基础,但另外指出:

On a mostly related tangent, there is a much deeper analysis of how node achieves asynchronicity, and some related potential problems and how to deal with them, in this excellent article. Most of it expands on what I've written above, but additionally it points out:


  • 您的项目中包含的任何外部模块使用本机C ++和libuv可能使用线程池(认为:数据库访问)

  • libuv的默认线程池大小为4,并使用队列来管理对线程池 - 结果是,如果您有5个长时间运行的DB查询同时进行,则其中一个(以及依赖于线程池的任何其他异步操作)将等待这些查询在它们甚至之前完成开始

  • 您可以通过增加线程池的大小通过 UV_THREADPOOL_SIZE 环境变量来缓解这一点,只要你这样做在线程池需要和创建之前: process.env.UV_THREADPOOL_SIZE = 10;

  • Any external module that you include in your project that makes use of native C++ and libuv is likely to use the thread pool (think: database access)
  • libuv has a default thread pool size of 4, and uses a queue to manage access to the thread pool - the upshot is that if you have 5 long-running DB queries all going at the same time, one of them (and any other asynchronous action that relies on the thread pool) will be waiting for those queries to finish before they even get started
  • You can mitigate this by increasing the size of the thread pool through the UV_THREADPOOL_SIZE environment variable, so long as you do it before the thread pool is required and created: process.env.UV_THREADPOOL_SIZE = 10;

如果要在节点中传统的多处理或多线程,可以让我通过内置集群模块或各种其他模块(如上述 webworker-threads ),或者您可以伪造它通过实现一些方法来重组您的工作,并手动使用 setTimeout setImmediate 进程。 nextTick 暂停工作,并在稍后的循环中继续,让其他进程完成(但不推荐)。

If you want traditional multi-processing or multi-threading in node, you can get it through the built in cluster module or various other modules such as the aforementioned webworker-threads, or you can fake it by implementing some way of chunking up your work and manually using setTimeout or setImmediate or process.nextTick to pause your work and continue it in a later loop to let other processes complete (but that's not recommended).

请注意,如果您在JavaScript中编写长时间运行/阻止代码,您可能会犯错误。其他语言的效能会更高。

Please note, if you're writing long running/blocking code in javascript, you're probably making a mistake. Other languages will perform much more efficiently.

这篇关于什么时候使用线程池?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆