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

是否可以使用节点工作线程执行数据库插入?

糜鸿风
2023-03-14

我最近读到了Node的“worker_threads”模块,该模块允许在多个线程中并行执行Javascript代码,这对于CPU密集型操作非常有用。(注意:这些不是Chrome在浏览器中制作的web Worker)

我正在构建一个功能,我需要在不阻塞浏览器的情况下执行大量的Postgres INSERT。

问题是:在我实例化worker的Javascript文件中,不允许导入任何内容,包括本机节点模块或像Knex这样的NPM库。js,这是进行数据库查询所必需的。我得到一个错误,上面写着:一旦文件被执行,就不能在模块外使用import语句。

我尝试将工作代码放在另一个文件中,顶部有一个import语句(相同的错误)。我尝试将Knex对象提供给workerData,但它无法克隆非本机JS对象。

我没主意了-如果我们不能导入任何NPM库,有人知道如何在工作线程中与数据库交互吗?!?!

// mainThread.js

const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');

import knex from 'knex'; // --> *** UNCAUGHT EXCEPTION: Cannot use import statement outside a module ***

if (isMainThread) {
  module.exports = async function runWorker (rowsToInsert = []) {
    return new Promise((resolve, reject) => {
      const worker = new Worker(__filename, { workerData: { rowsToInsert } });

      worker.on('message', (returningRows) => resolve(returningRows));
      worker.on('error', reject);
      worker.on('exit', (code) => {
        if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`));
      });
    });
  };
} else {
  const { rowsToInsert } = workerData;

  return knex('table').insert(rowsToInsert)
    .then((returningRows) => {
      parentPort.postMessage({ data: returningRows });
    });
}

以下是本网页的教程:https://blog.logrocket.com/use-cases-for-node-workers/

共有1个答案

韩鸿波
2023-03-14

这当然是可能的,但这是一个非常糟糕的主意。

数据库驱动程序已经是异步的,并且不阻塞JavaScript线程。按照您的建议将insert调用移动到一个单独的线程不仅不会获得任何性能提升,而且实际上会降低总体性能,因为线程间通信会带来开销:

  • 同步和消息传递不是免费的

一般来说,只有当你的JavaScript代码执行CPU密集型工作时才真正适合使用JS线程。节点文档在顶部说了同样多的话:

worker(线程)对于执行CPU密集型JavaScript操作非常有用。它们对I/O密集型工作没有多大帮助。节点。js内置的异步I/O操作比Worker更高效。

这意味着如果你要做很多解析、数学或类似的工作,那么在线程中完成这项工作可能是合适的。然而,简单地将数据从一个地方铲到另一个地方(即I/O)并不是线程的好候选人——毕竟,节点的设计在这种工作中是高效的。

您不会说您的rowsToInsert来自何处,但如果它来自HTTP请求,则使用线程是错误的。但是,如果您在服务器上解析CSV或JSON文件,那么在线程中进行解析可能是值得的,但重要的是线程完成所有工作(因此不需要在线程之间移动内存)。您向工作线程发布的消息应该是“处理位于/foo/bar.csv的文件”,然后工作线程执行其余操作。

您得到的错误与没有工作线程时得到的错误相同:您试图在常规的非模块JS文件中使用导入。或者将工作文件重命名为*. mjs,或者使用要求('kvision')代替。

node的ES模块文档详细介绍了importrequire的区别。

 类似资料:
  • 我正在eclipse中使用模拟器。我在模拟器中提取了大约2200条文本消息/data/data/com.android.providers.telephony/databases/mmssms。从emulator中读取db,并在其中看到文本消息 SQLiteDatabase smsDB=SQLiteDatabase.openDatabase("/data/data/com.android.prov

  • 我有我的kubernetes集群设置,我想从worker/minion节点检查节点,我们能从worker/minion节点运行kubectl吗?

  • 我正在尝试实现一个永久的工作流,它从阻塞直到消息被传递的活动开始(即Redis的)。一旦完成,我想异步启动一个新的工作流来进行某种处理并立即返回。 我尝试使用子工作流启动处理工作流。我观察到,我的父工作流在子工作流执行之前完成。除非我处理返回的未来,但我真的不想这样做。 正确的方法是什么?是否可以在工作流中启动新的常规工作流?此类操作是作为工作流的一部分还是在活动中实现? 提前谢谢你!

  • 问题内容: 在MySQL中,您可以像这样插入多行: 但是,尝试执行此类操作时出现错误。是否可以一次在SQLite数据库中插入多行?这样做的语法是什么? 问题答案: 更新 正如BrianCampbell在此处指出的那样,SQLite 3.7.11及更高版本现在支持原始文章的更简单语法 。但是,如果您希望在旧数据库之间实现最大兼容性,则所示的方法仍然适用。 原始答案 如果有特权,River的回答:您可

  • 问题内容: 我在jenkins中有一组构建作业,可以在3个构建节点中的任何一个中运行。它们都带有通用标签“ ubuntu_build”。每个节点都有许多执行程序,因此允许某些构建在计算机上并行执行。该安装程序运行正常,可以完成预期的工作,但我想对其进行改进。 3个构建节点具有不同的性能。第一个是第二个的两倍,第二个是第三个的两倍。(称它们为fast_node,regular_node,slow_n

  • 我正在运行一个spring boot应用程序,刚刚开始从Spring-Cloud-Netflix集成Hystrix。我正在使用@HystrixCommand包装一个用假客户机进行的服务到服务调用。 我的问题是,spring是否提供了将Spring Security上下文(和应用程序上下文)传递给运行Hystrix命令的Hystrix线程的方法?