Сервер UDP - стоит ли асинхронный вызов дополнительной сложности? - PullRequest
3 голосов
/ 20 апреля 2011

Я пишу UDP-серверы, которые должны обрабатывать большое количество клиентов.

Протоколы очень просты - один UDP-пакет приходит и декодируется.Это может потребовать небольшой пакет подтверждения.Результаты обычно хранятся в базе данных.

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

Я мог бы использовать асинхронные вызовы UDP (BeginReceieve, EndReceive), но мне интересно, получу ли я что-нибудь с точки зрения производительности?

Многие люди говорят: «Если вы хотите масштабируемости, вам нужно использоватьасинхронные вызовы ".Вроде бы получена мудрость.Я использовал Twisted ранее, поэтому я не боюсь асинхронного проектирования.

Я понимаю, почему с TCP или даже с некоторыми более сложными протоколами UDP асинхронность хороша.Это помогает избежать одного потока на соединение в TCP-серверах.Но мой протокол на самом деле не требует ожидания, за исключением случаев, когда нечего делать, потому что данные не поступают.

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

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

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

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

Спасибо!

Ответы [ 2 ]

2 голосов
/ 20 апреля 2011

Поскольку вы используете UDP, ваши посылки никогда не блокируются, и вам не нужно мультиплексировать несколько сокетов (или, если вы делаете, только небольшое число).

Таким образом, один поток, выполняющий все, вероятно, будетвсе будет в порядке.

Лично я бы рассматривал использование какой-то причудливой асинхронной структуры в качестве преждевременной оптимизации.Если объем вашего сервера не изменится (например, для его отправки на другие запросы другим серверам), это будет очень просто.


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

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

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

Если ваша спецификация гласит, что «когда получатель получит подтверждение, данные определенно будут храниться в течение длительного времени», то вы должны выполнять действие базы данных синхронно.

0 голосов
/ 25 апреля 2011

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

Но опять же, все дело в цифрах. Сколько процентов процессорного времени вы потратили на предварительную обработку сообщений (0,5% или 15%)? Сколько времени вам нужно для отправки UDP-пакета? ОС будет блокировать вас, пока в буфере не будет достаточно места для отправки сообщения. В большинстве случаев это не проблема, но у вас могут быть определенные обстоятельства.

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

...