У меня есть приложение nodejs, которое работает на одном сервере.Мне нужно запустить приложение на нескольких серверах для балансировки нагрузки.
Это приложение обрабатывает только один запрос от конкретного пользователя за раз.Если одновременные запросы поступают от пользователя, запросы ставятся в очередь и выполняются один за другим.Это сделано для поддержания согласованности некоторых данных в базе данных, которые могут быть повреждены, если приложение обрабатывает одновременные запросы.
Поскольку я собираюсь запустить приложение на нескольких серверах, мне нужен способ предотвратитьсерверы от одновременной обработки запросов от одного пользователя.Для этого я использовал базу данных Firebase в реальном времени для создания распределенной блокировки.Ниже приведена более простая версия моего кода.
function lockUser(user) {
return firebaseAdmin.database().ref('users/' + user + '/lock').transaction((currentData) => {
if (currentData === null || currentData.lockTime === 0) {
return {'lockTime': Date.now()};
}
}, null, false).then(async (result) => {
if (result.committed) {
return Promise.resolve();
}
log.info('failed to lock ' + user + '. retrying.');
await sleepFor(500);
return lockUser(user, user, res);
}).catch(async (reason) => {
log.info('lock failed. ' + user + '. reason: ' + reason + '. retrying');
await sleepFor(500);
return lockUser(user, user, res);
});
}
function unlockUser(user) {
log.info('unlocking firebase lock. ' + user);
firebaseAdmin.database().ref('users/' + user + '/lock').set({'lockTime': 0}, (error) => {
if (error) {
log.warn('failed to unlock ' + user + '. error: ' + util.inspect(error));
} else {
log.info('unlocked ' + user);
}
});
}
При использовании приведенного выше кода блокировка обычно занимает около 100 миллисекунд, и она в основном соответствует.Но редко, иногда я наблюдаю значительную задержку завершения транзакции.Когда это происходит, блокировка может занять около 30 секунд.
В чем может быть причина этой задержки?Есть ли причина, по которой я не должен использовать базу данных Firebase в реальном времени таким образом?