Вопрос или проблема
В моей лаборатории есть сервер для измерений, работающий на Ubuntu. И есть программа на C, которая принимает данные через TCP-соединение и должна как можно быстрее отправить ответ.
Конфигурация
- Процессоры: 2 процессора x 4 ядра – Intel(R) Xeon(R) CPU E5345 @ 2.33GHz
- ОЗУ: 12 ГБ
- Сетевой адаптер: Intel Corporation 80003ES2LAN Gigabit Ethernet Controller / 82546EB Gigabit Ethernet Controller
- Сетевой свитч: Cisco Catalyst 2960
- Информация о данных: Данные поступают примерно каждые 10 миллисекунд. Размер блока данных примерно 1000 байт.
Сетевые задержки при получении пакетов очень критичны (десятки микросекунд важны). Я оптимизировал программу до максимума, но у меня нет опыта настройки Ubuntu.
Что можно настроить в Ubuntu, чтобы уменьшить локальную задержку обработки/отправки пакетов?
Честно говоря, я бы не использовал Ubuntu для этого… но есть варианты, которые можно применить к любой версии Linux.
Вам нужно увеличить буферы сетевого стека:
net.core.rmem_default = 10000000
net.core.wmem_default = 10000000
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
Если приложение записывает на диск, возможно, потребуется изменить планировщик/лифт (например, лифт deadline
).
На уровне сервера вы можете изменить губернатор ЦП и управление питанием и частотой ЦП (P-States, C-States).
На уровне ОС вы можете изменить приоритет реального времени вашего приложения (chrt
), оптимизировав для уменьшения прерываний, закрепить его за одним ЦП или группой ЦП (taskset
), а также остановить все ненужные службы или демоны.
Вы также можете ознакомиться с некоторыми предложениями на: Как устранить задержки между 2 хостами Linux
Трудно дать более конкретные рекомендации, не зная оборудования или сетевого оборудования, задействованного в этом.
Если вы направляетесь к высокой производительности, вам, как правило, нужно запустить как можно меньше других (планируемых) процессов, так как они будут мешать вашему приложению.
Linux, подобно классическим операционным системам UNIX, предназначен для одновременного запуска нескольких приложений справедливо и пытается предотвратить недостаток ресурсов, а вы будете стремиться к противоположному – лишить всего остального, кроме вашего приложения. Простые шаги на уровне ОС включают изменение уровня nice и приоритета реального времени вашего приложения, изменение планировщика или переход на реальное время ядро.
TCP/IP обычно настраивается для предотвращения разрывов соединения и эффективного использования доступной полосы пропускания. Чтобы получить наименьшую задержку из очень быстрого соединения, а не максимизировать полосу пропускания соединения, где некоторые промежуточные звенья более ограничены, вам нужно будет настроить сеть.
sysctl -a
покажет вам множество параметров ядра, которые можно настроить. Настройки зависят от того, используете ли вы IPv4 или IPv6 и что именно вы уже делаете в своем приложении, но могут быть интересны:
net.ipv4.tcp_window_scaling=1
RFC 1323 – поддержка для TCP IPv4
размеров окна больше 64K – обычно требуется в сетях с высокой пропускной способностьюnet.ipv4.tcp_reordering=3
Максимальное количество раз, которое пакет IPV4 может
быть переупорядочен в потоке TCP без предположения TCP о потере пакета
и перехода в медленный старт.net.ipv4.tcp_low_latency=1
предназначено
для приоритета низкой задержки над высокой пропускной способностью; установка =1
отключает предварительную очередь ненависти TCP IPv4net.ipv4.tcp_sack=0
установка на 1
включает избирательное подтверждение для IPv4, что требует включения
tcp_timestamps и добавляет некоторую накладную нагрузку на пакеты, вам это не нужно, если
вы не испытываете потери пакетовnet.ipv4.tcp_timestamps=0
Только рекомендуется в случаях, когда необходимо подтверждение.net.ipv4.tcp_fastopen=1
Включите, чтобы отправить данные в начальном SYN пакете.
Большинство, если не все, из них лучше задокументированы в исходниках ядра.
Вы, конечно, можете программировать необработанные TCP-сокеты и в значительной степени обойти стек TCP/IP ядра.
Часто высоконастроенные системы работают в доверенной сети и имеют отключенные свои локальные (iptables) файрволы.
Ответ или решение
Настройки TCP с низкой задержкой на Ubuntu для вашего сервера
Если вы работаете с сервером на Ubuntu, который обрабатывает запросы через TCP и требует низкой задержки для максимальной производительности, есть несколько параметров, которые можно настроить для уменьшения задержек в обработке и отправке пакетов. Ваша система, описанная выше, с двумя процессорами, значительным объемом RAM и качественной сетевой картой, может быть настроена для оптимальной работы.
1. Настройка системных параметров сети
Прежде всего, вы можете изменить параметры сетевых стеков с помощью команды sysctl
. Откройте файл конфигурации для редактирования:
sudo nano /etc/sysctl.conf
Добавьте следующие строки для улучшения обработки TCP:
net.core.rmem_default = 10000000
net.core.wmem_default = 10000000
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_window_scaling=1
net.ipv4.tcp_reordering=3
net.ipv4.tcp_low_latency=1
net.ipv4.tcp_sack=0
net.ipv4.tcp_timestamps=0
net.ipv4.tcp_fastopen=1
После внесения изменений, примените их:
sudo sysctl -p
2. Изменение планировщика процессов
Следующий шаг — изменение параметров планирования вашей программы. Обычно планировщик Linux пытается равномерно распределять ресурсы, но в вашем случае нужно дать приоритет вашему приложению.
Вы можете использовать команду chrt
, чтобы задать реальное время вашим процессам:
sudo chrt -f 99 ./ваша_программа
Это даст вашей программе наивысший приоритет. Также имеет смысл использовать nice
для уменьшения приоритета всех других процессов:
sudo renice -n -10 -p <PID>
3. Прямое управление использованием процессора
С помощью taskset
вы можете "привязать" вашу программу к определенному процессору. Это уменьшит накладные расходы на переключение контекста между ядрами. Например, если вы хотите, чтобы процесс работал только на первом ядре:
taskset -c 0 ./ваша_программа
4. Отключение ненужных служб
Для снижения задержек, обязательно отключите все ненужные службы и демонные процессы, которые могут отвлекать ресурсы системы. Вы можете использовать systemctl
для управления службами:
sudo systemctl stop <имя_службы>
sudo systemctl disable <имя_службы>
5. Тонкая настройка сетевой карты
Еще один важный этап — это настройка вашей сетевой карты. Измените параметры Ethernet, чтобы оптимизировать производительность:
sudo ethtool -G eth0 rx 4096 tx 4096
sudo ethtool -C eth0 rx-usecs 0
Заключение
Применение этих рекомендаций значительно снизит задержки в TCP-соединении и улучшит общую производительность вашего сервера. Обязательно протестируйте каждое изменение и отслеживайте результаты. Если проблема остается, возможно, стоит обратить внимание на уровень сети и оборудование, такие как коммутатор. Попробуйте также отключить брандмауэр, если он не влияет на безопасность вашей системы в данное время, чтобы убедиться, что он не добавляет дополнительную задержку в обработку пакетов.
Эти настройки являются обобщением и могут потребовать дополнительной адаптации в зависимости от вашего конкретного сценария использования и сетевой инфраструктуры.