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

Ребята, кто шарит, Есть балансер, за ним 2-3 сервера, на которых

крутится Nodejs приложение.
Есть эндпоинт по которому выполняется долгий запрос в котором происходит много разных действий.

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

Думал через запись в БД лочить, но, она находится в другом месте и боюсь что могут быть задержки из-за пинга

Вопрос: как вы решаете такие задачи?

39 ответов

15 просмотров

Перед началом собственно логики обработки запроса проверяешь, что данных пользователя нет в условном редисе, если есть - отклоняешь, если нет - помещаешь. Перед выполненным запросом удаляешь из редиса данные

Самый простой вариант sticky sessions, запросы распределяются по нодам, но от одного юзера всегда идут к той же ноде В nginx есть поддержка скриптов lua и js, в них можно проверять в Redis статус запроса

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

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

Несколько процессов не шарят память

да на балансере просто)

если это куки, то можно же очистить куки и заново отправить)

У меня такая задача лок через редис ван лав

Дело не в редисе и т.п. Мне кажется нужно подходить с точки зрения архитектуры приложения. Ему нужен отдельный слой, который будет выполнять задачу. А как он это сделает это уже другой вопрос. Можно сделать это как слой монолита, можно написать отдельный сервис под эти нужны, можно подключить модуль к nginx, рассмотреть готовые rate limiter'ы Короче вариантов куча, если понимать что это отдельный слой, а не часть бизнес слоя текущего монолита

это вполне же может быть частью бизнес логики в зависимости от задачи

Например когда? Из его слов: Нужно сделать так, чтобы одному пользователю нельзя было выполнить этот запрос больше одного раза одновременно, учитывая что балансер распределяет запросы рандомно на разные сервера. Вроде тут из контекста ясно, что дело касается около апликационного слоя (запросы). Не могу подобрать ситуацию, когда это касалось бы бизнес логики

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

Да, но человек не спрашивал "Как архитектурно построить", он спрашивал "Как реализовать". Если ему нужно, он вынесет в любой слой или сделает отдельным микросервисом, реализация останется такой же)

Ну если у него контроллеры и сервисы есть - слои уже есть)

Не, он спросил "как вы решаете такие задачи?"

И видимо по-вашему ответ на это "Решаю задачи на архитектурном уровне"?)

Решаю задачи на уровне разделения на 10050 слоев и создания миллиарда абстракций))

бери мьютекс у БД, по имени вид запроса и пользователю. Когда второй начнет работать, получив лок по завершению первого - запись будет уже удалена. надежнее чем лок записи, который зависит от уровня изоляции и может "сломаться" если появятся еще действия, в дополнение к удалению чтобы ощутить просад быстродействия с таким мьютексом и без него - не знаю какая должна быть ахриненная нагрузка на систему помноженная на курьерскую доставку пакетов между серверами датацентра

Это не про куки, а про IP

Ip может и поменяться, так что к нему точно не стоит привязываться (в контексте изначального вопроса)

по сабжу два ответа, простой способ и сложнее

Хз, по-моему там не нужны липкие сессии, и даже если на их основе делать, привязываться к айпи нельзя

большинство пользователей - добросовестные, и не пытаются что-то сломать, поэтому этот простой способ балансировки часто используют

Это не решает проблему. Плюс добавляет сложности. Помимо того, что нужно sticky session добавлять на уровне балансера, так еще и в коде приложения делать lock в памяти (который не имtт смысла без балансера со sticky session) Вроде простая задача, а всё усложнилось в разы на пустом месте

Да способ ок, но в конкретной ситуации не подходит потому что не даёт гарантию, которую ищет автор вопроса. Если делать липкость на основе юзерайди, это может решить проблему. А на основе ip - нет

читайте второй способ в треде )

И плюс мы залазим в работу балансера, у которого свои цели

Я подходящие варианты и так знаю. Просто посчитал важным для автора вопроса отметить то, что сессии не решат его проблемы

Как же сессии для юзера не решают проблему? U1 отправляется на N1 каждый раз, без сессии на логин, и потом снова на N1, профит

Вроде изначально была проблема в том, что по определенному роуту нужно обрабатывать запрос не больше одного раза от одного пользователя за раз

А где тут включается запрет на обработку запросов по роуту от одного юзера паралельно?

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

Sticky sessions это про раскидывание запросов по определенному сценарию, в конкретном случае, мапить юзера на одну ноду, где хранится состояние о задаче

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

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

Я исхожу из того, что у топикстартера достаточно скилов, чтобы загуглить термин, и найдя огромное количество статей, довести до готовности

Он имеет ввиду что этот костыль вообще не надо доводить до ума. Это плохое решение и к нему можно прибегнуть в очень крайнем случае (я даже хз в каком)

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

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

Господа, а что сейчас вообще с рынком труда на делфи происходит? Какова ситуация?
Rꙮman Yankꙮvsky
29
А вообще, что может смущать в самой Julia - бы сказал, что нет единого стандартного подхода по многим моментам, поэтому многое выглядит как "хаки" и произвол. Короче говоря, с...
Viktor G.
2
30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Добрый день! Скажите пожалуйста, а какие программы вы бы рекомендовали написать для того, чтобы научиться управлять памятью? Можно написать динамический массив, можно связный ...
Филипп
7
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Ребят в СИ можно реализовать ООП?
Николай
33
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
Карта сайта