170 похожих чатов

Всем привет! Есть такая проблема. NestJS используется в качестве BFF прокси

прослойки. Фронт авторизуется через BFF и держит авторизацию через сессию (express-session + connect-redis). JWT токен хранится на стороне BFF в сессии. Кроме access токена хранится ещё refresh token. И вот проблема в реализации нормального рефреша. Пользователь открывает страницу, сразу отправляется пачка параллельных запросов за всякими данными, словарями и прочим. Я в guard'е проверяю не истёк ли токен, и если истёк, то отправляю запрос на refresh и обновляю в сессии access token. Но когда запросов много одновременно, то в итоге формируется целая пачка access токенов. Пытался синхронизировать через redis. Типа записывать в сессию флаг о том, что выполняется рефреш токена. В созданный для этого канал пушится сообщение о начале рефреша. При этом подписанные к этому каналу на это событие подгружают актуальную сессию через req.session.reload(). Но это не работает, всё равно успевают создаться несколько сессий.

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

13 ответов

20 просмотров

Кажется, что проблему надо решать на фронте. Так как пачка одинаковых запросов - это неправильно

Vladimir- Автор вопроса
Алексей Попов
Кажется, что проблему надо решать на фронте. Так к...

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

Vladimir- Автор вопроса
Алексей Попов
Кажется, что проблему надо решать на фронте. Так к...

Запросы всяких списков, справочников типа /currencies, /countries, /some-list

Касательно того, как сделать так, чтобы только один запрос уходил на запрос токена, а остальные ждали, то можешь посмотреть как работают pool'ы конекшенов, например тут. Если я правильно понял, то проблема похожа

Vladimir- Автор вопроса
John Doe
Касательно того, как сделать так, чтобы только оди...

Да, похоже, но здесь сработает, если нода запущена одна. А у нас запускается параллельно два пода с приложением. С таким вариантом просто отправится не более 2 запросов. Что уже лучше, конечно. Но не полностью решит ситуацию.

Vladimir
Да, похоже, но здесь сработает, если нода запущена...

Тогда если нужен один access на все иснтансы, то пусть инстаны ноды лезут в общее хранилище (например redis) и получаю токен оттуда. А в редис его будет класть другой бекграунд процесс раз в N времени

Vladimir- Автор вопроса
Vladimir
Он и лежит в redis - в сессии

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

Vladimir- Автор вопроса
John Doe
Пусть его кладёт один бекграунд процесс раз в N вр...

Да я вот уже думаю о том, чтобы просто автоматически рефрешить эти токены по крону... Это будет примерно тоже самое, тоже обновляться раз в N времени.

Vladimir
Да я вот уже думаю о том, чтобы просто автоматичес...

Я думаю мы тогда говорим об одном и том же

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

Vladimir
Да я вот уже думаю о том, чтобы просто автоматичес...

Обновлять токены для пользователей без активного соединения? Это звучит странно

Vladimir- Автор вопроса
Алексей Попов
А почему не работает синк через редис? При правиль...

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

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

Обсуждают сегодня

Какой-то там пердун в 90-х решил, что есть какая-то разная типизация. Кого вообще это волнует?
КТ315
49
void terminal_scroll() { memmove(terminal_buffer, terminal_buffer + VGA_WIDTH, buffer_size - VGA_WIDTH); memset(terminal_buffer + buffer_size - VGA_WIDTH, 0, VGA_WIDTH); ...
Егор
47
Всем привет! Подскажите, пожалуйста, в чем ошибка? Настраиваю подключение к MySQL. Либы лежат рядом с exe. Все как по "учебнику"
Евгений
16
А можете как-то проверить меня по знаниям по ассемблеру?
A A
132
Здравствуйте! У меня появилась возможность купить книгу "Изучай Haskell во имя добра!". Но я где-то слышал, что эта книга устарела. Насколько это правда??
E
22
Здравствуйте! Я вот на stepic решаю задачи на хаскеле https://stepik.org/lesson/8443/step/8?unit=1578 мой код import Data.List (isInfixOf) removing :: String -> [String] ->...
E
10
Камрады, кто тесно работал с vtv, хотел уточнить. Ширина column задаётся жёстко на этапе создания дерева или можно в рантайме ее менять программно (не мышкой)?
Ed Doc
10
да ладно ... что там неочевидного ? глянуть в исх-ки датасета и/или кверика чтобы понять в каком месте и как выполняется обращения к св-вам blablaSQL - минутное дело, даже е...
Сергей
7
Здесь для arm кто-нибудь кодит ?
Nothing
52
Всем привет, у меня есть сервер принимающий входящие HTTP подключения, как проверить, что подключение было через прокси или нет, есть какие то поля в заголовках по которым мо...
DS
8
Карта сайта