Многопоточный дизайн для API - PullRequest
0 голосов
/ 24 ноября 2018

Я реализую API.Фронт-эндом, скорее всего, будет REST / HTTP, бэкэнд-MSSQL, с легким промежуточным звеном между ними.Возможно, IIS размещен.

К каждому входящему запросу будет прикреплен неуникальный идентификатор.Любые запросы, которые имеют один и тот же идентификатор, должны обрабатываться сериализованно (и FIFO);тогда как запросы с разными идентификаторами могут (и должны) обрабатываться одновременно для повышения производительности и эффективности.

  1. Предположим, что когда клиенты вызывают мой API, создается новый поток для обработки запроса (поток на модель вызова).
  2. Предположим, что каждый запрос имеет примерно одинаковый размер и одинаковый объем вычислительной работы

Текущий дизайн

Мой текущий дизайн и реализацияочень просто и понятно.Монитор создается для каждого идентификатора, и все запросы обрабатываются в критической части кода, обеспечивающей сериализацию.Другими словами, Monitor for Id X будет блокировать все потоки, несущие запрос с Id X, до тех пор, пока текущий поток, несущий Id X, не завершит свою работу.

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

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

Альтернативный дизайн

Другой дизайн может состоять из более сложной схемы:

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

Недостатком этой конструкции является сложность

Вторым недостатком является то, что будут накладные расходы из-за переключения данных между потоками (по крайней мере, дваждыза запрос)

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

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

  • Вопросы

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

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

1 Ответ

0 голосов
/ 24 ноября 2018

Ваше текущее решение будет ужасно масштабироваться, если количество запросов станет слишком большим (запросы начнут стоять в очереди).Каждый запрос порождает новый поток и также выделяет необходимые ресурсы.
Посмотрите на Модель актера .
Вы бы порождали поток для идентификатора запроса и просто отправляли запросы через"message" для актера.
Подумайте об использовании ленивой инициализации для актеров, что означает, что вы порождаете поток, только если на самом деле происходит запрос на ID.Если очередь сообщений актера пуста, вы можете прекратить их и только порождать их снова, если поступает новый запрос с его идентификатором.
Реализация, сделанная с Threadpool , также должна помочь с производительностью вбудущее.

...