Передача UDP слишком быстрая, Apache Mina не справляется с этим

Мы решили использовать UDP для отправки большого количества данных, таких как координаты, между:

  • клиент [C++] (используя опрос)
  • сервер [JAVA] [Apache MINA]

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

Каждая дейтаграмма имеет заголовок, который я добавил (с идентификатором внутри), чтобы я мог отслеживать:

  • сколько дейтаграмм получено
  • какие из них получены

Проблема в том, что мы отправляем дейтаграммы слишком быстро. Мы получаем как в первый раз, а потом имеем большой убыток, а потом получаем, и снова большой убыток. Последовательность полученных дейтаграмм ID выглядит примерно так: [1], [2], [250], [251]...

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

Итак, мои вопросы здесь:

  • On client, how can I get the best :
    • settings, or socket settings?
    • способ отправить столько, сколько я могу, не будучи слишком много?
  • На сервере Apache MINA, кажется, говорит, что он сам управляет ~ «размером буферного сокета» ~, но есть ли еще какие-то настройки, о которых нужно заботиться?
  • Можно ли достичь примерно 1 МБ/с, зная, что наше соединение уже позволяет нам иметь хотя бы эту пропускную способность при загрузке обычных файлов?

В настоящее время, когда мы хотим передать информацию о координатах ~ 4 КБ, мы должны добавить время ожидания, чтобы мы ждали 5 минут или более, чтобы закончить его, это большая проблема для нас, зная, что мы должны отправлять каждую минуту не менее 10 МБ координаты информации.


person itMaxence    schedule 01.10.2015    source источник
comment
Я бы начал с установки wireshark, чтобы убедиться, что пакеты попадают в коробку. Также можно поиграться с размером буфера UDP ОС. Звучит подозрительно, даже если мина слишком медленно их обрабатывает, ОС должна буферизоваться.   -  person MK.    schedule 01.10.2015
comment
чтобы передать информацию о координатах ~4 КБ, мы должны добавить время ожидания, чтобы мы ждали 5 минут или более Это 1 пакет каждые 40 секунд... Было бы быстрее переключиться на телеграф и азбуку Морзе.   -  person ElderBug    schedule 01.10.2015
comment
Например, в Windows сетевой стек будет отбрасывать дейтаграммы UDP (как это разрешено), если его буферы заполнятся — попробуйте увеличить размер буфера для проверки.   -  person SChepurin    schedule 01.10.2015
comment
Это похоже на проблему перегрузки, поэтому вам потребуется некоторый контроль перегрузки или, по крайней мере, ограничение отправки. Но 4 КБ за 5 минут создают впечатление, что проблема намного больше, возможно, в вашем коде.   -  person ElderBug    schedule 01.10.2015
comment
@SChepurin Мое приложение потребляет 1 ТБ на моем жестком диске, когда не должно, ваш ответ: купите жесткий диск на 2 ТБ. Это не решение.   -  person ElderBug    schedule 01.10.2015
comment
@ElderBug - видел, чтобы проверить в конце? Это тест, а не решение (какое решение без кода можно посоветовать?).   -  person SChepurin    schedule 01.10.2015
comment
Просто для проверки, но это сценарий загрузки (клиент-сервер)? Первым шагом должно быть получение сетевой трассировки. Возьмите WireShark и узнайте, дошли ли недостающие пакеты до сети. После этого вы, вероятно, можете обвинить одну сторону в › 99% потери пакетов.   -  person MSalters    schedule 01.10.2015
comment
Чем дольше я думаю об этом, тем хуже становится. 4 КБ за 5 минут? Это примерно 1 пакет за 30 секунд. Я полагаю, что единственный способ быть таким плохим — это (1) выполнять поиск нового имени для каждой отправки, (2) настроить поиск имени как DNS-затем-и т. д./хост и (3) иметь тайм-аут поиска DNS через 30 секунд при каждой отправке. Либо так, либо что-то столь же эпически глупое.   -  person MSalters    schedule 01.10.2015
comment
Хорошая идея, я в первую очередь проверю Wireshark. Мои слова о времени передачи не совсем то, что я написал, но это объясняет, по крайней мере, насколько медленным он может быть. Я буду держать вас в курсе.   -  person itMaxence    schedule 01.10.2015


