Задать вопрос

Как обеспечивается согласованность данных между процессами в кластере Node.js?

Господа, я новичок в мире традиционной разработки Web-бекэнда и Node.js в частности.

Обычно я разрабатываю ПО на C/C++, где мы часто имеем многопоточные приложения, в которых все объекты расположены в общей для всех потоков памяти (а для синхронизации доступа потоков к объектам используются примитивы, такие как mutex, spinlock).

Однако, кластер Node.js не многопоточный, а многопроцессовый - из-за этого у меня возникает масса теоретических вопросов. Господа, будьте добры рассказать каковы традиционные подходы при разработке ПО для кластера Node.js относительно обеспечения согласованности информации между процессами кластера? Что я должен учитывать разрабатывая бекэнд-приложение для кластера Node.js?

Например, у нас есть несколько процессов в кластере Node.js, каждый из процессов закешировал секретный код для аутентификации HTTP-запросов некоторого пользователя посредством cookies (выбрав этот код из БД). В какой-то момент один из процессов кластера решил обновить этот секретный код. Как новый секретный код должен попасть ко всем остальным процессам? Ведь когда следующие HTTP-запросы пользователя пойдут через другие процессы, то пользователь получит отказ в доступе.

Второй пример, у нас есть несколько процессов в кластере Node.js, который обслуживает онлайн-магазин одежды. По запросу пользователя один из процессов выбрал из БД список на 500 позиций одежды, подходящих под запрос пользователя. 100 позиций этот процесс отдал пользователю в качестве первой страницы ответа, остальные позиции он закешировал (чтобы не ходить в БД снова когда пользователь запросит следующие страницы). Но запросы пользователя на следующие страницы могут пойти через другие процессы, где нет этих закешированных данных - как же с этим быть? Дублировать ли закешированный список из 500 позиций на остальные процессы? Если да, то как? Или пользователь каким-то образом должен быть привязан исключительно к первому процессу? Если да, то как?

Кроме того, являются ли мои примеры корректными, практикуется ли описанное кеширование данных в бекэнд-приложениях на Node.js?
  • Вопрос задан
  • 1987 просмотров
Подписаться 12 Оценить 2 комментария
Решения вопроса 1
zoonman
@zoonman
⋆⋆⋆⋆⋆
В кластерном Node.js вместо разделяемой памяти используется подход разделяемого хранилища данных.
Обычно эту роль выполняет Redis-кластер поскольку в нем есть механизмы уведомлений (подписок) и возможность асинхронного оповещения узлов кластера.
Такие вещи, как сессии и данные специфичные для клиента (кэши пользователя) хранятся вне Node.Js процесса, например в том же Redis. Это увеличивает инфраструктурные издержки, но позволяет производить бесшовные рестарты и пережить внезапные остановки машин в кластере.

Стандартной практикой является применение балансировщика, например того же nginx, включенного как reverse-proxy. Если вам не очень хочется разбираться с сессиями, используйте ip_hash, это снимет головную боль.

По поводу конкретных вопросов.

традиционные подходы при разработке ПО для кластера Node.js

Традиционный кластер представляет собой множество машин, на который запущено множество процессов через https://nodejs.org/api/cluster.html
Разумеется вместо разделямой памяти вы получаете разделямый сервис. Например с кэшем работаете как с базой и т.д. Почитайте о том, как работает горизонтальное масштабирование.

Что я должен учитывать разрабатывая бекэнд-приложение для кластера Node.js?

Учитывайте факт того, что это новая для вас область знаний. Вдобавок очень популярная и очень перегретая мнениями. Рассматривайте Node.js как некий клей между сервисами и другими решениями. Например ресайз картинок лучше делать на C++, поэтому расходы на создание процесса ресайзинга меньше расходов на ресайз реализованный на Node.js.

Как новый секретный код должен попасть ко всем остальным процессам?

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

100 позиций этот процесс отдал пользователю в качестве первой страницы ответа, остальные позиции он закешировал

Смотрите про балансировщик и ip_hash. Но в целом подход довольно плохой. Запрашивайте только нужные 100 товаров. Если вытаскивание данных из базы является проблемой, меняйте базу или ее структуру. Масштабируйте хранилище. В крайнем случае используйте разделяемый кэш (Redis, memcached).

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

Считается плохой практикой. Кэширование конфигурации или данных используемых повсеместно (например локализация) - норма. Кэширование пользовательских данных легко приводит к утечкам, т.к. вы никогда не знаете, сколько пользователей может обратиться к вашему ресурсу в указанный период времени.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
index0h
@index0h
PHP, Golang. https://github.com/index0h
Господа, будьте добры рассказать каковы традиционные подходы при разработке ПО для кластера Node.js относительно обеспечения согласованности информации между процессами кластера?

В рамках одного инстатса - собственно то же самое, что и на c++ - общая память. Создаем в некоем общем скопе сервис с данными, которые нужны для всех и используем.
В рамках кластера - кэширующие сервера, типа memcached, redis.

Что я должен учитывать разрабатывая бекэнд-приложение для кластера Node.js?

Несколько факторов:
- оно течет, и вы не раз будете вытирать капли крови из глаз, пытаясь понять где.
- качество существующих решений в большинстве случаев - невероятно низкое. Чего только стоит https://habrahabr.ru/post/280099/
- у вас будет много зависимостей хотите вы того, или нет.
- если вам не помогает событийная модель - Node.js вероятно не то, что вам надо.

Но запросы пользователя на следующие страницы могут пойти через другие процессы, где нет этих закешированных данных - как же с этим быть?

Кэшировать в скопе, доступном для каждого из ваших процессов.

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

По тому, как оно внутри работает - безусловно. Визуально же будет несколько по другому.

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const I_AM_CACHE = {
    "some": "data",
};

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end(JSON.stringify(I_AM_CACHE));
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});
Ответ написан
dummyman
@dummyman
диссидент-схизматик

Однако, кластер Node.js не многопоточный, а многопроцессовый - из-за этого у меня возникает масса теоретических вопросов. Господа, будьте добры рассказать каковы традиционные подходы при разработке ПО для кластера Node.js относительно обеспечения согласованности информации между процессами кластера? Что я должен учитывать разрабатывая бекэнд-приложение для кластера Node.js?


Все как в nix. Если вы знаете плюсы, то должны понять. Как передавать данные между процессами? Ну самое быстрое - безусловно, stdin/stdout, потом уже сокеты, базы данных особо не используют, в основном, только в случаях, что бы не допустить race conditions.

Если вы работали с плюсами, то с утечками памяти у вас проблем не будет. Просто подходите к модели потребления памяти так же как и в плюсах. Опять же, не меняйсте структуру класса, после создания объекта. - И все у вас будет.

Заметил тенденцию, текут нодовские скриптецы только у программистов PHP.

Что касается магазина одежды, я бы БД там не использовал. Как бы, хз, может мое личное субъективное мнение, но я бы сделал без БД. Ну это канеш смотря сколько сотрудников подключены к этому магазину. Если их там всего 4 менеджера и 1 директор, канеш БД - это просто лишний гемор. SQL куда менее поворотливый чем работа с массивами/объектами в js, за что как раз я его очень люблю.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы