Многопоточный дизайн для API

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Вопросы

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

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

1 ответ

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

Другие вопросы по тегам