Ответы (2)


Если вам нужен надежный транспорт, вы должны использовать TCP. Это позволит вам отправлять почти так же быстро, как медленнее сеть и клиент, без потерь.

Если вам нужен оптимизированный транспорт с малой задержкой, который не должен быть надежным, вам нужен UDP. Это позволит вам отправлять точно так же быстро, как сеть может обрабатывать, но вы также можете отправлять быстрее или быстрее, чем клиент может прочитать, и тогда вы потеряете пакеты.

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

... как я могу получить лучшие настройки или настройки сокета

Обычно опытным путем.

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

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

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

Вам нужно какое-то сообщение ack/nack/противодавление/дросселирование/перегрузка/любое сообщение от получателя обратно к источнику. Это именно то, что TCP дает вам бесплатно, и что довольно сложно реализовать самостоятельно.

Можно ли достичь чего-то вроде 1 МБ/с...

Я только что видел 8 МБ/с при использовании scp поверх обратной связи, поэтому я бы сказал да. Это использует TCP и, по-видимому, выбрал AES128 для шифрования и дешифрования файла на лету - должно быть тривиально, чтобы получить эквивалентную производительность, если вы просто отправляете открытый текст.

person Useless    schedule 01.10.2015
comment
Я проведу несколько экспериментов. Но моя цель сегодня — передать большое количество данных как можно быстрее, не заботясь о том, будет ли потеря 1% или 30%, но сейчас моя проблема — просто заставить UDP работать нормально. Я расследую больше и буду держать вас в курсе. Спасибо - person itMaxence; 01.10.2015

UDP является жизнеспособным выбором только тогда, когда любое количество дейтаграмм может быть потеряно без ущерба для QoS. Я не знаком с Apache MINA, но описанный сценарий напоминает сервер, который последовательно обрабатывает каждую дейтаграмму. В этом случае все дейтаграммы, поступившие во время обслуживания одной, будут потеряны - очередность UDP-дейтаграмм отсутствует. Как я уже сказал, я не знаю, можно ли настроить MINA для параллельной обработки дейтаграмм, но если нет, то это просто неправильный выбор инструментов.

person SergeyA    schedule 01.10.2015
comment
Я относительно уверен, что вы ошибаетесь в этом. ОС ставит в очередь полученные UDP-пакеты. - person MK.; 01.10.2015
comment
Поскольку дейтаграмма UDP может иметь размер до 64 КБ, системные буферы почти гарантированно вмещают 128 пакетов по 512 байт. Даже с плохо закодированным приложением было бы трудно отбрасывать пакеты таким образом. - person ElderBug; 01.10.2015
comment
Это то, что я видел своими глазами, поэтому я придерживаюсь этого. - person SergeyA; 01.10.2015
comment
*NIX обычно ставит пакеты в очередь в буфер фиксированного размера и затем молча отбрасывает пакеты, которые не помещаются в буфер. На отправителе нет обратного давления или дросселирования. Итак, @МК. прав в том, что пакеты ставятся в очередь, и СергейА прав в том, что пакеты отбрасываются. Я понятия не имею, что могут делать другие ОС. - person Useless; 01.10.2015
comment
@ Бесполезно, я бы добавил, что это делает не * NIX, а стек. Тем не менее, я также должен признать, что мой опыт в этом вопросе может быть связан с некоторыми экзотическими стеками. - person SergeyA; 01.10.2015
comment
Как написано, это чистый бред. Обработка одного UDP-пакета приводит к потере всех последующих пакетов?! Обработка никогда не вызывает этого. Это может быть вызвано переполнением буфера, но начиная с Linux 2.6 (много лет назад) эти буферы составляют 4 МБ = 8192 пакета по 512 байт. - person MSalters; 01.10.2015
comment
Линукс. Единственная известная нам система. - person SergeyA; 01.10.2015