Как ограничить пропускную способность на соединение с помощью tc?

Вопрос или проблема

Я новичок в Linux и команде tc, и я искал способ ограничить пропускную способность для каждого соединения с помощью tc. У меня есть серверное приложение, которое обрабатывает запросы от клиентов, состоящие из операций ввода-вывода, и я хочу, чтобы каждый запрос достигал максимальной скорости в 50 МБ/с, если есть достаточно пропускной способности (но я гарантирую, что параллельных запросов будет не слишком много, чтобы пропускная способность не упала ниже 50 МБ/с на запрос). Я использовал tc для ограничения пропускной способности, но все соединения делят 50 МБ/с, вместо того чтобы каждое соединение получало 50 МБ/с.

Команды tc, которые я опробовал:

sudo tc qdisc add dev eth4 root netem rate 400mbit

или

sudo tc qdisc add dev eth4 root handle 1: htb default 30
sudo tc class add dev eth4 parent 1: classid 1:1 htb rate 100gbit burst 15k

sudo tc class add dev eth4 parent 1:1 classid 1:10 htb rate 400mbit burst 15k
sudo tc class add dev eth4 parent 1:1 classid 1:20 htb rate 400mbit burst 15k 

sudo tc filter add dev eth4 protocol ip parent 1: prio 1 u32 match ip dst 0.0.0.0/0 flowid 1:10
sudo tc filter add dev eth4 protocol ip parent 1: prio 1 u32 match ip src 0.0.0.0/0 flowid 1:20

или, поскольку я контролирую как сервер, так и клиентов и знаю, что сервер обрабатывает запросы клиентов на порту 9000, я попробовал следующее на клиентской машине:

sudo tc qdisc add dev eth4 root handle 1: prio priomap 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
sudo tc qdisc add dev eth4 parent 1:2 handle 20: netem rate 400mbit
sudo tc filter add dev eth4 parent 1:0 protocol ip u32 match ip dport 9000 0xffff flowid 1:2

Ни одно из решений не сделало того, что я хочу. Я думаю, мне нужно создать класс для каждого порта, через который отправляются запросы, но я не знаю их заранее, так как они выбираются автоматически. Есть ли способ создать эти классы “на ходу” или другое решение?

Ответ или решение

Чтобы ограничить пропускную способность для каждого соединения с помощью команды tc в Linux, нужно использовать подход, который позволяет индивидуально регулировать скорость для каждого соединения. В вашем случае, вы хотите, чтобы каждое соединение имело лимит 50 МБ/с, если это позволяет имеющаяся пропускная способность. Рассмотрим, как это можно реализовать.

Теоретическая часть

tc — это утилита для управления трафиком в Linux, которая позволяет задавать правила для каналов передачи данных и очередей (qdisc). Для настройки лимитов пропускной способности часто используют комбинацию классов и фильтров, чтобы детализированно управлять трафиком.

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

Пример применения

Одним из способов достичь динамического ограничения является использование модуля IMQ (Intermediate Queueing device) совместно с Iptables для маркировки пакетов и затем распределения их в различные классы с разными ограничениями. Однако это более сложный подход и требует модификации ядра.

Ниже приводится более доступное решения с использованием HTB (Hierarchical Token Bucket) для управления полосой пропускания:

  1. Настройка корневого qdisc:
sudo tc qdisc add dev eth4 root handle 1: htb default 30
  1. Создание основного класса с достаточной пропускной способностью:
sudo tc class add dev eth4 parent 1: classid 1:1 htb rate 1000mbit
  1. Создание дочерних классов для ограничения до 50 МБ/с (примерно 400 мбит/с):
sudo tc class add dev eth4 parent 1:1 classid 1:10 htb rate 50mbit
  1. Создание фильтров для направления трафика на данные классы. Это место, где нужен более динамический подход для автоматического создания классов, но этого мы можем достичь только мануально или через скрипты.

Пример использования Iptables для маркировки пакетов:

sudo iptables -t mangle -A PREROUTING -p tcp --dport 9000 -j MARK --set-mark 10
  1. Применение фильтров, чтобы распределить трафик на основе меток:
sudo tc filter add dev eth4 protocol ip parent 1:0 prio 1 handle 10 fw classid 1:10

Применение

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

Мониторинг сети с помощью таких утилит, как netstat, может помочь захватывать активные соединения и динамически применять правила.

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

Оцените материал
Добавить комментарий

Капча загружается...