Изменение SetWriteBuffer и SetReadBuffer - PullRequest
0 голосов
/ 13 марта 2020

Описание

Я занят написанием высокочастотного UDP-сервера с Go. Я бы оценил по крайней мере 1000 пакетов в секунду в обоих направлениях.

Однако, с ростом размера данных, которые я отправляю через сокет UDP, я в итоге столкнулся с следующей ошибкой: read udp 127.0.0.1:1541->127.0.0.1:9737: wsarecv: A message sent on a datagram socket was larger than the internal message buffer or some other network limit, or the buffer used to receive a datagram into was smaller than the datagram itself.

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

buffer := make([]byte, 64 * 1024 * 1024) // used to just be 1024
l, err := s.socketSim.Read(buffer)

Это работало нормально, и я перестал получать ошибку ... Однако тогда я могу справиться с двумя функциями внутри net пакет:

s.socketSim.SetWriteBuffer(64 * 1024 * 1024)
s.socketSim.SetReadBuffer(64 * 1024 * 1024)

Я узнал, что эти два действия влияют на operating system's transmit buffer

Вопрос

Не хочу ли я задать размер буфера операционной системы и почему? Как размер буфера приложения влияет на размер буфера операционной системы? Должны ли они всегда быть одинаковыми и насколько большими они могут / могут стать?

1 Ответ

1 голос
/ 14 марта 2020

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

Во-вторых, вы почти наверняка хотите, чтобы ваши буферы SND / RCV были больше, чем MTU. Это буферы ядра, которые сохраняют данные, когда вы не готовы их получить. Больший буфер RCV UDP означает, что ядро ​​будет буферизовать больше пакетов вместо вас, прежде чем выбросить их в пропасть. Возможно, у вас есть нетривиальная работа для каждого пакета. В зависимости от битрейта может потребоваться больший или меньший буфер ядра.

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

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

Если вы включены linux, вы можете увидеть текущие размеры буфера в / proc / sys /net. Обычно ядро ​​удваивает то, что вы просите.

Кроме того, вы можете настроить размер буфера, наблюдая за отбрасыванием пакетов в / proc / net / udp. Если вы видите дропс, вы можете захотеть увеличить буфер rcv, особенно если данные загружены и интенсивно обрабатываются. Если ваши данные поступают с постоянной скоростью и вы все еще отбрасываете пакеты, значит, вы не обрабатываете их достаточно быстро.

...