Я реализую API.Фронт-эндом, скорее всего, будет REST / HTTP, бэкэнд-MSSQL, с легким промежуточным звеном между ними.Возможно, IIS размещен.
К каждому входящему запросу будет прикреплен неуникальный идентификатор.Любые запросы, которые имеют один и тот же идентификатор, должны обрабатываться сериализованно (и FIFO);тогда как запросы с разными идентификаторами могут (и должны) обрабатываться одновременно для повышения производительности и эффективности.
- Предположим, что когда клиенты вызывают мой API, создается новый поток для обработки запроса (поток на модель вызова).
- Предположим, что каждый запрос имеет примерно одинаковый размер и одинаковый объем вычислительной работы
Текущий дизайн
Мой текущий дизайн и реализацияочень просто и понятно.Монитор создается для каждого идентификатора, и все запросы обрабатываются в критической части кода, обеспечивающей сериализацию.Другими словами, Monitor for Id X будет блокировать все потоки, несущие запрос с Id X, до тех пор, пока текущий поток, несущий Id X, не завершит свою работу.
Преимуществом этого текущего проекта является простота (его было легковоплощать в жизнь).Второе преимущество заключается в том, что при переключении данных между потоками не возникает никаких затрат: каждый поток несет запрос на всем пути от его первоначального поступления в API до отправки ответа клиенту.
Одним из возможных недостатков является то, что, когда многие запросы поступают с одним и тем же идентификатором, будет много блоков, блокирующих (и, в конечном счете, снова разблокирующих). Другой возможный недостаток заключается в том, что эта конструкция не поддается асинхронному коду для потенциально увеличивающейся масштабируемостискорее всего, придется реализовать и другими способами).
Альтернативный дизайн
Другой дизайн может состоять из более сложной схемы:
- Создайте выделенную коллекцию BlockingCollection для каждого обнаруженного идентификатора. Создайте отдельный выделенный длительный потребительский поток для каждой коллекции BlockingCollection
- Каждый поток, который обрабатывает запрос, действует как производитель, помещая запрос в соответствующий BlockingCollec.
- Производящий поток затем ждет (в асинхронном стиле), пока ответ не будет готов к сбору
- Каждый потребительский поток обрабатывает элементы из своей очереди BlockingCollection в последовательной форме и сигнализирует потоку, чтоожидает ответа, как только ответ будет готов
Недостатком этой конструкции является сложность
Вторым недостатком является то, что будут накладные расходы из-за переключения данных между потоками (по крайней мере, дваждыза запрос)
Тем не менее, я думаю, что в достаточно загруженной системе, куда поступает много запросов, это может быть лучше при уменьшении количества блокирующих потоков;И, возможно, общее количество требуемых потоков будет меньше.
Он также лучше подходит для асинхронного кода, чем оригинальный дизайн, что может улучшить его масштабирование.
Учитывая трудоемкость и сложность повторной реализации с использованием альтернативного дизайна, может ли это быть целесообразным?(В данный момент я склоняюсь к «НЕТ» и придерживаюсь своего нынешнего замысла: но любые взгляды или общие мысли будут высоко оценены.)
Если нет прямого ответа на поставленный выше вопрос, то каковыключевые соображения, которые мне необходимо учитывать при принятии решения?