АйТи Фреш
Главная / Статьи / Серверы и инфраструктура
Серверы и инфраструктура

Канал свободен, а синхронизация PBS между площадками ползёт: как работает worker-threads в Proxmox Backup Server 4.2

Автор: Семёнов Евгений Сергеевич, директор ООО «АйТи-Фреш» · · ~18 мин чтения
Параллельная синхронизация Proxmox Backup Server между площадками: worker-threads вместо одного потока
Канал не виноват: один поток просто не умеет его заполнить на большой задержке.

Sync job в Proxmox Backup Server до 4.2 обрабатывал группы бэкапов по одной, и на канале с задержкой 30 мс один поток не заполняет полосу. Параметр worker-threads в 4.2 синхронизирует группы параллельно. Ниже — как доказать, что проблема именно в этом, как подобрать число потоков, чем оно ограничено и как не задушить офисный канал.

Почему sync PBS между площадками медленный, хотя канал свободен

Типичная жалоба: «Поставили второй PBS на удалённой площадке, настроили синхронизацию, ночью она не успевает». Дальше по классике: админ проверяет канал через iperf3, получает честную полосу, идёт крутить MTU, включает BBR, меняет шифр в IPsec, переносит туннель на WireGuard. Скорость sync при этом не меняется. Я видел это не раз, и чаще всего проблема была не в транспорте, а в том, как устроено само резервное копирование на удалённую площадку.

Sync job в PBS — это не rsync и не scp. Это клиент, который ходит к удалённому датастору по HTTP/2 поверх TLS: запрашивает список групп, снимки в группе, индексные файлы и по ним вытягивает недостающие chunks. До версии 4.2 группы обрабатывались строго по очереди. Официальная документация прямо называет узкое место: на соединениях с высокой задержкой одно HTTP/2-соединение к источнику упирается в head-of-line blocking, а параллельная обработка групп может заметно поднять пропускную способность.

Интуиция тут простая. Чем больше RTT, тем больше данных должно одновременно находиться «в полёте», чтобы заполнить канал, и тем сильнее один логический поток страдает от каждой паузы на запрос индекса или ожидание ответа. На локалке с RTT меньше миллисекунды вы этого не увидите — один поток спокойно выбирает гигабит. А через VPN между городами с RTT 30–40 мс потолок одного потока оказывается в разы ниже потолка канала.

Среднюю скорость sync я беру не «на глаз» из графика интерфейса, а из журнала задачи: в конце лога PBS пишет, сколько данных передано и за какое время. Делю одно на другое и перевожу в мегабиты — это число и сравниваю с iperf3. Для первого замера достаточно открыть последнюю успешную задачу во вкладке Tasks или вызвать proxmox-backup-manager task log <upid>. Если задач несколько, берите ночь с типичной дельтой, а не первый полный перенос — первичная заливка ведёт себя иначе.

Отсюда практический вывод одной фразой: если sync идёт между двумя зданиями по своей оптике, тюнить нечего. Если между городами или через VPN с RTT больше 10–15 мс — читайте дальше.

Прежде чем крутить сеть, замерьте `iperf3 -P 1` и `iperf3 -P 8`. Если однопоточный результат совпал со скоростью sync, сеть трогать не нужно — проблема в параллелизме приложения.

Что именно распараллеливает worker-threads в PBS 4.2

В Proxmox Backup Server 4.2 (релиз 29 апреля 2026) у задачи синхронизации появился параметр worker-threads. По документации: значения от 1 до 32, по умолчанию 1, значение больше единицы синхронизирует несколько backup groups параллельно. Ключевое слово — groups. Параллелизм идёт по группам резервных копий, то есть по сущностям вида vm/101, ct/204, host/buh-pc05.

Из этого следует несколько вещей, которые доходят не сразу. Первое: внутри одной группы ничего не ускоряется. Снимки в группе идут по очереди, chunks внутри снимка — тоже. Если на площадке одна-единственная большая виртуальная машина, worker-threads не даст ничего. Я однажды поставил восемь потоков для площадки, где почти весь объём давал один файловый сервер, ждал чуда и получил ноль. Пришлось разбирать сам бэкап: выносить данные на отдельные диски и в отдельные группы.

