У меня есть сервер, прослушивающий сокеты, какой хороший подход к обслуживанию запросов, привязанных к процессору, с несколькими потоками?
-
19-09-2019 - |
Вопрос
У меня есть приложение, написанное на C ++, которое использует boost::asio.Он прослушивает запросы в сокете и для каждого запроса выполняет некоторую работу, связанную с процессором (напримернет дискового или сетевого ввода-вывода), а затем выдает ответ.
Это приложение будет работать в многоядерной системе, поэтому я планирую иметь (как минимум) 1 поток на ядро для параллельной обработки запросов.
Какой здесь наилучший подход?Есть о чем подумать:
- Мне понадобится пул потоков фиксированного размера (например1 поток на процессор)
- Если поступает больше запросов, чем у меня потоков, то их нужно будет поставить в очередь (возможно, на уровне сокетов o / s?)
В настоящее время сервер является однопоточным:
- Он ожидает запроса клиента
- Как только он получает запрос, он выполняет работу и записывает ответ обратно, затем начинает ждать следующего запроса
Обновить:
Более конкретно:какой механизм я должен использовать, чтобы гарантировать, что если сервер занят, входящие запросы будут поставлены в очередь?Какой механизм я должен использовать для распределения входящих запросов между N потоками (по 1 на ядро)?
Решение
Я не вижу, чтобы было что-то, что вы еще не рассмотрели, заслуживающее внимания.
Если он действительно привязан к процессору, то добавление потоков, превышающих количество ядер, вам не сильно поможет за исключением если у вас будет много запросов.В этом случае очередь прослушивания может соответствовать или не соответствовать вашим потребностям, и, возможно, было бы лучше иметь несколько потоков, которые принимали бы соединения и ставили их в очередь самостоятельно.Проверьте значения listen backlog для вашей системы и немного поэкспериментируйте с количеством потоков.
Обновить:
listen() имеет второй параметр, который является запрошенной вами глубиной очереди OS / TCP.Вы можете настроить его на пределе возможностей операционной системы.Кроме того, вам нужно поиграть с системными ручками.В моей текущей системе он равен 128, так что он не огромен, но и не тривиален.Проверьте свою систему и подумайте, действительно ли вам нужно что-то большее, чем стандартное.
Помимо этого, есть несколько направлений, в которых вы можете пойти.Рассмотрим поцелуй - никаких сложностей до того, как он действительно понадобится.Начните с чего-то простого, например, просто попросите поток принять соединение (до некоторого предела) и поместите их в очередь.Рабочие потоки забирают их, обрабатывают, записывают результат и закрывают сокет.
При нынешних темпах обновления моего дистрибутива Boost (и моем нежелании компилировать его самостоятельно) я начну играть с ASIO только в 2012 году, так что я ничего не могу с этим поделать.
Другие советы
туз http://www.cs.wustl.edu /~шмидт/ТУЗ/книга 1/
Здесь есть все, что вам нужно.Управление потоками и очередями и в качестве дополнительного бонуса портативный способ написания серверов сокетов.
Если вы используете перегруженный конструктор basic_socket_acceptor для привязки и прослушивания заданной конечной точки, он использует SOMAXCONN в качестве списка незавершенных подключений в вызове listen().Я думаю (не очень уверен), что это соответствует 250 в Windows.Таким образом, поставщик сетевых услуг будет (молча) принимать клиентские подключения до этого предела и ставить их в очередь для обработки вашим приложением.Ваш следующий вызов accept приведет к появлению соединения из этой очереди.