2016-10-12 4 views
1

Я прочитал статью об обслуживании множества клиентов с помощью настраиваемого сервера HTTP 1.1. Он сказал, что нужно использовать пул потоков с таким количеством потоков, как и ядра ЦП, а не создавать новый поток для каждого запроса. Но, скажем, файл имеет длину 1 ГБ. Это передача остановит одну из очередей в пуле потоков, в то время как файл передается, останавливая обработку новых запросов. Конечно, при передаче таких файлов возникает нить? Но какой критерий применяется для определения того, должен ли быть создан новый поток для обслуживания запроса, размер файла? Или какой-то другой? Возможно, используется какая-то форма совместной многозадачности?HTTP 1.1 сервер, отправляющий большие файлы

+0

Зачем вам возникать новый поток при наличии пула? – SMA

+0

@SMA говорит, что у вас 4 ядра, это означает, скажем, 4 очереди в пуле потоков. Файл GB останавливает одну из четырех очередей, поскольку для переноса файла требуется много времени, оставляя 3 для обработки HTTP-запросов. Если вы создаете новый поток, 4 очереди могут обрабатывать запросы. – user1095108

+0

Написание настраиваемого HTTP-сервера - очень сложная задача (просто прочитайте раздел 3.3.3 и 6 rfc7230). Возможно, вам стоит проверить nginx или Apache 2.4 mpm_event, которые уже управляют такими типами управления потоками и циклы событий tcp/ip. Или даже golang http-обработчики. – regilero

ответ

1

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

Вы можете использовать блокирующий и неблокирующий IO смешанным способом на одном и том же HTTP-сервере. Большинство запросов выполняются быстро, поэтому нет смысла использовать неблокирующий IO.

Может быть хорошей идеей, чтобы длительные запросы использовали неблокирующий IO, чтобы не задерживать слишком много потоков. Передача файлов на 1 ГБ, безусловно, звучит как хороший случай для этого.

Socket IO на HTTP-сервере обычно должен быть неблокирующим. HTTP-серверы часто запускаются в соответствии с предположением многих подключенных клиентов и многолетних подключений. Для создания этого масштаба почти требуется неблокирующий IO. Но учтите, что, хотя сетевая сторона должна быть неблокирующей, не требуется архитектурно требовать, чтобы обработка запросов также не блокировалась.

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

+0

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

+0

Резьбы могут блокироваться, поэтому для насыщения процессора обычно бывает немного (или намного больше). Не все IO должны быть/не должны блокироваться. Глобальная очередь не является обязательной, она может обеспечить справедливость для определенных рабочих элементов. Доступ к локальным очередям осуществляется синхронно. Нет никакого способа обойти это, если вы не хотите, чтобы предметы застряли за головой блокатора строк (как вы упомянули). Большинство приложений не загружаются на 100%, поэтому неравномерно заполненные очереди потоков чрезвычайно распространены. – usr

+0

Если вы хотите хороший, современный пример того, как это работает, посмотрите на .NET. У меня есть пул потоков, как я описал его, и он использует Windows IOCP для неблокирующего ввода-вывода. Блокировка и неблокирование играют хорошо вместе. Это всего лишь один большой пул потоков.Неблокирующие IO не блокируют поток. Завершения ввода-вывода публикуются как рабочие элементы TP. – usr