Второе: потолок ускорения — число групп, которые реально изменились за интервал. В датасторе может быть 60 групп, но если за сутки поменялись пять, работать будут максимум пять потоков. Третье: одна большая группа среди мелких превращается в хвост — все потоки отработали, а один продолжает тянуть. Общее время задачи не может быть меньше времени самой тяжёлой группы. Бороться с этим надо не потоками, а разбиением бэкапа.

Опция работает в обе стороны: и для pull (направление по умолчанию), и для push. В 4.2 push к тому же научился шифровать нешифрованные снимки активным ключом при отправке на менее доверенный удалённый PBS. Ограничители трафика различаются: rate-in для pull и rate-out для push.

Если весь ваш offsite — две-три группы бэкапов, выигрыша не будет физически. Смысл появляется от десятка меняющихся групп.
Канал свободен, а синхронизация PBS между площадками ползёт: как работает worker-threads в Proxmox Backup Server 4.2 — схема
Схема к статье. Открыть схему в полном размере
Схема worker-threads в PBS 4.2: параллельная синхронизация backup groups между источником и приёмником
Потоки распределяются по группам бэкапов — одну большую группу они не ускорят.

Как включить worker-threads: CLI, sync.cfg, веб-интерфейс

Быстрее и надёжнее всего — через proxmox-backup-manager на том сервере, где живёт задача (для pull это приёмник, для push — источник). Создание и правка выглядят так:

# создать задачу pull-синхронизации
proxmox-backup-manager sync-job create pbs2-local \
  --remote pbs2 --remote-store local --store local \
  --schedule 'Wed 02:30'

# включить параллельную обработку групп
proxmox-backup-manager sync-job update pbs2-local --worker-threads 4

# проверить и прогнать вручную
proxmox-backup-manager sync-job list
proxmox-backup-manager sync-job run pbs2-local

Настройки задач лежат в /etc/proxmox-backup/sync.cfg — текстовом файле в формате секций. Я смотрю его напрямую, когда надо быстро понять, что наворотил предыдущий админ, и держу копию в git вместе с datastore.cfg и remote.cfg. Секция выглядит примерно так (сверяйте с proxmox-backup-manager sync-job show <id> в своей версии):

sync: pbs2-local
	store local
	remote pbs2
	remote-store local
	schedule Wed 02:30
	worker-threads 4
	rate-in 20MiB
	comment offsite

В веб-интерфейсе параметр в настройках задачи синхронизации датастора, но я предпочитаю CLI: воспроизводимо и сразу видно все параметры. Права для pull по документации: Remote.Read на /remote/{remote}/{remote-store} и Datastore.Backup на локальный датастор (плюс Datastore.Prune, если включён remove-vanished). Для push — Remote.Audit и Remote.DatastoreBackup на удалённой стороне. Если приёмник не видит датастор источника, вероятно, дело в правах самого пользователя, а не токена, — эту ловушку я разбирал в статье про API-токен PBS с правами на datastore.

Полезный приём для площадок с неоднородными группами — разнести синхронизацию на две задачи через --group-filter. Например, одна задача берёт только виртуальные машины (--group-filter type:vm), другая — только бэкапы рабочих станций (--group-filter type:host). Тогда тяжёлые группы серверов не блокируют мелкие группы компьютеров, и вы можете задать им разное расписание и разный лимит. Главное — не забыть, что потоки двух одновременно работающих задач складываются.

И сразу совет: не меняйте worker-threads вместе с чем-то ещё. Один прогон — одно изменение. Иначе вы не поймёте, что дало прирост: потоки, новый лимит скорости или то, что заодно передвинули verify.

Перед первым экспериментом зафиксируйте базовую точку: время выполнения и объём из лога последней успешной задачи. Без этого числа тюнинг превращается в гадание.
Порядок действий: Как включить worker-threads: CLI, sync.cfg, веб-интерфейс — схема
Порядок действий: Как включить worker-threads: CLI, sync.cfg, веб-интерфейс. Открыть схему в полном размере

Разбор из практики: «Дебет-Кредит», 19 рабочих мест и offsite за 30 мс

