высокопроизводительный сервер udp.блокирующий или неблокирующий?с - PullRequest
8 голосов
/ 10 февраля 2010

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

немного предыстории о моем собственном наборе проблем, чтобы ответы могли быть применены как конкретно, так и к общей природе вопроса. У меня есть сервер udp, который я пишу, который будет иметь 40 подключений на локальной сети, благодаря чему будет поступать постоянный поток данных. Скорости передачи данных будут около 250 МБ / с в среднем с пиковыми значениями до 500 + МБ / с с avg размер датаграммы около 1400 байт. обработка дейтаграмм невелика, но из-за большого объема сообщений эффективность и производительность сообщения являются приоритетными для предотвращения потери пакетов.

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

С уважением, Джим.

~ ~ редактировать

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

~ edit2 ~

Во-первых, я хотел сказать, что покажите вам ответы. некоторые из вас упоминали, что модель с одним потоком / сокетом с таким количеством сокетов может быть плохой идеей, и я признаю, что я сам пробовал с решением. однако в одной из ссылок в ответе Николая автор обсуждает модель с одним потоком / сокетом и ссылается на очень интересную статью, на которую, как я думал, я буду ссылаться, поскольку она рассеивает множество мифов, которые я держал о потоках против события основанные модели: почему события плохая идея

наслаждаться.

Ответы [ 4 ]

5 голосов
/ 10 февраля 2010

Не ответ, просто некоторые ссылки, если у вас их еще нет в закладках:

Проблема C10K Дана Кегеля,
Высокопроизводительная серверная архитектура Джефф Дарси,
Расширенные API опроса: epoll(4), kqueue(2).

Edit:

Как бы глупо это не звучало, но я полностью упустил, что вы работаете с UDP, так что ...

Поскольку в UDP нет соединений на уровне протокола, и если не нужно работать на разных портах, вам не нужно 40 сокетов на сервере . Просто один UDP "серверный" сокет подойдет для всех клиентов. Вы можете заблокировать на этом одном сокете все, что вам нравится, просто убедитесь, что буфер приема сокета достаточно велик для размещения пиков трафика и не тратит слишком много времени на обработку каждого чтения.

2 голосов
/ 11 февраля 2010
  • при использовании блокирования ввода-вывода, в какой-то момент в вашей программе у вас должен быть опрос или выборка, ожидающая данных на любом из ваших файловых дескрипторов (в вашем случае сокетов). Потому что, если вы прочитаете какой-либо из ваших fh, не убедившись, что данные на нем готовы, он заблокируется, и программа перестанет управлять другими сокетами. Чтобы избежать этого и сохранить простую программу, программы, использующие блокировку ввода-вывода, часто пишутся с одним потоком для каждого сокета / fh, что позволяет избежать необходимости опроса или выбора.

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

Я считаю, что наиболее эффективным подходом является использование poll или select для управления несколькими IO одновременно (это может быть подмножество всех файловых дескрипторов, разделенных между потоками, если вы предпочитаете). Это более эффективно, чем неблокирующий ввод-вывод без опроса или выбора, потому что этот метод в большинстве случаев пытается бесполезно читать все сокеты, и это требует затрат. Наихудший метод между этими тремя - использовать блокировку ввода-вывода с одним fh для каждого потока из-за высокой стоимости управления потоками по сравнению с чтением, возвращающим WOULDBLOCK или опросом.

Это говорит о том, что неблокирующее IO имеет еще одно преимущество: ваша программа может выполнять вычисления помимо IO, и когда блокируется в ожидании IO, вы не можете этого сделать. Это может привести к использованию poll / select с неблокирующим вводом-выводом, или его использованию с небольшим таймаутом, или даже к использованию небольшого специализированного потока, выделенного для ввода-вывода и других потоков, для более требовательных к вычислениям деталей или программы.

В некоторых случаях у вас также может не быть выбора. Мне пришлось ждать данных от дескриптора файла, смонтированного через NFS. В таком случае попытка установить неблокирующий ввод-вывод бесполезна, потому что уровень NFS использует блокирующий ввод-вывод внутренне ...

Вы также можете рассмотреть возможность использования асинхронного ввода-вывода. Это очень эффективно, ваша программа становится «управляемой событиями». Это вполне обычно для систем Windows, я не смотрел текущее состояние разработки асинхронного ввода-вывода для Linux. В прошлый раз я проверял некоторых людей, которые работают над добавлением асинхронного ввода-вывода в API ядра, но я не знаю, стабильно ли оно или достигло основных ядер.

2 голосов
/ 10 февраля 2010

Я не знаю, что блокирование или неблокирование имеет значительное преимущество в производительности; это больше вопрос о том, что хотят делать циклы событий сетевого ввода-вывода:

  • Если единственная вещь, которую ваш сетевой поток ввода-вывода когда-либо собирается сделать, это прослушивать входящие пакеты UDP на одном сокете, то блокировка ввода-вывода, вероятно, будет работать нормально и будет легче программироваться.

  • Если ваш сетевой поток ввода-вывода должен обрабатывать более одного сокета, то блокировка ввода-вывода становится проблематичной, поскольку, если он блокирует сокет A, он не будет разбужен для обработки данных, поступающих на розетка B или наоборот. В этом случае предпочтителен неблокирующий ввод / вывод, поскольку вы можете выполнить блокировку с помощью select () или poll (), которая будет возвращаться всякий раз, когда данные доступны на любом из отслеживаемых сокетов.

Обратите внимание, что даже в неблокирующем случае вы не захотите зацикливаться между пакетами, поскольку запись циклов ЦП в потоке A означает, что они не будут доступны для потока B, что снизит производительность. Так что если вы не блокируете в recv (), убедитесь, что блокировали в select () или poll ().

0 голосов
/ 10 февраля 2010

Я не уверен, что использование 40 потоков для 40 сокетов - отличная идея ... Конечно, использование потока на сокет имеет смысл, когда у вас небольшое количество сокетов, однако наличие такого количества потоков просто требует потока голодание, тупик и пропущенные пакеты.

Что касается блокирования и неблокирования, помните, что блокировка может быть относительно дорогой ... хотя, на мой взгляд, с ней легче работать. Асинхронные триггеры и т. Д., Вероятно, в целом быстрее, чем необходимость блокировать / пробуждать поток.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...