Среда: Ubuntu 16.04 - Linux, компиляция C ++ 11 с использованием GCC. Программное обеспечение не обязательно должно быть кроссплатформенным - оно должно эффективно выполнять свою задачу и быть отличным демоном.
На данный момент у меня есть довольно простое приложение, которое в основном действует как посредник между сторонней службой и подключением к веб-сокету. поэтому пользователи подключаются к моей службе через веб-сокет, чтобы поговорить с указанной сторонней службой.
| End-User | <-C1-> | My Application | <-C2-> | 3rd Party Service |
В настоящее время мое приложение имеет два основных потока:
Поток 1 - слушает соединение с веб-сокетом, всякий раз, когда он получает сообщение, он помещает в очередь задач fifo объект, который содержит сообщение и соединение с веб-сокетом, которое запросило указанное сообщение.
Поток 2 - проходит через очередь сообщений, выводит сообщение и обрабатывает его.
Проблема в том, что Thread 1 довольно быстр и может легко обрабатывать сотни подключений к веб-сокетам. Поток 2 время от времени блокирует задачи и может быть медленным, поскольку обработка определенных элементов очереди занимает некоторое время указанной сторонней службой. Это означает, что если пользователь A запрашивает 1, ответ на который занимает 5 секунд, то пользователь B, который пришел позже и сделал запрос 2, должен будет дождаться завершения запроса 1 пользователя A, даже если запрос 2 занимает менее 1 мс.
Предлагаемое мной решение этой проблемы:
- Поток 1 - прослушиватель подключения WebSocket
- Делегатор задач потока 2
- Тема 3 - 100 - Рабочие задачи
Поток 1 может легко обрабатывать сотни подключений к веб-сокетам, и каждое соединение может выполнять запросы задачи, которые могут занимать от 1 мс до 1 минуты. все нити 3 - 100 спят. Причина такого большого количества потоков заключается в том, что при наличии 50-60 соединений, которые все выполняют разные длительные запросы, каждый из этих трудоемких вызовов блокирует только один поток, другие потоки по-прежнему могут работать с очередью, и делать другие задачи.
Я знаю, что переключение потоков - это интенсивная операция, но я не знаю другого подхода, кроме многопоточности.
Я решил ту же проблему с одним потоком, но проблема заключалась в том, что сервер прекратил обрабатывать любые сообщения веб-сокета, когда он блокировался, ожидая сторонней службы. Поэтому я увеличил его до двух потоков - один для веб-сокета, а другой для обработки очереди задач. Но теперь проблема в том, что один рабочий процесс в очереди задач работает медленно, поскольку он последовательно обрабатывает блокирующие операции ввода-вывода.
Звучит как ужасная дизайнерская идея? Есть мысли о лучших практиках?