【问题标题】:Why do we need connection pool in node.js when node is single threaded?当节点是单线程时,为什么我们需要 node.js 中的连接池?
【发布时间】:2017-12-11 22:54:39
【问题描述】:

Node.js 是单线程的。 Javascript V8 引擎和一些内部库是多线程的。对于 I/O,节点将 I/O 委托给可能是多线程的操作系统。

如果我的 node.js 应用程序正在连接到 redis 或 ,sql/mariadb 服务器,我假设我不需要 redis 或 mysql 的连接池。

作为开发人员,我创建了 1 个 redis 或 mysql 连接并重用它来发送/获取数据。当数据到达时,节点会调用回调来处理数据。

我了解 Java/.NET 的连接池,但它们是多线程的,因此 Java/.NET 中的连接池具有明显的优势。

我的问题是:当 node 是单线程时,为什么我们需要 node.js 中的连接池?它有什么好处吗? Node 会不会利用底层 OS 和 javascript 引擎的多线程特性,而开发者不必这样做?

谢谢

【问题讨论】:

    标签: node.js redis pooling


    【解决方案1】:

    节点运行你的代码单线程。但是,Node.js 实际上有一个线程池可供您使用,您的代码无法访问该线程池。线程机制通过libuv 实现。深入了解libuv book 并解释 libuv 的内部工作原理。

    基本上,您的代码在事件循环(单线程)的上下文中运行。然后将任何异步工作从池中卸载到可用线程,并且事件循环将仅轮询,直到该异步工作由其中一个线程完成。完成后,将调用由您的异步调用注册的回调函数,并将在事件循环的下一个I/O Callback Phase 期间进行处理。您可以在 Node.js docs 中阅读有关事件循环及其阶段的更多信息。

    使用这种事件循环样式构建应用程序的好处之一是抽象了通常与多线程应用程序相关的关键部分编码(互斥体、信号量等)。

    【讨论】:

    • 感谢您的评论和链接。那么使用redis连接池或mysql连接池有什么好处,因为节点将使用其内部线程池进行I/O?
    • 当然,这些连接池仍然允许您拥有多个共享且可用的连接,而不是等待打开新连接的开销。这是正确实施时的优化。
    • @Avneet 同样,来自 redis 和 mysql 的那些线程池仍然像您的代码一样使用 libuv 运行。所以这些包没有创建一个单独的池。你的代码是用这些包实现的,你的代码是单线程运行的,这些池只提供开放连接,等待工作。无需等待连接打开。
    • 感谢您的解释...如果我们重用同一个连接而不关闭它会怎样。对于每个请求,相同的 1 个连接将用于 redis。所以我们不会有每次打开新连接的开销。
    • @Avneet 是的,这可行,但请注意,客户端和服务器端的连接只能完成这么多的工作。一般来说,连接池被视为一种性能优化,并且易于使用,因为大多数 DB 驱动程序/包都抽象了它们的实现,因此您可以只处理请求,而无需在代码中显式管理连接。
    【解决方案2】:

    您需要连接池,因为即使是单个线程也可以容纳多个“阻塞”数据库连接(假设此处为 RDBMS)。如果没有连接池,您的应用程序将为每个额外的数据库请求从头开始创建每个连接,即使在像 Node.js 这样的异步/非阻塞系统中也是如此。

    示例:

    request 1 - insert user  -- wait for response (assume it's 5 secs)
    request 2 - insert invoice - wait for response (assume it's 3 secs)
    request 3 - insert another invoice
    

    请注意,请求 3 会立即处理,无需等待请求 1 和 2 完成。在这个单线程中,我们已经使用了三个资源来连接数据库。想象一下,每次需要数据库操作时都必须创建每一个。从连接池中抓取一个会快得多!

    【讨论】:

      猜你喜欢
      • 2013-04-12
      • 1970-01-01
      • 1970-01-01
      • 2020-11-21
      • 2013-10-01
      • 2018-06-22
      • 1970-01-01
      • 2015-01-17
      • 2016-06-12
      相关资源
      最近更新 更多