简体   繁体   English

如何在 Sapper 上使用 worker_threads?

[英]How to use worker_threads on Sapper?

I'm trying to start a thread on Sapper using the nodejs worker_threads , but it looks like it's trying to start also another instance of Polka.我正在尝试使用 nodejs worker_threads在 Sapper 上启动一个线程,但看起来它也在尝试启动另一个 Polka 实例。

You can find my code on this repo , but it basically has a route to http://localhost:3000/worker that fetches the server-side worker\run.js .你可以在这个repo上找到我的代码,但它基本上有一条到http://localhost:3000/worker的路由,它获取服务器端worker\run.js It calls the worker.js that has the worker_threads logic.它调用具有 worker_threads 逻辑的worker.js

The run.js calls the main() function on worker.js and creates a new thread that re-loads itself inside a worker thread instance, this time matching the if (.isMainThread) {...} condition, executing the console.logs (I tried other uses and the same problem appeared). run.js调用worker.js上的 main() function 并创建一个新线程,该线程在工作线程实例中重新加载自身,这一次匹配if (.isMainThread) {...}条件,执行控制台。日志(我尝试了其他用途并出现了同样的问题)。

/* worker.js */

import { Worker, isMainThread } from 'worker_threads';

export const main = () => new Promise(function (resolve, reject) {
  if (!isMainThread) return;

  // This re-loads the current file inside a Worker instance.
  const wk = new Worker(__filename);
  wk.on("online", () => console.log("Worker UP"));
  wk.on("message", (msg) => {
    console.log("message ~>", msg);
    resolve(msg);
  });
  wk.on("exit", (code) => console.warn("exit ~>", code));
  wk.on("error", (err) => {
    console.error("error ~>", err);
    reject(err);
  });
})

if (!isMainThread) {
  console.log('Inside Worker!');
  console.log(isMainThread);  
}

But it returns the following error (note that the console.log(isMainThread) is not executed):但它返回以下错误(注意console.log(isMainThread)没有执行):

> sapper dev

✔ client (3.3s)
✔ server (3.3s)
> Listening on http://localhost:3000
✔ service worker (84ms)
Worker UP
Inside Worker!
error ~> Error: listen EADDRINUSE: address already in use :::3000
    at Server.setupListenHandle [as _listen2] (net.js:1313:16)
    at listenInCluster (net.js:1361:12)
    at Server.listen (net.js:1449:7)
    at Polka.listen (/mnt/disk2/adr/lab2/pollers/worker/node_modules/.pnpm/registry.npmjs.org/polka/1.0.0-next.11/node_modules/polka/build.js:59:22)
    at Object.<anonymous> (/mnt/disk2/adr/lab2/pollers/worker/__sapper__/dev/server/server.js:3119:3)
    at Module._compile (internal/modules/cjs/loader.js:1133:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1153:10)
    at Module.load (internal/modules/cjs/loader.js:977:32)
    at Function.Module._load (internal/modules/cjs/loader.js:877:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12) {
  code: 'EADDRINUSE',
  errno: 'EADDRINUSE',
  syscall: 'listen',
  address: '::',
  port: 3000
}
exit ~> 1

edit:编辑:

After analyzing the output from rollup:从汇总分析 output 后:

/* __sapper__/dev/server/server.js */

'use strict';

function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }

var sirv = _interopDefault(require('sirv'));
var polka = _interopDefault(require('polka'));
var compression = _interopDefault(require('compression'));
var fs = _interopDefault(require('fs'));
var path = _interopDefault(require('path'));
var worker_threads = require('worker_threads');
var Stream = _interopDefault(require('stream'));
var http = _interopDefault(require('http'));
var Url = _interopDefault(require('url'));
var https = _interopDefault(require('https'));
var zlib = _interopDefault(require('zlib'));

if (!worker_threads.isMainThread) {
    console.log('Inside Worker!');
    console.log(worker_threads.isMainThread);  
}

var route_0 = /*#__PURE__*/Object.freeze({
    __proto__: null
});

const main = () => new Promise(function (resolve, reject) {
  if (!worker_threads.isMainThread) return;

  // This re-loads the current file inside a Worker instance.
  const wk = new worker_threads.Worker(path.join(__dirname, "threads.js"));
  wk.on("online", () => console.log("Worker UP"));
  wk.on("message", (msg) => {
    console.log("message ~>", msg);
    resolve(msg);
  });
  wk.on("exit", (code) => console.warn("exit ~>", code));
  wk.on("error", (err) => {
    console.error("error ~>", err);
    reject(err);
  });
});
...

Rollup bundles all files into a single one, hence the Worker(__filename) loads it again in a thread. Rollup 将所有文件捆绑到一个文件中,因此Worker(__filename)在线程中再次加载它。

So I put the file to be loaded in a thread into a separated file:所以我把要在一个线程中加载的文件放到一个单独的文件中:

/* thread.js */

import { isMainThread } from 'worker_threads';

if (!isMainThread) {
    console.log('Inside Worker!');
    console.log(isMainThread);
}

And changed the construction of the Worker instance to:并将Worker实例的构造改为:

const wk = new Worker(path.join(__dirname, "thread.js"));

Now the error has changed to:现在错误已更改为:

"Cannot find module '/mnt/disk2/adr/lab2/pollers/worker/__sapper__/dev/server/thread.js'"

The problem now boils down to a rollup config to keep the thread.js separated from the server.js.问题现在归结为汇总配置,以保持 thread.js 与 server.js 分离。

Sapper handles the rollup config in its own way, otherwise I could set the rollup.config.js like this: Sapper 以自己的方式处理汇总配置,否则我可以像这样设置rollup.config.js

export default [
  {
    input: "server.js",
    output: {
      file: "dist/server.js",
      format: "cjs",
    },
  },
  {
    input: "thread.js",
    output: {
      file: "dist/thread.js",
      format: "cjs",
    },
  },
];

Now the question is: is there a way to do that without modifying Sapper code?现在的问题是:有没有办法在不修改 Sapper 代码的情况下做到这一点?

To solve this, at least on sapper v0.27.0, I added the file I wanted to be executed as a thread in the server.input on rollup.config.js :为了解决这个问题,至少在 sapper v0.27.0 上,我在rollup.config.js的 server.input 中添加了我想作为线程执行的文件:

export default {

  server: {
    input: { ...config.server.input(), threads: "src/routes/worker/threads.js" },
    output: config.server.output(),
  }
}

config.server.intput() returns { server: `${__chunk_3.src}/server.js` } , then adding threads: "path_to_thread_file" did the trick. config.server.intput()返回{ server: `${__chunk_3.src}/server.js` } ,然后添加threads: "path_to_thread_file"就可以了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM