Как выполнить многопоточность в Node.js

Прошло уже пять лет с тех пор, как Node.js представил собственную библиотеку worker_threads, предназначенную для создания воркеров, по сути функционирующих как потоки.

Когда он был выпущен, я был полон энтузиазма и стремился создать что-то интересное в этом плане.

Обсуждая рабочие потоки, я заметил, что не каждому удается построить правильную систему, использующую worker_threads. Следовательно, я начал поиск абстракций, которые могли бы упростить и расширить возможности для более интригующих решений.

Я наткнулся на несколько интригующих абстракций, но в конечном итоге решил разработать свою собственную — легкую и понятную.

веселые нити

НПМ | Гитхаб

Идея проста: вы можете выполнить свою функцию в выделенном потоке, используя Promises.

import executeInThread from 'funthreads';

async function calculate() {
    const values = await Promise.all([
        executeInThread(() => 2 ** 10),
        
        executeInThread(() => 3 ** 10)
    ]);
    
    console.log(values);
}

calculate();

Вы можете переместить операции с интенсивным использованием ЦП в отдельные потоки и легко получать результаты с помощью Promises.

Просто попробуйте себя и увидите.

$ npm i funthreads

https://github.com/nairihar/funthreads

Я не потратил много времени на эту библиотеку, и хотя я не использовал ее в реальном проекте, я остался в восторге и со временем внес небольшие улучшения.

После публикации этой библиотеки я заметил другие расширенные реализации той же идеи.

пул потоков-узлов-работников

Как описывают авторы: Простой пул рабочих потоков с использованием модуля worker_threads Node. Совместим с ES6+ Promise, Async/Await и TypeScript🚀.

Но это еще не все, есть еще одна библиотека, выпущенная еще до worker_threads.

Раньше они использовали различные стратегии и подходы для поддержки многопоточности. Однако после worker_threads их реализация значительно улучшилась.

Вот краткий пример, иллюстрирующий, как работает библиотека.

// main.js
import { spawn, Thread, Worker } from "threads"

const auth = await spawn(new Worker("./workers/auth"))
const hashed = await auth.hashPassword("Super secret password", "1234")

console.log("Hashed password:", hashed)

await Thread.terminate(auth)
// worker.js
import sha256 from "js-sha256"
import { expose } from "threads/worker"

expose({
  hashPassword(password, salt) {
    return sha256(password + salt)
  }
})

Кажется, это самая большая библиотека, предоставляющая кучу инструментов для работы с многопоточностью в Node.js.

P.S. Обе библиотеки предлагают метод создания пула потоков и использования его для конкретных случаев использования.

К сожалению, ни один из них я не использовал в производстве, так как не было необходимости. Однако я уверен, что многие проекты могут извлечь из них пользу в реальных сценариях.

Интересно наблюдать, как они работают, и понимать механику абстракции.

Библиотека funthreads довольно проста и состоит всего из нескольких файлов с небольшими функциями. Вы можете начать с него, и я уверен, что вы легко поймете эту концепцию, понимая, насколько проста предоставленная абстракция.

Подведение итогов

По сравнению с другими языками программирования в JavaScript все совсем по-другому. Все происходит по-своему и имеет свое объяснение.

В JavaScript есть классы, а Node.js поддерживает многопоточность. Хотя это может показаться ошеломляющим по сравнению с другими языками, важно учитывать его уникальность.

Благодарим вас за то, что нашли время прочитать эту подробную статью.
Не стесняйтесь задавать любые вопросы или писать мне в Твиттере @nairihar

Также следите за моей рассылкой JavaScript в Telegram: @javascript

Надеюсь, вы нашли это информативным и почерпнули из него ценную информацию.

Читать далее