NodeJS и Socket.io в производстве: работа с состоянием

В среде разработки у меня есть единственный процесс nodejs, у которого socket.io прослушивает данный порт. После подключения клиента состояние необходимо поддерживать. Скрипт nodejs выполняет некоторую работу с файлами и отправляет статус обработки через сокеты. Это как партия, которая может никогда не закончиться.

Если клиент закрывает браузер, а затем снова открывается (в среде разработки), веб-страница просто снова подключается к сокету и захватывает текущее состояние процесса, который будет обрабатывать файлы в фоновом режиме для этого конкретного пользователя.

Чтобы иметь один процесс для каждого пользователя и гарантировать, что пользователи всегда повторно подключаются к тому же процессу, который они запустили, на одном и том же порте, мне нужно управлять этим процессом, по одному для каждого пользователя в качестве службы на сервере, и резервировать порты для каждого. Пользователь.

Как мне построить этот сценарий как единую точку входа nodejs, которая разветвляет процессы и соответствующим образом маршрутизирует соединения сокетов, используя, возможно, кластеры Nginx, PM2 или Nodejs. Другими словами, какая архитектура лучше всего подходит для такого сценария?

О государственной проблеме:

Состояние, которое я держу, - это не просто переменные, которые можно хранить в базе данных. У меня есть непрерывные потоки чтения файлов, которые обрабатываются один за другим в порядке, который пользователь настроил через веб-страницу, подключенную с помощью сокетов к этому процессу. Этот процесс также подключается к другому сокету сервер-сервер, и соединение должно быть сохранено.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
2 667
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я бы, вероятно, пошел с выставлением pid ваших процессов вашему сценарию маршрутизации и использованием сеансов и файлов cookie, сохраняя их в Redis DB вместе с pid, назначенным пользователю.

Итак, при подключении вы устанавливаете cookie и сеанс, возможно, с хешем datetime для идентификатора пользователя (в зависимости от того, есть ли у вас учетные записи пользователей, связанные с вашими клиентами), сохраняете его в cookie пользователя и сохраняете pid в своем сеансе.

Затем вы можете перенаправить своих пользователей на соответствующую вилку вашего процесса в вашем маршрутизаторе.

Редактировать

Я бы использовал nodecript в качестве прокси. Я нашел ответ это, поскольку вы не разместили код, я не знаю, как именно вы создаете свои процессы, поэтому я буду использовать его для справки:

const socketio = require('socket.io');
const redis = require('redis');

on.connect((req, res) => {
    let uid,
        pid,
        port;

    // if user does not have the cookie yet
    if (!req.cookies.uid) {
        uid = getNewUserID(req); // create uid from information from the request, set a cookie later
        pid = createWorker(uid); // generate new socket.io worker in cluster and return pid
        port = getSocketPort(pid); // get socket port from worker

        // save acquired variables to database
        redis.set(uid, [pid, port], function(err, reply) {
            if (err) throw err;
            console.info(reply);
        });
    };

    uid = req.cookies.uid; // get uid from request
    pid = getPid(uid); // get pid from redis

    socketio(getSocketPort(pid)); // connect client to port of correct worker
});

для ваших потоков чтения вы можете просто выполнять их внутри соответствующего воркера. 1 рабочий равен 1 процессу socket.io

Будет ли это сделано с помощью обратного прокси-сервера Nginx? Как бы был выполнен этот сценарий маршрутизации? Это сценарий nodejs, действующий как прокси-сервер Nginx Revese?

Valdir 11.04.2018 16:44

@Valdir Насколько мне известно, обратный прокси-сервер NginX перенаправляет клиентов на разные службы и серверы. В этом случае вы просто перенаправляете на форки в своем кластере. Я обновил свой ответ образцом сценария, чтобы вы лучше поняли мой ответ.

Tom M 11.04.2018 21:19

Да вроде путь.

Valdir 12.04.2018 15:11

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

Мне нужно подключиться к тому же процессу, поскольку мне нужно иметь возможность воспроизводить / приостанавливать / изменять пакетный процесс, который будет выполняться для этого пользователя в этом конкретном процессе.

Valdir 11.04.2018 16:34

Другие вопросы по теме