Поступові оновлення
Виконуйте поступове оновлення для заміни вузлів API, worker чи scheduler без вимкнення розгортання. Контракт охоплює невелику кластерну форму з посібника самостійного розгортання: два чи три вузли API за балансувальником, спільні зовнішні MySQL або PostgreSQL, спільний Redis, незалежно масштабовані worker та рівно один scheduler або runner обслуговування.
Поступове оновлення підтримується за виконання всіх гарантій цієї сторінки. Поза цими межами використовуйте задокументований процес оновлення із зупинкою всього розгортання.
Терміни ролей і маніфест форм цього контракту наведені в
топології ролей Server. Цей посібник
описує поступове оновлення поточних класів процесів standalone_server.
Що означає поступове оновлення
Поступове оновлення замінює процеси по одному, завершуючи роботу кожного перед зупинкою, поки решта набору обслуговує трафік. Результат — відсутність простою розгортання загалом і обмежене вікно співіснування старих і нових процесів.
Контракт розрізняє чотири класи процесів поточної форми
standalone_server, кожен із власним підходом до оновлення:
- Вузли HTTP/API: процеси Server без стану, що обслуговують HTTP
і зараз містять ролі
api_ingress,control_plane,matchingіhistory_projection. - Worker: процеси SDK, що опитують площину worker та виконують
завдання activity й workflow як
execution_plane. - Scheduler / runner обслуговування: єдиний процес, що запускає
розклади та забезпечує тайм-аути activity й зберігання історії як
роль
scheduler. - Bootstrap: одноразовий процес міграцій бази даних і створення типового простору імен.
Вузли API та worker оновлюються незалежно. Scheduler має один екземпляр: зупиніть старий перед запуском нового. Решта розгортання обслуговує трафік протягом цього проміжку.
Правила сумісного змішування версій
Вікно співіснування — час, коли одночасно працюють кілька образів Server, версій пакета Workflow або версій SDK worker. У ньому мають виконуватися всі правила цього розділу.
Образ Server і пакет Workflow
- Лише сусідні версії. Під час поступового оновлення кожен вузол API та інший процес Server має використовувати образ Server, версія пакета Workflow якого має ту саму мажорну версію, що й попередній пакет кластера, і відрізняється від кожного іншого живого процесу щонайбільше на одну мінорну версію. Перехід через мажорну версію потребує оновлення із загальною зупинкою.
- Міграції лише з додаванням. Кожна зміна схеми Durable Workflow v2 є додатковою в межах мажорної версії. Нові вузли не повинні потребувати стовпця чи таблиці, яких ще немає після міграцій. Старі вузли мають працювати з новим стовпцем, якого не читають. Це забезпечують правила порядку міграцій.
- Сусідні версії площини керування й протоколу worker. Кожен
вузол публікує підтримувані діапазони
control_plane.versionіworker_protocol.versionчерезGET /api/cluster/info. Під час оновлення підтримуваний діапазон нового образу має перетинатися з діапазоном кожного живого старого вузла. Виявіть діапазон перед оновленням і припиніть його за відсутності перетину.
SDK worker та ідентичність збірки
- Worker позначають кожну збірку. Кожен worker поступового
оновлення має реєструватися через
POST /api/worker/registerзі стабільнимbuild_id. Група без версії (build_id: null) є типовою до оновлення. Посібник оновлення build ID worker пояснює перший перехід. - Fingerprint визначення workflow залишаються закріпленими.
Образи Server із
DW_V2_PIN_TO_RECORDED_FINGERPRINT=true, типовим значенням, закріплюють незавершені run за fingerprint визначення workflow, записаним уWorkflowStarted. Новий worker з іншим fingerprint того самого workflow відмовляється забирати ці run до їх завершення. - Підхід до допуску збірок, що співіснують. Оберіть
DW_V2_FLEET_VALIDATION_MODEперед початком.warnдозволяє оновлення навіть без живого worker потрібного маркера сумісності.failблокує диспетчеризацію та закриває допуск контракту готовності в цьому вікні. Виробничі оновлення, що потребують чистого переходу, мають використовуватиfail.
Порядок схеми й bootstrap
Зміни схеми виконуються одним проходом bootstrap. Порядок важливий.
- Спочатку виконайте bootstrap рівно один раз. Виконайте
php artisan server:bootstrap --forceабо еквівалент опублікованого образу з одного контейнера перед запуском будь-якого нового вузла API, worker чи scheduler. Bootstrap виконуєmigrateі створення типового простору імен. Він приймає міграції пакета Workflow, таблиці яких уже існують на підключенні. - Нова схема має бути сумісною зі старим кодом. Кожна міграція v2 цього шляху лише додає таблиці, стовпці чи індекси. Старі вузли API й worker продовжують працювати з новою схемою.
- Не запускайте новий код до завершення bootstrap. Оновлюйте образ Server лише після успішного завершення bootstrap. Нові вузли API й worker можуть залежати від щойно створених таблиць. Запуск до завершення bootstrap є найпоширенішою причиною сплеску 5xx під час переходу.
- Bootstrap ідемпотентний. Його безпечно повторювати. Якщо він частково завершився помилкою, виправте причину й повторіть. Журнал міграцій продовжує з місця зупинки, а створення простору імен нічого не змінює за наявності рядка.
Міграція, що з’явилася на одному сервері раніше за інший, НЕ ПОВИННА порушувати інтерфейс готовності. Якщо під час планування знайдено зміну, яка не є додатковою, використовуйте вікно загальної зупинки для цього випуску й поверніться до поступових оновлень у наступному.
Drain і допуск у вікні співіснування
Три інтерфейси допуску автоматично забезпечують безпеку співіснування:
- Допуск запуску. Кожен процес Server завантажує
BackendCapabilities,LongPollCacheValidator,WorkflowModeGuardі контракт готовності під час запуску. Процес із backend чи кешем, що не відповідає контракту v2, відмовляється позначати себе готовим. - Сумісність worker. За
DW_V2_FLEET_VALIDATION_MODE=failі відсутності живого worker потрібного маркера сумісності в області підключення та черги завдання роль matching блокує диспетчеризацію, а перевірка здоров’яworker_compatibilityпереходить ізwarningдоerror. Завдання залишаються готовими й видимими та не втрачаються. Контракт готовності повертає 503 на цьому вузлі, щоб балансувальник виключив його з обслуговування. - Безпека маршрутизації. Готове завдання без живого worker потрібної
сумісності зберігається й рахується в метриці backlog
compatibility_blocked_runs. Drain маршрутизації не призводить до прихованої втрати завдань. Гарантія виконання щонайменше один раз залишається чинною.
Щоб скоротити вікно співіснування worker, переведіть старі групи в drain після появи нових. Використовуйте процес оновлення build ID worker:
dw task-queue:drain orders-critical --build-id orders-worker-2026-04-21-z9
drain_intent групи стає draining. Worker цієї збірки завершують
поточну роботу, але припиняють забирати нові завдання. Дочекайтеся нуля
active_worker_count і draining_worker_count перед зупинкою старих
процесів worker.
Scheduler не має довготривалої черги завдань і не потребує drain worker. Зупиніть старий контейнер scheduler, виконайте bootstrap, якщо його ще не виконано, і запустіть новий. Вікно між ними обмежене часом запуску нового контейнера. Розклади відновлюються зі збереженого стану на наступному tick.
Якщо оновлення також вводить окреме розгортання ролі matching, явно
задайте зміну топології. Не припускайте, що кожен вузол виконання
продовжить загальний пошук готових завдань. У
зіставленні й диспетчеризації завдань
наведена форма workflow:v2:repair-pass --loop разом із
DW_V2_MATCHING_ROLE_QUEUE_WAKE=0. Перевірте живий контракт вузла
через GET /api/cluster/info: topology.current_shape має відповідати
розгортанню переходу, topology.current_roles — задокументованому набору
ролей вузла, а topology.matching_role.queue_wake_enabled,
topology.matching_role.shape і topology.matching_role.wake_owner
мають показувати очікуваного власника загального пошуку готових завдань.
Типова форма повідомляє queue_wake_enabled: true, shape: "in_worker"
і wake_owner: "worker_loop". Окремі розгортання matching змінюють
вузли виконання на queue_wake_enabled: false, shape: "dedicated"
і wake_owner: "dedicated_repair_pass".
Готовність і перемикання
Визначайте допуск трафіку на вузол за контрактом готовності:
GET /api/healthдоводить обслуговування HTTP процесом.GET /api/readyдоводить доступ до налаштованих залежностей runtime, включно з міграціями, типовим простором імен та перевіркою допуску сумісності worker заDW_V2_FLEET_VALIDATION_MODE=fail.GET /api/cluster/infoдоводить можливість автентифікованого клієнта виявити ідентичність збірки, протоколи площини керування й worker, кодеки payload та можливості Server.POST /api/worker/registerдоводить можливість автентифікації worker в очікуваному просторі імен і черзі завдань.
Послідовність перемикання одного вузла API:
- Виключіть вузол із ротації балансувальника. Найпростіший шлях — спричинити невдачу перевірки готовності балансувальника, зупинивши pre-start hook нового образу перед запуском нового контейнера.
- Дочекайтеся завершення поточних запитів HTTP. Більшість клієнтів повторює запит після скидання підключення. Довгі підключення, як long-poll worker, підключаються до решти набору вузлів.
- Зупиніть старий контейнер і запустіть новий.
- Дочекайтеся 200 від
GET /api/readyта нової ідентичності збірки вGET /api/cluster/info. За зміни топології matching також підтвердьте відповідністьtopology.matching_role.task_dispatch_mode,topology.matching_role.queue_wake_enabled,topology.matching_role.shape,topology.matching_role.wake_owner,topology.matching_role.partition_primitivesіtopology.matching_role.backpressure_modelпотрібному розгортанню перед поверненням трафіку. Використовуйте/api/system/operator-metricsдля того самого локального контракту ролі matching разом із живими лічильниками backlog, відновлення й worker процесу, що відповідає. - Поверніть вузол до ротації.
Повторюйте по одному вузлу. Не оновлюйте наступний, доки попередній не повернувся до ротації й не обслуговує трафік без помилок.
Worker перемикаються за групами:
- Запустіть нову групу worker із новим
build_id. - Підтвердьте
rollout_status: "active"і ненульовийactive_worker_countобох груп уdw task-queue:build-ids <queue> --json. - Переведіть стару групу в drain через
dw task-queue:drain. - Дочекайтеся нуля
active_worker_countіdraining_worker_countстарої групи. - Зупиніть старі процеси worker.
Відкат
Кожен крок оборотний. Сплануйте відкат перед початком.
-
Відкат bootstrap. Міграції v2 оборотні через стандартний шлях Laravel
down(). Відкат міграції, потрібної новому образу, вимагає спочатку зупинити всі нові вузли. Інакше новий код бачить відсутній стовпець, а контракт готовності повертає 503. Більшість відкатів не потребує скасування міграцій, оскільки зміни схеми додаткові. -
Відкат вузла API. Зупиніть новий контейнер і запустіть старий на тому самому вузлі. Виключіть вузол із ротації на час запуску та поверніть після успішного
GET /api/ready. Повторіть для інших оновлених вузлів API. Старий код читає нову схему, бо зміна додаткова. -
Відкат worker. Відновіть раніше спорожнену групу, переведіть невдалу групу в drain і знову масштабуйте відому робочу збірку:
dw task-queue:resume orders-critical --build-id orders-worker-2026-04-21-z9dw task-queue:drain orders-critical --build-id orders-worker-2026-04-22Resume очищає
drain_intentіdrained_at. Worker, що надсилає heartbeat із відновленимbuild_id, повертається доactiveна наступному опитуванні. Обидва виклики ідемпотентні.
Якщо оновлення виявило недодаткову проблему схеми, використовуйте вікно загальної зупинки для відкату, виконайте коригувальні міграції та сплануйте перехід заново.
Перевірка оператором
Перевіряйте кожен етап оновлення за інтерфейсами оператора.
| Питання | Інтерфейс |
|---|---|
| Чи bootstrap завершений? | Код завершення 0 php artisan server:bootstrap --force. migrate:status показує виконання всіх міграцій. |
| Чи новий вузол готовий? | GET /api/ready повертає 200, GET /api/cluster/info повідомляє нову збірку. |
| Чи здоровий допуск сумісності? | workers.fleet, workers.active_workers і workers.active_workers_supporting_required у GET /api/system/operator-metrics погоджені щодо ненульової кількості worker кожного потрібного маркера сумісності. |
| Чи просувається drain worker? | dw task-queue:build-ids <queue> --json показує зменшення active_worker_count і draining_worker_count групи drain. |
| Чи маршрутизація безпечна? | backlog.compatibility_blocked_runs і backlog.max_compatibility_blocked_age_ms у GET /api/system/operator-metrics близькі до нуля, перевірка worker_compatibility не має error. |
| Чи scheduler наздогнав розклад? | schedules.missed у GET /api/system/operator-metrics дорівнює нулю, schedules.oldest_overdue_at — null. |
| Чи накопичуються застряглі run? | runs.repair_needed і runs.max_repair_needed_age_ms у GET /api/system/operator-metrics залишаються близькими до базових значень перед оновленням. |
dw system:operator-metrics --json надає той самий знімок метрик
оператора в консолі набору окремого Server, тож оператори можуть
обрати зручний для свого процесу інтерфейс. Окрема служба Waterline
може читати той самий стан оновлення Server через PHP SDK у
/waterline/api/v2/health і /waterline/api/stats. Узгодьте її endpoint,
простір імен та токен Server з оновлюваним набором. Вбудовані
Laravel-розгортання надають ці маршрути Waterline зі свого пакета
в процесі. Server API та CLI залишаються доступними в обох випадках,
як описано в операційних межах оператора.
Сценарії помилок і дії
| Симптом | Імовірна причина | Дія |
|---|---|---|
Новий вузол API не проходить GET /api/ready після запуску | Bootstrap не завершений або задано DW_V2_FLEET_VALIDATION_MODE=fail без живого сумісного worker | Повторіть bootstrap. Запустіть сумісну групу worker перед поверненням вузла API до ротації. |
worker_compatibility переходить до error під час оновлення | Потрібний маркер сумісності не має живого worker із підтримкою | Запустіть більше worker підтримуваного build_id. Відновіть раніше спорожнену групу, якщо потрібен відкат. |
backlog.compatibility_blocked_runs і max_compatibility_blocked_age_ms зростають | Завдання очікують маркер, якого не підтримує живий worker | Та сама дія. Завдання зберігаються й автоматично надсилаються після heartbeat сумісного worker. |
dw task-queue:drain успішний, але worker продовжують забирати завдання | Процес worker не надсилав heartbeat після drain | Дочекайтеся одного циклу heartbeat. Якщо група залишається активною, перезапустіть процес worker, щоб отримати намір drain. |
| Запуски розкладів припинилися після перезапуску scheduler | Старий і новий scheduler зупинені | Запустіть новий контейнер scheduler. Перевірте повернення schedules.missed до нуля під час наступного зчитування метрик оператора. |
Якщо симптому немає в списку, вважайте оновлення невдалим: припиніть додавати нові процеси, переведіть запущені нові групи в drain та відновіть попередню збірку перед подальшою діагностикою.
Пов’язані довідники
- Самостійні розгортання для форм розгортання, які передбачає цей контракт.
- Оновлення build ID worker для викликів drain і resume груп.
- Операційні межі оператора для контракту діагностики, черг і відновлення проєкцій, який оператори читають разом із сигналами оновлення.
- Довідник конфігурації Server
для змінних середовища безпеки оновлення (
DW_V2_FLEET_VALIDATION_MODE,DW_V2_PIN_TO_RECORDED_FINGERPRINT,DW_V2_GUARDRAILS_BOOT,DW_V2_CACHE_VALIDATION_MODE,DW_V2_MULTI_NODE,DW_V2_VALIDATE_CACHE_BACKEND,DW_V2_TASK_REPAIR_*). - Довідник Server API для endpoint готовності, cluster info й метрик оператора, що перевіряють кожен етап оновлення.