350 lines
20 KiB
Markdown
350 lines
20 KiB
Markdown
[Документация](../../README-ru.md#документация) → [Конфигурация](../config.ru.md) → Параметры сетевого протокола
|
||
|
||
-----
|
||
|
||
[Read in English](network.en.md)
|
||
|
||
# Параметры сетевого протокола
|
||
|
||
Данные параметры используются клиентами и OSD и влияют на логику сетевого
|
||
взаимодействия между клиентами, OSD, а также etcd.
|
||
|
||
- [osd_network](#osd_network)
|
||
- [osd_cluster_network](#osd_cluster_network)
|
||
- [use_rdma](#use_rdma)
|
||
- [use_rdmacm](#use_rdmacm)
|
||
- [disable_tcp](#disable_tcp)
|
||
- [rdma_device](#rdma_device)
|
||
- [rdma_port_num](#rdma_port_num)
|
||
- [rdma_gid_index](#rdma_gid_index)
|
||
- [rdma_mtu](#rdma_mtu)
|
||
- [rdma_max_sge](#rdma_max_sge)
|
||
- [rdma_max_msg](#rdma_max_msg)
|
||
- [rdma_max_recv](#rdma_max_recv)
|
||
- [rdma_max_send](#rdma_max_send)
|
||
- [peer_connect_interval](#peer_connect_interval)
|
||
- [peer_connect_timeout](#peer_connect_timeout)
|
||
- [osd_idle_timeout](#osd_idle_timeout)
|
||
- [osd_ping_timeout](#osd_ping_timeout)
|
||
- [max_etcd_attempts](#max_etcd_attempts)
|
||
- [etcd_quick_timeout](#etcd_quick_timeout)
|
||
- [etcd_slow_timeout](#etcd_slow_timeout)
|
||
- [etcd_keepalive_timeout](#etcd_keepalive_timeout)
|
||
- [etcd_ws_keepalive_interval](#etcd_ws_keepalive_interval)
|
||
- [etcd_min_reload_interval](#etcd_min_reload_interval)
|
||
- [tcp_header_buffer_size](#tcp_header_buffer_size)
|
||
- [min_zerocopy_send_size](#min_zerocopy_send_size)
|
||
- [use_sync_send_recv](#use_sync_send_recv)
|
||
|
||
## osd_network
|
||
|
||
- Тип: строка или массив строк
|
||
|
||
Маски подсетей (IPv4 или IPv6) публичной сети или сетей OSD. Каждый OSD слушает
|
||
один и тот же порт на всех адресах поднятых (UP + RUNNING) сетевых интерфейсов,
|
||
соответствующих одной из указанных сетей. Порт выбирается автоматически, если
|
||
только [bind_port](osd.ru.md#bind_port) не задан явно. Адреса для подключений можно
|
||
также переопределить явно, задав [bind_address](osd.ru.md#bind_address). Если сети OSD
|
||
не заданы вообще, OSD слушает все адреса (0.0.0.0).
|
||
|
||
## osd_cluster_network
|
||
|
||
- Тип: строка или массив строк
|
||
|
||
Маски подсетей (IPv4 или IPv6) отдельной кластерной сети или сетей OSD.
|
||
То есть, OSD будут всегда стараться использовать эти сети для соединений
|
||
с другими OSD, а клиенты будут стараться использовать сети из [osd_network](#osd_network).
|
||
|
||
## use_rdma
|
||
|
||
- Тип: булево (да/нет)
|
||
- Значение по умолчанию: true
|
||
|
||
Попробовать использовать RDMA через libibverbs для связи при наличии
|
||
доступных устройств. Отключите, если вы не хотите, чтобы Vitastor
|
||
использовал RDMA. TCP-клиенты также могут работать с RDMA-кластером,
|
||
так что отключать RDMA может быть нужно, только если у клиентов есть
|
||
RDMA-устройства, но они не имеют соединения с кластером Vitastor.
|
||
|
||
`use_rdma` работает с RoCEv1/RoCEv2 сетями, но не работает с iWARP и
|
||
может не работать с частью конфигураций Infiniband, требующих RDMA-CM.
|
||
Рассмотрите включение `use_rdmacm` для таких сетей.
|
||
|
||
## use_rdmacm
|
||
|
||
- Тип: булево (да/нет)
|
||
- Значение по умолчанию: false
|
||
|
||
Использовать альтернативную реализацию RDMA на основе RDMA-CM (Connection
|
||
Manager). Работает со всеми типами RDMA-сетей: Infiniband, iWARP и
|
||
RoCEv1/RoCEv2, и даже позволяет полностью отключить TCP и работать
|
||
только на RDMA. OSD используют случайные номера портов для ожидания
|
||
соединений через RDMA-CM, отличающиеся от их TCP-портов. Также при
|
||
включении `use_rdmacm` автоматически отключается опция `use_rdma`.
|
||
|
||
## disable_tcp
|
||
|
||
- Тип: булево (да/нет)
|
||
- Значение по умолчанию: true
|
||
|
||
Полностью отключить TCP и использовать только RDMA-CM для соединений с OSD.
|
||
|
||
## rdma_device
|
||
|
||
- Тип: строка
|
||
|
||
Название RDMA-устройства для связи с Vitastor OSD (например, "rocep5s0f0").
|
||
Если не указано, Vitastor попробует найти RoCE-устройство, соответствующее
|
||
[osd_network](osd.en.md#osd_network), предпочитая RoCEv2, или выбрать первое
|
||
попавшееся RDMA-устройство, если RoCE-устройств нет или если сеть `osd_network`
|
||
не задана. Также автовыбор не поддерживается со старыми версиями библиотеки
|
||
libibverbs < v32, например в Debian 10 Buster или CentOS 7.
|
||
|
||
Запустите `ibv_devinfo -v` от имени суперпользователя, чтобы посмотреть
|
||
список доступных RDMA-устройств, их параметры и возможности.
|
||
|
||
Обратите внимание, что если вы используете RoCE/RoCEv2, вам также необходимо
|
||
правильно настроить для него коммутаторы, иначе вы можете столкнуться с
|
||
нестабильной производительностью. Подробную информацию о настройке
|
||
коммутатора для RoCEv2 ищите в документации производителя. Обычно это
|
||
подразумевает настройку сети без потерь на основе PFC (Priority Flow
|
||
Control) и ECN (Explicit Congestion Notification).
|
||
|
||
Vitastor поддерживает все модели адаптеров, включая те, у которых нет
|
||
поддержки ODP (On-Demand Paging), например, ConnectX-3 и карты производства
|
||
не Mellanox. Функция ODP доступна только на адаптерах Mellanox ConnectX-4 и
|
||
более новых и позволяет не регистрировать память для её использования RDMA-картой,
|
||
благодаря чему в теории можно избежать лишних копирований памяти.
|
||
|
||
Версии Vitastor до 1.2.0 включительно требовали ODP, потом функция был отключена
|
||
по умолчанию, но поддерживалась вплоть до версии 3.0.3. Сейчас поддержка ODP
|
||
полностью удалена, так как на самом деле она только портит производительность:
|
||
например, на 3-узловом кластере с 8 NVMe в каждом узле и сетью 2*25 Гбит/с на
|
||
чтение с RDMA без ODP удаётся снять 3950000 iops, а с ODP - всего 239000 iops.
|
||
|
||
Это происходит из-за того, что реализация ODP у Mellanox неоптимальная и
|
||
основана на повторной передаче сообщений, когда карте не известен буфер -
|
||
вероятно, на стандартных "RNR retransmission" (RNR = receiver not ready).
|
||
А данные повторные передачи в RDMA/RoCE - всегда очень медленная штука.
|
||
Презентация на эту тему с конференции ISPASS-2021: https://tkygtr6.github.io/pub/ISPASS21_slides.pdf
|
||
|
||
## rdma_port_num
|
||
|
||
- Тип: целое число
|
||
|
||
Номер порта RDMA-устройства, который следует использовать. Имеет смысл
|
||
только для устройств, у которых более 1 порта. Чтобы узнать, сколько портов
|
||
у вашего адаптера, посмотрите `phys_port_cnt` в выводе команды
|
||
`ibv_devinfo -v`.
|
||
|
||
Опция неприменима к RDMA-CM (use_rdmacm).
|
||
|
||
## rdma_gid_index
|
||
|
||
- Тип: целое число
|
||
|
||
Номер глобального идентификатора адреса RDMA-устройства, который следует
|
||
использовать. Разным gid_index могут соответствовать разные протоколы связи:
|
||
RoCEv1, RoCEv2, iWARP. Чтобы понять, какой нужен вам - смотрите строчки со
|
||
словом "GID" в выводе команды `ibv_devinfo -v`.
|
||
|
||
Если не указан, Vitastor попробует автоматически выбрать сначала GID,
|
||
соответствующий RoCEv2 IPv4, потом RoCEv2 IPv6, потом RoCEv1 IPv4, потом
|
||
RoCEv1 IPv6, потом IB. Авто-выбор GID не поддерживается со старыми версиями
|
||
libibverbs < v32.
|
||
|
||
Правильный rdma_gid_index для RoCEv2, как правило, 1 (IPv6) или 3 (IPv4).
|
||
|
||
Опция неприменима к RDMA-CM (use_rdmacm).
|
||
|
||
## rdma_mtu
|
||
|
||
- Тип: целое число
|
||
|
||
Максимальная единица передачи (Path MTU) для RDMA. Должно быть равно 1024,
|
||
2048 или 4096. По умолчанию используется значение MTU RDMA-устройства.
|
||
|
||
## rdma_max_sge
|
||
|
||
- Тип: целое число
|
||
- Значение по умолчанию: 128
|
||
|
||
Максимальное число записей разделения/сборки (scatter/gather) для RDMA.
|
||
OSD в любом случае согласовывают реальное значение при установке соединения,
|
||
так что менять этот параметр обычно не нужно.
|
||
|
||
## rdma_max_msg
|
||
|
||
- Тип: целое число
|
||
- Значение по умолчанию: 132096
|
||
|
||
Максимальный размер одной RDMA-операции отправки или приёма.
|
||
|
||
## rdma_max_recv
|
||
|
||
- Тип: целое число
|
||
- Значение по умолчанию: 16
|
||
|
||
Максимальное число буферов для RDMA-приёма данных на одно соединение
|
||
(RDMA требует заранее выделенных буферов для приёма данных). Каждый буфер
|
||
имеет размер `rdma_max_msg` байт. Таким образом, настройка прямо влияет на
|
||
потребление памяти - один Vitastor-клиент с RDMA использует
|
||
`rdma_max_recv * rdma_max_msg * ЧИСЛО_OSD` байт памяти, по умолчанию -
|
||
примерно 2 МБ * число OSD.
|
||
|
||
## rdma_max_send
|
||
|
||
- Тип: целое число
|
||
- Значение по умолчанию: 8
|
||
|
||
Максимальное число RDMA-операций отправки, отправляемых в очередь одного
|
||
соединения. Желательно, чтобы оно было меньше `rdma_max_recv`, чтобы
|
||
у принимающей стороны в процессе работы не заканчивались буферы на приём.
|
||
Не влияет на потребление памяти - дополнительная память на операции отправки
|
||
не выделяется.
|
||
|
||
## peer_connect_interval
|
||
|
||
- Тип: секунды
|
||
- Значение по умолчанию: 5
|
||
- Минимальное значение: 1
|
||
- Можно менять на лету: да
|
||
|
||
Время ожидания перед повторной попыткой соединиться с недоступным OSD.
|
||
|
||
## peer_connect_timeout
|
||
|
||
- Тип: секунды
|
||
- Значение по умолчанию: 5
|
||
- Минимальное значение: 1
|
||
- Можно менять на лету: да
|
||
|
||
Максимальное время ожидания попытки соединения с OSD.
|
||
|
||
## osd_idle_timeout
|
||
|
||
- Тип: секунды
|
||
- Значение по умолчанию: 5
|
||
- Минимальное значение: 1
|
||
- Можно менять на лету: да
|
||
|
||
Время неактивности соединения с OSD, после которого клиенты или другие OSD
|
||
посылают запрос проверки состояния соединения.
|
||
|
||
## osd_ping_timeout
|
||
|
||
- Тип: секунды
|
||
- Значение по умолчанию: 5
|
||
- Минимальное значение: 1
|
||
- Можно менять на лету: да
|
||
|
||
Максимальное время ожидания ответа на запрос проверки состояния соединения.
|
||
Если OSD не отвечает за это время, соединение отключается и производится
|
||
повторная попытка соединения.
|
||
|
||
## max_etcd_attempts
|
||
|
||
- Тип: целое число
|
||
- Значение по умолчанию: 5
|
||
- Можно менять на лету: да
|
||
|
||
Максимальное число попыток выполнения запросов к etcd для тех запросов,
|
||
которые нельзя повторять бесконечно.
|
||
|
||
## etcd_quick_timeout
|
||
|
||
- Тип: миллисекунды
|
||
- Значение по умолчанию: 1000
|
||
- Можно менять на лету: да
|
||
|
||
Максимальное время выполнения запросов к etcd, которые должны завершаться
|
||
быстро, таких, как обновление резервации (lease).
|
||
|
||
## etcd_slow_timeout
|
||
|
||
- Тип: миллисекунды
|
||
- Значение по умолчанию: 5000
|
||
- Можно менять на лету: да
|
||
|
||
Максимальное время выполнения запросов к etcd, для которых не обязательно
|
||
гарантировать быстрое выполнение.
|
||
|
||
## etcd_keepalive_timeout
|
||
|
||
- Тип: секунды
|
||
- Значение по умолчанию: max(30, etcd_report_interval*2)
|
||
- Можно менять на лету: да
|
||
|
||
Таймаут для HTTP Keep-Alive в соединениях к etcd. Должен быть больше, чем
|
||
etcd_report_interval, чтобы keepalive гарантированно работал.
|
||
|
||
## etcd_ws_keepalive_interval
|
||
|
||
- Тип: секунды
|
||
- Значение по умолчанию: 5
|
||
- Можно менять на лету: да
|
||
|
||
Интервал проверки живости вебсокет-подключений к etcd.
|
||
|
||
## etcd_min_reload_interval
|
||
|
||
- Тип: миллисекунды
|
||
- Значение по умолчанию: 1000
|
||
- Можно менять на лету: да
|
||
|
||
Минимальный интервал полной перезагрузки состояния из etcd. Добавлено для
|
||
предотвращения избыточной нагрузки на etcd во время отказов, когда etcd не
|
||
успевает рассылать потоки событий и отменяет их.
|
||
|
||
## tcp_header_buffer_size
|
||
|
||
- Тип: целое число
|
||
- Значение по умолчанию: 65536
|
||
|
||
Размер буфера для чтения данных с дополнительным копированием. Пакеты
|
||
Vitastor содержат 128-байтные заголовки, за которыми следуют данные размером
|
||
от 4 КБ и для мелких операций ввода-вывода обычно выгодно за 1 вызов читать
|
||
сразу несколько пакетов, даже не смотря на то, что это требует лишний раз
|
||
скопировать данные. Часть каждого пакета за пределами значения данного
|
||
параметра читается без дополнительного копирования. Вы можете попробовать
|
||
поменять этот параметр и посмотреть, как он влияет на производительность
|
||
случайного и линейного доступа.
|
||
|
||
## min_zerocopy_send_size
|
||
|
||
- Тип: целое число
|
||
- Значение по умолчанию: 32768
|
||
|
||
OSD и клиенты будут пробовать использовать TCP-отправку без копирования (zero-copy) на
|
||
основе io_uring для буферов, больших, чем это число байт. Отправка без копирования
|
||
поддерживается в io_uring, начиная с версии ядра Linux 6.1. Наличие поддержки
|
||
проверяется автоматически и zero-copy отключается, когда поддержки нет. Также
|
||
её можно отключить явно, установив данный параметр в отрицательное значение.
|
||
|
||
⚠️ Внимание! Производительность данной функции может сильно отличаться на разных
|
||
процессорах и на разных версиях ядра Linux. В целом, zero-copy обычно быстрее с
|
||
большими сообщениями, а с мелкими (например, 4 КБ) zero-copy может быть даже
|
||
медленнее. 32 КБ достаточно почти для всех процессоров, но для каких-то можно
|
||
использовать даже меньшие значения. Например, для EPYC Milan/Genoa подходит 4 КБ,
|
||
а для Xeon Ice Lake - 12 КБ (но, пожалуйста, перепроверьте это сами).
|
||
|
||
Инструкция по проверке:
|
||
1. Добавьте `iommu=pt` в командную строку загрузки вашего ядра Linux и перезагрузитесь.
|
||
2. Обновите ядро. Например, для AMD EPYC очень важно использовать версию 6.11+.
|
||
3. Позапускайте тесты с помощью [send-zerocopy из примеров liburing](https://github.com/axboe/liburing/blob/master/examples/send-zerocopy.c),
|
||
чтобы найти минимальный размер сообщения, для которого zero-copy отправка оптимальна.
|
||
Запускайте `./send-zerocopy tcp -4 -R` на стороне сервера и
|
||
`time ./send-zerocopy tcp -4 -b 0 -s РАЗМЕР_БУФЕРА -D АДРЕС_СЕРВЕРА` на стороне клиента
|
||
с опцией `-z 0` (обычная отправка) и `-z 1` (отправка без копирования), и сравнивайте
|
||
скорость в МБ/с и занятое процессорное время (user+system).
|
||
|
||
## use_sync_send_recv
|
||
|
||
- Тип: булево (да/нет)
|
||
- Значение по умолчанию: false
|
||
|
||
Если установлено в истину, то вместо io_uring для передачи данных по сети
|
||
будут использоваться обычные синхронные системные вызовы send/recv. Для OSD
|
||
это бессмысленно, так как OSD в любом случае нуждается в io_uring, но, в
|
||
принципе, это может применяться для клиентов со старыми версиями ядра.
|