[JavaScript, Программирование, Node.JS] Как управлять несколькими потоками в Node JS (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
В этом посте я собираюсь показать вам, как потенциально утроить производительность вашего приложения Node за счет управления несколькими потоками. Это важный учебник, в котором показанные методы и примеры дадут вам все необходимое для настройки эффективного управления потоками.Извините, данный ресурс не поддреживается. :( Дочерние процессы, кластеризация и Worker ThreadsВ течение долгого времени Node обладал способностью быть многопоточным, используя дочерние процессы, кластеризацию, или более предпочтительный в последнее время метод модуля под названием Worker Threads.Дочерние процессы были первоначальным средством создания нескольких потоков для вашего приложения и были доступны с версии 0.10. Это достигалось путем создания узлового процесса для каждого дополнительного потока, который вы хотели создать.Кластеризация, которая стала стабильной примерно с версии 4, позволяет нам упростить создание и управление дочерними процессами. Она великолепно работает в сочетании с PM2.Теперь, прежде чем мы перейдем к многопоточности нашего приложения, есть несколько моментов, которые должны быть полностью поняты:1. Многопоточность уже существует для задач ввода/выводаВ Node есть слой, который уже является многопоточным, и это пул потоков libuv. Задачи ввода-вывода, такие как управление файлами и папками, транзакции TCP/UDP, сжатие и шифрование, передаются libuv, и если они не являются асинхронными по своей природе, то обрабатываются в пуле потоков libuv.2. Child Processes (Дочерние процессы)/Worker Threads работают только для синхронной логики JavaScript.Имплементация многопоточности с помощью дочерних процессов или Worker Threads будет эффективна только для синхронного кода JavaScript, выполняющего трудоемкие операции, такие как циклы, вычисления и т.д. Если вы в качестве примера попытаетесь переложить задачи ввода-вывода на Worker Threads, то не увидите улучшения производительности.3. Создать один поток легко. Динамично управлять несколькими потоками сложноСоздать один дополнительный поток в вашем приложении достаточно просто, поскольку существует масса руководств о том, как это сделать. Однако создание потоков, эквивалентных количеству логических ядер вашей или виртуальной машины, и управление распределением работы между этими потоками является более сложной задачей, разработка такой логики достаточно трудозатратна.Хорошо, что мы живем в мире открытого исходного кода и блестящего вклада сообщества Node. Это значит, что уже существует модуль, который даст нам полную возможность динамически создавать и управлять потоками в зависимости от доступности ЦП нашей или виртуальной машины.Worker PoolМодуль, с которым мы будем работать сегодня, называется Worker Pool. Созданный Джосом де Йонгом, Worker Pool предлагает простой способ создания пула воркеров для динамической разгрузки вычислений, а также для управления пулом выделенных воркеров. По сути, это менеджер пула потоков для Node JS, поддерживающий Worker Threads, дочерние процессы и Web Workers для браузерных имплементаций.Чтобы использовать модуль Worker Pool в нашем приложении, необходимо выполнить следующие задачи:
- Установить Worker Pool
Сначала нам нужно установить модуль Worker Pool - npm install workerpool
- Инициализировать Worker Pool
Далее нам нужно будет инициализировать Worker Pool при запуске нашего приложения.
- Создать Middleware Layer
Затем нам нужно будет создать Middleware Layer (промежуточный слой) между нашей сложной JavaScript-логикой и Worker Pool, который будет управлять ею.
- Обновить существующую логику
Наконец, нам нужно обновить наше приложение, чтобы при необходимости передавать трудоемкие задачи Worker Pool.Управление несколькими потоками с помощью Worker PoolНа данном этапе у вас есть 2 варианта: Использовать свое собственное приложение NodeJS (и установить модули workerpool и bcryptjs), или загрузить исходный код с GitHub по этому руководству и моей серии видео об оптимизации производительности NodeJS.Если вы выберете последний вариант, файлы по данному руководству будут находиться в папке 06-multithreading. После загрузки войдите в корневую папку проекта и запустите npm install. Затем войдите в папку 06-multithreading, чтобы продолжить работу.
В папке worker-pool у нас есть 2 файла: один - это логика контроллера для Worker Pool (controller.js). Другой (файл) содержит функции, которые будут запускаться потоками... он же так называемый промежуточный слой, о котором я говорил ранее (thread-functions.js).worker-pool/controller.js
'use strict'
const WorkerPool = require('workerpool')
const Path = require('path')
let poolProxy = null
// FUNCTIONS
const init = async (options) => {
const pool = WorkerPool.pool(Path.join(__dirname, './thread-functions.js'), options)
poolProxy = await pool.proxy()
console.log(`Worker Threads Enabled - Min Workers: ${pool.minWorkers} - Max Workers: ${pool.maxWorkers} - Worker Type: ${pool.workerType}`)
}
const get = () => {
return poolProxy
}
// EXPORTS
exports.init = init
exports.get = get
В файле controller.js мы используем модуль workerpool. У нас также есть 2 экспортируемые функции, которые называются init и get. Функция init будет выполняться один раз во время загрузки нашего приложения. Она инстанцирует Worker Pool с опциями, которые мы предоставим, и ссылкой на thread-functions.js. Она также создает прокси, который будет храниться в памяти до тех пор, пока работает наше приложение. Функция get просто возвращает прокси в памяти.worker-pool/thread-functions.js
'use strict'
const WorkerPool = require('workerpool')
const Utilities = require('../2-utilities')
// MIDDLEWARE FUNCTIONS
const bcryptHash = (password) => {
return Utilities.bcryptHash(password)
}
// CREATE WORKERS
WorkerPool.worker({
bcryptHash
})
В файле thread-functions.js создадим воркер-функции, которые будут управляться Worker Pool. В нашем примере применим BcryptJS для хэширования паролей. Это обычно занимает около 10 миллисекунд, в зависимости от скорости работы используемой машины, и является хорошим решением для трудоемких задач. Внутри файла utilities.js находится функция и логика, которая хэширует пароль. Все, что мы делаем в функциях потока, заключается в выполнении этого bcryptHash через функцию workerpool. Таким образом, мы сохраняем код централизованным и избегаем дублирования или путаницы в том, где существуют определенные операции.2-utilities.js
'use strict'
const BCrypt = require('bcryptjs')
const bcryptHash = async (password) => {
return await BCrypt.hash(password, 8)
}
exports.bcryptHash = bcryptHash
.env
NODE_ENV="production"
PORT=6000
WORKER_POOL_ENABLED="1"
Файл .env содержит номер порта и устанавливает переменную NODE_ENV на "production". Здесь же мы указываем, хотим ли мы включить или отключить Worker Pool, устанавливая WORKER_POOL_ENABLED в "1" или "0".1-app.js
'use strict'
require('dotenv').config()
const Express = require('express')
const App = Express()
const HTTP = require('http')
const Utilities = require('./2-utilities')
const WorkerCon = require('./worker-pool/controller')
// Router Setup
App.get('/bcrypt', async (req, res) => {
const password = 'This is a long password'
let result = null
let workerPool = null
if (process.env.WORKER_POOL_ENABLED === '1') {
workerPool = WorkerCon.get()
result = await workerPool.bcryptHash(password)
} else {
result = await Utilities.bcryptHash(password)
}
res.send(result)
})
// Server Setup
const port = process.env.PORT
const server = HTTP.createServer(App)
;(async () => {
// Init Worker Pool
if (process.env.WORKER_POOL_ENABLED === '1') {
const options = { minWorkers: 'max' }
await WorkerCon.init(options)
}
// Start Server
server.listen(port, () => {
console.log('NodeJS Performance Optimizations listening on: ', port)
})
})()
И последнее, файл 1-app.js содержит код, который будет выполняться при запуске нашего приложения. Сначала инициализируем переменные в файле .env. Затем настроим сервер Express и создадим маршрут под названием /bcrypt. При запуске этого маршрута проверим, включен ли Worker Pool. Если да, то получим управление прокси Worker Pool и выполним функцию bcryptHash, которую мы объявили в файле thread-functions.js. Она, в свою очередь, выполнит функцию bcryptHash в Utilities и вернет нам результат. Если Worker Pool отключен, тогда просто выполним функцию bcryptHash непосредственно в Utilities.В конце нашего файла 1-app.js находится функция, вызывающая саму себя. Это сделано для поддержки async/await, которую мы используем при взаимодействии с Worker Pool. Далее инициализируем Worker Pool, если он включен. Единственная конфигурация, которую надо переопределить - установка minWorkers на "max". Это гарантирует, что Worker Pool породит столько потоков, сколько логических ядер есть на нашей машине, за исключением 1 логического ядра, которое используется для главного потока. В моем случае имеется 6 физических ядер с гиперпоточностью, это означает, что у меня в распоряжении 12 логических ядер. Поэтому при значении minWorkers равном "max", Worker Pool будет создавать и управлять 11 потоками. Наконец, последний фрагмент кода - это запуск нашего сервера и прослушивание порта 6000.Тестирование Worker PoolТестировать Worker Pool очень просто: запустите приложение и во время его работы выполните запрос get на http://localhost:6000/bcrypt. Если у вас есть инструментарий нагрузочного тестирования, такой как AutoCannon, вы можете посмотреть разницу в производительности при включении/выключении Worker Pool. AutoCannon очень прост в использовании.ЗаключениеЯ надеюсь, что это руководство дало вам представление об управлении несколькими потоками в вашем приложении Node. Вложенное видео в начале статьи наглядно демонстрирует процесс тестирования приложения Node.
Перевод подготовлен в рамках курса "Node.js Developer". Если интересно узнать о курсе больше, регистрируйтесь на день открытых дверей.
===========
Источник:
habr.com
===========
===========
Автор оригинала: JOHN JARDIN | Bleeding Code
===========Похожие новости:
- [Программирование, Венчурные инвестиции, Развитие стартапа, Образование за рубежом, Бизнес-модели] Перевод Курса по стартапам и бизнесу от Стэнфордского Университета. Лекция №3. Подготовка к созданию стартапа (перевод)
- [JavaScript, API, Стандарты связи] Консорциум Всемирной паутины принял стандарт Web Audio в качестве официального
- [JavaScript] Первая программа для семилетки
- [JavaScript, Программирование, Тестирование веб-сервисов, Машинное обучение] В закладки: репозитории с книгами, шпаргалками, ресурсами по дизайну и не только (перевод)
- [Программирование, Java] Создание самодостаточных исполняемых JAR (перевод)
- [JavaScript, Программирование, Алгоритмы, Обработка изображений, Машинное обучение] Как мы создали Web приложение для определения лиц и масок для Google Chrome (часть 2) (перевод)
- [Микросервисы] Лучшие фреймворки для микросервисов (перевод)
- [Программирование, Учебный процесс в IT, Карьера в IT-индустрии, История IT, Биографии гиков] Пятьдесят лет на стезе программирования. Часть I. Начало пути. Отчий дом и Казанское суворовское военное училище
- [JavaScript, Учебный процесс в IT, Удалённая работа] История о том, как я иду к должности JS разработчика через обучение на курсах в Skillbox
- [Разработка веб-сайтов, JavaScript] Идеальный инструмент для создания прогрессивных веб-приложений или Все, что вы хотели знать о Workbox. Часть 2
Теги для поиска: #_javascript, #_programmirovanie (Программирование), #_node.js, #_javascript, #_node.js, #_programming, #_blog_kompanii_otus (
Блог компании OTUS
), #_javascript, #_programmirovanie (
Программирование
), #_node.js
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 12:55
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
В этом посте я собираюсь показать вам, как потенциально утроить производительность вашего приложения Node за счет управления несколькими потоками. Это важный учебник, в котором показанные методы и примеры дадут вам все необходимое для настройки эффективного управления потоками.Извините, данный ресурс не поддреживается. :( Дочерние процессы, кластеризация и Worker ThreadsВ течение долгого времени Node обладал способностью быть многопоточным, используя дочерние процессы, кластеризацию, или более предпочтительный в последнее время метод модуля под названием Worker Threads.Дочерние процессы были первоначальным средством создания нескольких потоков для вашего приложения и были доступны с версии 0.10. Это достигалось путем создания узлового процесса для каждого дополнительного потока, который вы хотели создать.Кластеризация, которая стала стабильной примерно с версии 4, позволяет нам упростить создание и управление дочерними процессами. Она великолепно работает в сочетании с PM2.Теперь, прежде чем мы перейдем к многопоточности нашего приложения, есть несколько моментов, которые должны быть полностью поняты:1. Многопоточность уже существует для задач ввода/выводаВ Node есть слой, который уже является многопоточным, и это пул потоков libuv. Задачи ввода-вывода, такие как управление файлами и папками, транзакции TCP/UDP, сжатие и шифрование, передаются libuv, и если они не являются асинхронными по своей природе, то обрабатываются в пуле потоков libuv.2. Child Processes (Дочерние процессы)/Worker Threads работают только для синхронной логики JavaScript.Имплементация многопоточности с помощью дочерних процессов или Worker Threads будет эффективна только для синхронного кода JavaScript, выполняющего трудоемкие операции, такие как циклы, вычисления и т.д. Если вы в качестве примера попытаетесь переложить задачи ввода-вывода на Worker Threads, то не увидите улучшения производительности.3. Создать один поток легко. Динамично управлять несколькими потоками сложноСоздать один дополнительный поток в вашем приложении достаточно просто, поскольку существует масса руководств о том, как это сделать. Однако создание потоков, эквивалентных количеству логических ядер вашей или виртуальной машины, и управление распределением работы между этими потоками является более сложной задачей, разработка такой логики достаточно трудозатратна.Хорошо, что мы живем в мире открытого исходного кода и блестящего вклада сообщества Node. Это значит, что уже существует модуль, который даст нам полную возможность динамически создавать и управлять потоками в зависимости от доступности ЦП нашей или виртуальной машины.Worker PoolМодуль, с которым мы будем работать сегодня, называется Worker Pool. Созданный Джосом де Йонгом, Worker Pool предлагает простой способ создания пула воркеров для динамической разгрузки вычислений, а также для управления пулом выделенных воркеров. По сути, это менеджер пула потоков для Node JS, поддерживающий Worker Threads, дочерние процессы и Web Workers для браузерных имплементаций.Чтобы использовать модуль Worker Pool в нашем приложении, необходимо выполнить следующие задачи:
В папке worker-pool у нас есть 2 файла: один - это логика контроллера для Worker Pool (controller.js). Другой (файл) содержит функции, которые будут запускаться потоками... он же так называемый промежуточный слой, о котором я говорил ранее (thread-functions.js).worker-pool/controller.js 'use strict'
const WorkerPool = require('workerpool') const Path = require('path') let poolProxy = null // FUNCTIONS const init = async (options) => { const pool = WorkerPool.pool(Path.join(__dirname, './thread-functions.js'), options) poolProxy = await pool.proxy() console.log(`Worker Threads Enabled - Min Workers: ${pool.minWorkers} - Max Workers: ${pool.maxWorkers} - Worker Type: ${pool.workerType}`) } const get = () => { return poolProxy } // EXPORTS exports.init = init exports.get = get 'use strict'
const WorkerPool = require('workerpool') const Utilities = require('../2-utilities') // MIDDLEWARE FUNCTIONS const bcryptHash = (password) => { return Utilities.bcryptHash(password) } // CREATE WORKERS WorkerPool.worker({ bcryptHash }) 'use strict'
const BCrypt = require('bcryptjs') const bcryptHash = async (password) => { return await BCrypt.hash(password, 8) } exports.bcryptHash = bcryptHash NODE_ENV="production"
PORT=6000 WORKER_POOL_ENABLED="1" 'use strict'
require('dotenv').config() const Express = require('express') const App = Express() const HTTP = require('http') const Utilities = require('./2-utilities') const WorkerCon = require('./worker-pool/controller') // Router Setup App.get('/bcrypt', async (req, res) => { const password = 'This is a long password' let result = null let workerPool = null if (process.env.WORKER_POOL_ENABLED === '1') { workerPool = WorkerCon.get() result = await workerPool.bcryptHash(password) } else { result = await Utilities.bcryptHash(password) } res.send(result) }) // Server Setup const port = process.env.PORT const server = HTTP.createServer(App) ;(async () => { // Init Worker Pool if (process.env.WORKER_POOL_ENABLED === '1') { const options = { minWorkers: 'max' } await WorkerCon.init(options) } // Start Server server.listen(port, () => { console.log('NodeJS Performance Optimizations listening on: ', port) }) })() Перевод подготовлен в рамках курса "Node.js Developer". Если интересно узнать о курсе больше, регистрируйтесь на день открытых дверей.
=========== Источник: habr.com =========== =========== Автор оригинала: JOHN JARDIN | Bleeding Code ===========Похожие новости:
Блог компании OTUS ), #_javascript, #_programmirovanie ( Программирование ), #_node.js |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 12:55
Часовой пояс: UTC + 5