# Workers
MDN (opens new window) определяет Web Worker-ы так:
Web Worker-ы предоставляют простое средство для запуска скриптов в фоновом потоке. Поток Worker'а может выполнять задачи без вмешательства в пользовательский интерфейс.
ES4X не является браузером, и не заботится о пользовательском интерфейсе, но вы можете запускать долго бегущие задачи на стороне сервера. Все вызовы в Vert.x - неблокирующие, потому даже создание Web Worker должно следовать этой семантике. По этой причине мы не может строго следовать интерфейсу Worker и используем фабричный метод вместо конструктора.
Предположим, что вам необходимо запустить процессороёмкую задачу. Так как вы не должны блокировать событийный цикл, логичным шагом является использование Worker Verticle. Worker API соотносится с Vert.x API с некоторыми нюансами.
# Пример Worker
Представим следующий код Worker:
// Получаем ссылку на класс Thread с целью блокировки...
const Thread = Java.type('java.lang.Thread');
// Контекст Worker доступен через переменную `self` как в документации MDN
self.onmessage = function(e) {
console.log('Получено сообщение от главного скрипта, спим 5 секунд...');
// Внесем немного хаоса в событийный цикл
Thread.sleep(5 * 1000);
var workerResult = 'Результат: ' + (e.data[0] * e.data[1]);
console.log('Отправляем сообщение в главный скрипт');
// возвращаем данные в главный Verticle
postMessage(workerResult);
};
# Что нужно знать
Worker-ы загружаются в отдельных контекстах, так что вы не можете совместно использовать функции главного verticle и worker, все взаимодействие происходит через отправку сообщений (eventbus) с помощью:
postMessage()
отправляет сообщениеonmessage
принимает сообщение
# Со стороны Verticle
Часть API, отвечающая за Verticle, позволяет вам получать ошибки и завершать worker-ы c помощью terminate()
, в отличие
от самого worker.
# Пример Verticle
Worker.create('workers/worker.js', function (create) {
if (create.succeeded()) {
var worker = create.result();
worker.onmessage = function (msg) {
console.log('onmessage: ' + msg);
};
worker.onerror = function (err) {
console.err(err);
// завершаем worker
worker.terminate();
};
console.log('отправляем...');
worker.postMessage({data: [2, 3]});
}
});
Теперь код Thread.sleep(5000)
, который нельзя было запускать из событийного цикла, работает в worker-потоке, тем самым
оставляя поток событийного цикла доступным для всех других задач на чтение/запись.
# Worker-ы на других языках
Есть возможность создавать не JavaScript worker-ы. Worker-ы должны следовать следующему небольшому списку правил:
- Worker должен зарегистрировать адрес:
{deploymentId}.out
для получения сообщений от главного скрипта. - Worker должен отправлять сообщения для главного скрипта на адрес:
{deploymentId}.in
. - Содержимое сообщений должно использовать
JSON.stringify(message)
во избежание проблем между языками. - Ожидается, что Worker-ы будут локальными, если вы хотите подключиться к worker откуда угодно в кластере, используйте
конструктор с дополнительным аргументом
true
, например:new Worker('deploymentId', true)
.
← Eclipse Vert.x JARs →