Бухгалтерская консультация «Дебет-Кредит», 19 рабочих мест. В офисе — один хост Proxmox VE с шестью виртуальными машинами (контроллер домена, сервер 1С с PostgreSQL, терминальный сервер, файловый сервер, пара служебных) и локальный PBS 4.2 на отдельном сервере. Кроме виртуальных машин, через proxmox-backup-client бэкапятся профили и рабочие папки 19 компьютеров сотрудников — каждый своей группой host/. Итого в датасторе 27 групп. Вторая копия — PBS 4.2 на удалённой площадке, pull через IPsec, офисный канал 200 Мбит/с на отдачу, RTT 30–33 мс. Окно для синхронизации — с 22:00 до 07:00.

Пришли ко мне в конце квартала: «синхронизация не успевает, утром тормозит интернет в офисе». Замерили: суточная дельта в отчётный период выросла до 110 ГБ, задача шла 5 часов 25 минут при нормальных днях, а в пиковые ночи — дольше девяти и вылезала в рабочее время. Средняя скорость по логу — около 45 Мбит/с. iperf3 в один поток давал 48 Мбит/с, в восемь — 190. Диагноз поставили этими двумя цифрами за десять минут: приложение упирается в один поток, а не в канал.

Дальше перебор с шагом, каждое значение — отдельная ночь с сопоставимой дельтой. Снимал время выполнения, среднюю скорость из лога, пик RSS процесса proxmox-backup-proxy на приёмнике и await дисков. Результаты — в списке ниже. Остановились на шести потоках: 5 часов 25 минут превратились примерно в полтора часа. Восемь потоков дали плюс 4 % к шести при заметном росте await — в пределах шума, не стоит того. Меняющихся групп в обычную ночь около двадцати, так что запас по параллелизму был.

Отдельно пришлось разобраться с первичной заливкой на новый приёмник, которую делали за месяц до меня: она шла почти четверо суток, и её тоже списали на канал. Для первичного переноса большого объёма я сейчас предпочитаю один раз привезти данные физически или ограничить перенос последними снимками через --transfer-last, а историю догонять постепенно. После тюнинга в «Дебет-Кредите» повторную заливку делать не пришлось, но для следующего приёмника в регламенте теперь этот пункт есть.

Хвост тоже проявился честно: последние 50 минут любой задачи тянулась одна группа — сервер 1С с ежедневной дельтой около 18 ГБ. Быстрее этого времени задача не станет при любом числе потоков. Но главный выигрыш даже не в скорости: синхронизацию перевели с ночного расписания на запуск каждые четыре часа, и RPO по offsite-копии сократился с суток до четырёх часов. Ради этого всё и затевалось. Чтобы днём sync не мешал людям, задали rate-in 20MiB — около 168 Мбит/с, оставив офису запас канала.

Главный результат — не «стало быстрее», а «стало можно синхронизировать чаще». Пересчитайте RPO после тюнинга и покажите цифру руководству: это единственный аргумент, который здесь работает.
Результаты подбора worker-threads в PBS: время синхронизации от 5 ч 25 мин до 1 ч 29 мин, RPO с суток до 4 часов
После шести потоков прирост почти исчез — дальше вы платите памятью и дисками за проценты.

Сколько потоков ставить и чем ограничен их рост

Документация предупреждает прямо: память и число соединений на обоих концах растут примерно линейно с числом воркеров, поэтому большие значения не всегда лучше. На стенде это подтверждается почти буквально: каждый воркер держит своё соединение к удалённому серверу, свои буферы и свою TLS-обвязку. Сколько памяти уходит на воркер в вашей связке, проще всего измерить: RSS proxmox-backup-proxy до и во время задачи.

Второе ограничение — диск приёмника. Sync пишет chunks в .chunks, а это случайная запись по 65 536 подкаталогам. На NVMe вы этого не заметите, на RAIDZ2 из SATA-дисков заметите очень хорошо, особенно если параллельно идёт verify или GC. Проверьте tuning датастора: при sync-level=file fsync вызывается на каждую вставку chunk, и параллельные потоки упрутся в диск. Значение по умолчанию — filesystem, оно делает syncfs после завершения задачи и является разумным компромиссом.

# текущие tuning-опции датастора
proxmox-backup-manager datastore show local

# вернуть умолчание, если кто-то поставил sync-level=file
# (--tuning перезаписывает строку целиком — перечислите и остальные ваши опции)
proxmox-backup-manager datastore update local --tuning 'sync-level=filesystem'

