#node.js
#node.js
Вопрос:
Сценарий: нескольким процессам NodeJS, запущенным на нескольких виртуальных машинах, необходимо взаимодействовать с главным процессом критичным по времени образом. Иногда обмен данными происходит с высокой частотой.
Решение: Процессы добавляют сообщения в один текстовый файл, хранящийся в общем хранилище, которое обрабатывается и очищается ведущим.
Подход к реализации до сих пор:
Этап 1: Процессы используют fs.createWriteStream().write(msg 'n')
для минимизации изменений одного процесса перезапись обновления другого процесса.
Этап 2: Основные методы, fs.watch().on(processChange(e,f))
используемые для получения изменений.
Этап 3: Сообщения обрабатываются и удаляются ведущим с помощью:
processChange(e, f) {
const NewMsgs = fs.readFileSync(f).toString().split('n');
fs.writeFileSync(f,'');
// now process NewMsgs
}
Вопросы:
- Есть ли лучшее решение?
- Как я могу улучшить свою реализацию?
- Насколько вероятно, что сообщения будут перезаписаны на этапах 1 и 3?
Комментарии:
1. Почему не через сокет TCP?
2. Это кластеризованное приложение? Я имею в виду, все ли дочерние процессы в основном являются форком главного?
Ответ №1:
Я бы предложил использовать socket.io — он обеспечивает эффективную связь между приложениями без возможности потери данных из-за неправильного одновременного обновления файловой системы и содержит отличный набор руководств по началу работы.
Кроме того, это дает вам преимущество в том, что вы можете распределять процессы NodeJS по разным машинам — в вашем текущем решении все они должны быть расположены на одной машине. Вероятно, это поможет вашему приложению масштабироваться по мере роста спроса на него.
Ответ №2:
Моим предложением было бы настроить pub / sub и настроить дочерние процессы для публикации на канале и позволить master подписаться и обработать его любым способом, который он захочет. Используйте что-то вроде Redis Pub / Sub или Node-IPC. Пример использования node-ipc, написанный ndelangen
Первый процесс
const ipc = require('node-ipc');
ipc.config.id = 'a-unique-process-name1';
ipc.config.retry = 1500;
ipc.config.silent = true;
ipc.serve(() => ipc.server.on('a-unique-message-name', message => {
console.log(message);
}));
ipc.server.start();
Второй процесс
const ipc = require('node-ipc');
ipc.config.id = 'a-unique-process-name2';
ipc.config.retry = 1500;
ipc.config.silent = true;
ipc.connectTo('a-unique-process-name1', () => {
ipc.of['jest-observer'].on('connect', () => {
ipc.of['jest-observer'].emit('a-unique-message-name', "The message we send");
});
});
Комментарии:
1. Спасибо за ваши ответы. Я рассматриваю возможность использования сокета. ввод-вывод, как предложил джейкеминголла, который реализует модель pub / sub. Как вы думаете, мне было бы лучше использовать Redis Pub / Sub или Node-IPC? Если да, то почему?
2. Websockets — это технология двусторонней связи, в основном для браузера и сервера. Вы можете отправлять сообщения на сервер и получать ответы, управляемые событиями, без необходимости запрашивать ответ у сервера. Я бы предложил Node-IPC, если в этом нет ничего сложного, потому что Redis Pub / Sub требует, чтобы вы настроили экземпляр Redis.
Ответ №3:
Если вы не хотите обременять инфраструктуру пабом / субсистемой или системой очередей, могу я предложить, чтобы вместо добавления к файлу вы лучше помещали по одному файлу на сообщение в общую папку и позволяли главному процессу просматривать папку и обрабатывать и удалять их файл за файлом?
Добавление нескольких процессов к файлу при одновременном удалении строк звучит как путь к катастрофе.
Учитывая, что, похоже, от ведущего сервера нет обратной связи, это должен быть жизнеспособный подход.
Что помогло бы вам выбрать решение, так это если бы вы могли указать, предпочитаете ли вы надежность доставки (имеется в виду, что все сообщения в конечном итоге должны дойти до главного устройства) или скорость доставки (имеется в виду, что задержки недопустимы, но потеря данных, которые считаются старыми, — это нормально).