Третье — процессор: TLS, распаковка, проверка контрольных сумм chunks. На приёмнике с двумя vCPU ставить 16 потоков бессмысленно — получите очередь на планировщике. Четвёртое, самое приятное ограничение — канал: когда суммарная скорость потоков упёрлась в линию, дальнейшее увеличение только расходует память и IOPS. Именно это произошло в «Дебет-Кредите» между шестью и восемью потоками.

Про сеть между площадками одно уточнение, которое регулярно всплывает. Если туннель идёт через NAT на офисном маршрутизаторе, проверьте лимиты таблицы соединений и тайм-ауты для долгих TCP-сессий. Шесть-восемь долгих TLS-соединений сами по себе ничтожная нагрузка, но на бытовом роутере с агрессивным тайм-аутом простаивающая сессия может обрываться посреди ожидания индекса, и в журнале задачи вы увидите ошибки соединения, которые легко принять за проблему PBS.

Мой рабочий подход к стартовому значению: 4 потока для каналов до 200 Мбит/с, 8 — для гигабитных линков с RTT 20–50 мс, больше — только если приёмник на NVMe, памяти с запасом и вы реально видите незанятый канал. Значения ближе к 32 я на практике не применял и сценария, где они оправданы, не встречал.

Увеличивайте потоки шагами 1 → 4 → 8 и останавливайтесь, когда прирост скорости стал меньше 10–15 %. Дальше вы платите памятью и дисковой задержкой за проценты.
Цифры и версии: Сколько потоков ставить и чем ограничен их рост — схема
Цифры и версии: Сколько потоков ставить и чем ограничен их рост. Открыть схему в полном размере

Как ограничить скорость sync и не задушить рабочий трафик

Как только sync начинает выбирать канал целиком, появляется вторая проблема: если задача выехала за ночное окно или вы перевели её на дневной запуск, она конкурирует с рабочим трафиком. Подвох, на котором спотыкаются почти все: в PBS есть глобальный traffic control — правила с сетями, лимитами и таймфреймами. Но документация прямо предупреждает: sync job на сервере этими правилами не ограничиваются. Для них нужен собственный лимит задачи.

Ограничивать sync нужно параметрами самой задачи: rate-in для pull и rate-out для push, плюс burst-in / burst-out — размер корзины токенов для коротких всплесков. Единицы можно задавать в десятичных (MB, GB) или двоичных (MiB, GiB) — разница почти 5 %, не перепутайте. И помните, что это байты в секунду, а не биты.

# pull: ограничить входящий трафик ~168 Мбит/с с корзиной на всплески
proxmox-backup-manager sync-job update pbs2-local --rate-in 20MiB --burst-in 40MiB

# push: ограничивается исходящий
proxmox-backup-manager sync-job update pbs2-push --rate-out 20MiB --burst-out 40MiB

Второй источник конкуренции — соседние задачи самого PBS. GC и verify на приёмнике бьются с sync за одни и те же диски. Я развожу так: sync — раз в 4–6 часов, verify — раз в неделю ночью, GC — раз в неделю в другой день. Если verify на приёмнике находит повреждённые снимки, обычный sync их не перекачает — для этого есть отдельный режим, про resync-corrupt в PBS я писал подробно.

Третье: если у вас две задачи синхронизации в одну сторону и обе с восемью потоками, суммарно это шестнадцать. Считайте бюджет по всем одновременно работающим задачам, а не по каждой отдельно, либо разведите их по расписанию.

Не ставьте rate-in «на глазок в половину канала». Сначала посчитайте, какая скорость нужна: дельта в гигабайтах, делённая на длину окна в секундах, плюс 30 % запаса.

Порядок действий: что делать в первую очередь, а на что не тратить время

Сначала — доказать, что проблема в параллелизме: iperf3 в один поток и в восемь, сравнить однопоточный результат со средней скоростью sync из лога. Совпали — диагноз подтверждён. Если однопоточный iperf3 сильно выше скорости sync, дело не в head-of-line: смотрите диски приёмника, параллельный verify, память. Потом посчитать группы, которые реально меняются между запусками: это ваш потолок параллелизма. Затем три прогона — базовый, 4 и 8 потоков, каждый отдельной ночью с фиксацией времени, скорости, RSS и await. И только после этого — пересчитать расписание под новый RPO.

На что можно не тратить время. Тюнинг сети: MTU, congestion control, смена шифра IPsec при этой проблеме дают единицы процентов и стоят часов работы. Погоня за максимальным worker-threads: разница между 8 и 16 — проценты, а память отличается вдвое. Переход с pull на push ради скорости: push решает другую задачу — когда приёмник не должен иметь доступа к источнику, — а worker-threads работает одинаково в обе стороны. Отдельно про поведение приёмника при удалении снимков на источнике: без remove-vanished история на приёмнике копится, с ним — зеркалится; почему синхронизация PBS — это зеркало, а не второй архив, стоит понять до того, как поднимать частоту sync.

Не забивать нельзя на мониторинг возраста последней успешной синхронизации. Заведите проверку «последняя успешная задача завершилась не позже N часов назад» и уведомление. Дельта растёт вместе с бизнесом, и настройка, которая сегодня укладывается в окно с запасом, через год начнёт в него упираться. Узнать об этом лучше из графика, а не в момент аварии, когда offsite отстал на трое суток.

И вопрос, по которому единого мнения нет: держать ли промежуточный локальный PBS или бэкапить сразу в удалённый. Я за схему «локальный PBS плюс sync на удалённую площадку»: восстановление с локального идёт по локальной сети, виртуальные машины не ждут сетевых задержек во время бэкапа, а канал грузится асинхронно и предсказуемо. У коллег с хорошей оптикой между площадками прямой бэкап в удалённый датастор тоже работает. Решает конкретика вашего канала.

Ускорение sync — не про красивые мегабиты в логе, а про то, на сколько часов назад откатится компания, если сегодня ночью сгорит серверная. Мерьте результат именно так.
Порядок действий: Порядок действий: что делать в первую очередь, а на что не тратить время — схема
Порядок действий: Порядок действий: что делать в первую очередь, а на что не тратить время. Открыть схему в полном размере
Чек-лист ускорения синхронизации Proxmox Backup Server: диагностика iperf3, worker-threads, rate-in, RPO
Сначала доказать, что дело в одном потоке, и только потом добавлять потоки.

Частые вопросы

С какой версии PBS появился worker-threads у sync job?

С Proxmox Backup Server 4.2 (апрель 2026). Значения от 1 до 32, по умолчанию 1. Параметр задаётся в задаче синхронизации: `proxmox-backup-manager sync-job update <id> --worker-threads 4`.

Ускорит ли worker-threads синхронизацию одной большой виртуальной машины?

Нет. Параллелизм идёт по backup groups, а снимки и chunks внутри одной группы обрабатываются последовательно. Одна большая ВМ — одна группа и один поток.

Почему глобальный traffic control не ограничивает sync?

Так задумано: по документации sync job не подчиняются глобальным правилам. Для pull задайте rate-in у задачи, для push — rate-out, при необходимости с burst-in / burst-out.

Сколько потоков ставить?

Начните с 4, затем попробуйте 8, каждый раз отдельным прогоном с замером времени, памяти и задержки дисков. Остановитесь, когда прирост меньше 10–15 %. Больше числа меняющихся групп ставить бессмысленно.

Работает ли worker-threads для push-синхронизации?

Да, параметр одинаково работает для pull и push. Для push скорость ограничивается rate-out, а в 4.2 push умеет шифровать нешифрованные снимки активным ключом при отправке на менее доверенный сервер.

Столкнулись с похожей задачей? Обращайтесь — решим

Если у вас происходит что-то из описанного в этой статье — или любая другая проблема с ИТ-инфраструктурой, — обращайтесь в любое время. Мои специалисты и я лично разберём ситуацию, найдём настоящую причину и доведём до решения.

Возьмёмся и за разовую задачу, и за постоянное обслуживание. Первичная консультация — бесплатно и без обязательств.

📞 +7 903 729-62-41 💬 MAX: +7 903 729-62-41 ✈ Telegram @ITfresh_Boss

С уважением, Семёнов Евгений Сергеевич, директор «АйТи Фреш» — IT-аутсорсинг для компаний до 50 рабочих мест, 15+ лет практики

Источники

© ООО «АйТи-Фреш» · Москва · Все статьи