Петли обратной связи: усиливающие и уравновешивающие
В прошлой главе мы разбирали, как выбор границы меняет вывод: одна и та же авария выглядит как «баг в сервисе» или как «сбой процесса дежурства» в зависимости от того, где провести линию. Теперь возьмём то, что оказалось внутри границы, и зададим следующий вопрос: как это ведёт себя во времени?
Ответ почти всегда сводится к петлям. Если следствие возвращается к причине — цепочка замыкается, и система перестаёт вести себя как машина «вход → выход». Она начинает разгоняться сама, сопротивляться вмешательству или колебаться без внешнего толчка. Три поведения, которые интуиция инженера объясняет неправильно чаще всего:
- сервис держал нагрузку годами, а потом за 40 секунд ушёл в отказ и не вернулся даже после того, как трафик упал;
- команду увеличили вдвое, а скорость выпуска фич не выросла и через полгода;
- багу починили симптом, и через квартал вокруг заплатки вырос процесс, который теперь нельзя убрать.
Это не три разные загадки. Это три петли обратной связи, и у каждой есть структура, которую можно нарисовать, посчитать и проверить.
Сразу оговорка о жанре. Петли — инструмент, а не мировоззрение. Схема с кружочками и стрелками сама по себе ничего не предсказывает: она фиксирует гипотезу о структуре. Гипотеза становится знанием, только когда каждая стрелка привязана к метрике, а модель делает предсказание, которое можно было бы опровергнуть. Раздел «Пределы метода» ниже — не ритуальная скромность, а половина главы.
Минимальное определение
Петля обратной связи — замкнутая цепочка причинных связей, в которой изменение величины через несколько шагов возвращается к ней самой.
Три требования, без которых слово «петля» использовать нельзя:
- Замкнутость. Цепочка
A → B → C— это не петля, а причинная цепь. Петля —A → B → C → A. - Причинность, а не корреляция. Стрелка означает «изменение A меняет B при прочих равных». Совместная динамика двух метрик, вызванная общей третьей причиной, — не связь; подробный разбор этой ошибки есть в главе о причинных и статистических ошибках.
- Время. Обход петли занимает ненулевое время. Именно поэтому петли порождают динамику, а не мгновенное равновесие. Задержкам посвящена отдельная глава — «Задержки».
Петель ровно два типа. Усиливающая (reinforcing, R) — изменение возвращается с тем же знаком и добавляется к себе: рост порождает рост, падение порождает падение. Уравновешивающая (balancing, B) — изменение возвращается с обратным знаком и гасит само себя: система тянется к какому-то состоянию и сопротивляется отклонению.
Всё остальное — комбинации этих двух.
Знак связи и полярность петли
Чтобы определить тип петли, не нужна интуиция, нужен подсчёт.
Знак связи. Стрелка A → B помечается «+», если рост A увеличивает B (а падение A — уменьшает) при прочих равных; «−», если рост A уменьшает B. Формулировка «при прочих равных» существенна: знак — это частная производная, а не наблюдаемая корреляция.
Полярность петли = произведение знаков всех связей контура. Практически: посчитайте минусы. Чётное число (включая ноль) — усиливающая R. Нечётное — уравновешивающая B.
Две частые ошибки при расстановке знаков:
Знак — не оценка. «Число инцидентов растёт → доверие пользователей падает» — это связь со знаком «−», хотя оба конца звучат негативно. Знак описывает направление влияния, а не то, нравится ли вам результат. Смешивать оценку с направлением — самый быстрый способ получить схему, которая выглядит правдоподобно и врёт в полярности.
Двойное отрицание. «Меньше тестов → больше багов» и «Больше тестов → меньше багов» — одна и та же связь со знаком «−»; писать нужно один раз и от роста. Если вы формулируете половину стрелок «от уменьшения», то через три звена собьётесь в подсчёте минусов и получите R там, где B.
Проверка на здравый смысл: разомкните петлю мысленно и спросите «если я толкну эту величину вверх и подожду один оборот — она вернётся выше или ниже, чем была?». Выше — R. Ниже — B.
Уравновешивающая петля: цель, разрыв, действие
Уравновешивающая петля — это регулятор. У неё всегда есть три части, и полезно называть их явно:
- цель (goal) — значение, к которому система стремится: целевая утилизация 60%, длина очереди 0, error budget за месяц;
- разрыв (gap) — разница между целью и фактом;
- действие — то, что меняет факт пропорционально разрыву.
Каноническая форма в непрерывном времени:
$$\frac{dx}{dt} = k \cdot (G - x)$$
Решение — экспоненциальный подход к цели:
$$x(t) = G + (x_0 - G) \cdot e^{-kt}$$
Ключевая величина — постоянная времени $\tau = 1/k$: время, за которое разрыв сокращается примерно в 2.7 раза. За $3\tau$ разрыв закрывается на 95%. Это не абстракция: $\tau$ автоскейлера — это cooldown плюс время старта пода плюс окно усреднения метрики, и его можно измерить секундомером.
Уравновешивающие петли, которые есть в любой продакшн-системе:
| Петля | Цель | Разрыв измеряется как | Актуатор | Типичная τ |
|---|---|---|---|---|
| Горизонтальный автоскейлер | целевая утилизация CPU | факт − цель | число реплик | 1–5 мин |
| TCP congestion control | заполнить канал без потерь | сигнал потери/задержки | размер окна | 1 RTT |
| Rate limiter / token bucket | заданный RPS | превышение бюджета | отказ 429 | миллисекунды |
| Backpressure в очереди | ограниченный лаг | лаг консьюмера | замедление продюсера | секунды |
| Error budget | целевой SLO | сожжённая доля бюджета | заморозка релизов | недели |
| Наём под нагрузку | закрытые вакансии | недобор людей | офферы | месяцы |
Из таблицы видно главное свойство B-петель: они работают, но не мгновенно, и разброс постоянных времени — пять порядков. Именно из-за этого разброса возникает эффект, разобранный дальше: быстрая B-петля стабилизирует, медленная B-петля с задержкой раскачивает.
Ещё одно свойство B-петли, которое инженеры регулярно недооценивают: петля сопротивляется вашему вмешательству ровно так же, как внешнему возмущению. Если вы вручную снизили длину очереди, а автоскейлер настроен держать утилизацию, он честно вернёт систему в прежнюю точку. Это не «система сломана» — это регулятор работает. Меняйте цель, а не факт; идея развивается в главе «Точки воздействия».
AIMD в TCP — самый чистый инженерный пример уравновешивающей петли: аддитивный рост окна и мультипликативное падение при потере. Классический разбор — Jacobson, «Congestion Avoidance and Control» (SIGCOMM 1988); механика в применении к сети — в главе TCP.
Усиливающая петля: то, что растёт само
Усиливающая петля даёт экспоненту:
$$\frac{dx}{dt} = r \cdot x \quad\Longrightarrow\quad x(t) = x_0 \cdot e^{rt}, \qquad t_{2} = \frac{\ln 2}{r}$$
Время удвоения $t_2$ — единственное число, которое стоит помнить об R-петле. Оно отвечает на вопрос «сколько у меня времени до того, как станет вдвое хуже».
| Прирост за шаг | Время удвоения | Через 10 шагов | Через 30 шагов |
|---|---|---|---|
| 5% | ~14 шагов | ×1.6 | ×4.3 |
| 20% | ~3.8 шага | ×6.2 | ×237 |
| 100% (k = 2) | 1 шаг | ×1024 | ×10⁹ |
Третья строка — не гипербола, а конфиг retries: 3 без бюджета повторов.
Усиливающие петли, знакомые инженеру:
- Шторм ретраев. Ошибки → повторы → нагрузка → ещё ошибки. Ноль минусов, R.
- Деградация кэша. Падение hit rate → нагрузка на базу → рост латентности → таймауты на прогрев → ещё ниже hit rate. Механика самого кэша разобрана в «Кэшировании»; здесь важно, что при потере кэша нагрузка на источник растёт не на проценты, а в разы.
- Техдолг. Долг → медленнее вносить изменения → сильнее давление сроков → больше срезанных углов → больше долг.
- Выгорание дежурных. Шум алертов → усталость → медленнее реакция → длиннее инциденты → больше шума и меньше времени на починку алертов.
- Сетевой эффект и реферальный наём — те же R-петли, только желаемые.
Важнейшая оговорка: ни одна усиливающая петля не работает вечно. Экспонента всегда упирается в ресурс, и в этот момент включается B-петля — жёсткая и обычно неприятная: очередь переполняется, OOM-killer убивает процесс, люди увольняются. Вопрос не «остановится ли R», а «какая B её остановит и во что это обойдётся». Механика упора в предел — в главе «Нелинейность и пороги».
Как петли выглядят вместе
Реальная система — не одна петля, а несколько, конкурирующих за поведение. Минимальная честная схема надёжного сервиса содержит одну R и две B.
Читается так. R1 — усиливающая петля: ноль минусов, разгоняет сама себя. B1 (circuit breaker) — уравновешивающая, один минус, работает за миллисекунды. B2 (автоскейлер) — уравновешивающая, один минус, но с задержкой в минуты.
Отсюда сразу следует нетривиальный вывод, который схема делает очевидным, а список требований — нет: B2 не может защитить от R1. Постоянная времени шторма ретраев — секунды, автоскейлера — минуты. К моменту, когда приедут новые поды, шторм уже уничтожил систему, а новые реплики просто получат свою долю раздутого трафика. Единственная петля, играющая в той же временной лиге, — B1. Практический вывод: бюджет ретраев и размыкатель обязательны, автоскейлер их не заменяет; ровно это и рекомендуют AWS Builders’ Library о таймаутах и ретраях и глава Addressing Cascading Failures из Google SRE Book. Инженерные паттерны, реализующие B1, — в главе «Паттерны устойчивости».
Тот же шторм во времени, по шагам:
Шаг t4 — суть метастабильного отказа: система устойчива в нормальном режиме и устойчива в отказавшем, и внешнее возмущение может перекинуть её из первого во второй безвозвратно. Термин и таксономия — из работы «Metastable Failures in Distributed Systems» (HotOS 2021); разбор реальных случаев в проде — «Metastable Failures in the Wild» (OSDI 2022).
Четыре формы поведения
Полезное свойство петель: у каждой конфигурации есть характерный «почерк» на графике метрики.
- Экспонента вверх или вниз — доминирует R.
- Плавный выход на полку — доминирует B, полка равна цели петли.
- S-образная кривая — сначала доминировала R, потом её перехватила B (упёрлись в предел).
- Колебания вокруг уровня — B с задержкой: регулятор реагирует на устаревшее состояние, перелетает цель, компенсирует, снова перелетает.
Это работает и в обратную сторону как рабочий приём: увидели на дашборде затухающие колебания — ищите уравновешивающую петлю с задержкой, а не «шум». Увидели полку там, где ждали роста, — ищите ограничитель, который включился.
И сразу ограничение приёма: форма графика — не доказательство структуры, а гипотеза о ней. Экспоненциальный рост даёт и петля, и внешний тренд без всякой обратной связи. Колебания даёт и запаздывающий регулятор, и сезонность. Форма сужает пространство гипотез — проверять всё равно придётся отдельно.
Смена доминирующей петли
Самое практически важное свойство систем с несколькими петлями: доминирование меняется во времени, и именно момент смены выглядит как «система вдруг стала другой».
Три вывода, которые стоят отдельного внимания:
- Переход
O → M— не постепенная деградация, а смена режима. График до перехода выглядит «чуть хуже обычного». - Петля
M → M— то, что отличает метастабильный отказ от обычной перегрузки: снятие исходной причины не лечит. Отсюда практическое правило дежурного: если нагрузка вернулась к норме, а система нет — ищите петлю, а не причину всплеска. - Выход из
Mтребует размыкания петли, а не добавления мощности. Классический приём — сбросить накопленную очередь и впустить трафик частями. Добавление реплик в состоянииMчасто ухудшает ситуацию, потому что усиливает контур, а не разрывает.
Численный эксперимент: 20 строк, которые проверяют схему
Схема не предсказывает. Даже грубая численная модель — уже предсказывает. Разница между «красивой картинкой» и рабочим инструментом лежит примерно в этих двадцати строках.
Модель шторма ретраев на дискретном времени. Псевдокод:
на каждом шаге:
входящие = базовая_нагрузка + повторы_с_прошлого_шага
обслужено = min(входящие, ёмкость)
отказано = входящие - обслужено
повторы = k * отказано # k — среднее число повторов на отказ
если есть бюджет: повторы = min(повторы, бюджет * базовая_нагрузка)
def simulate(lam, cap, k, shock_at, shock_len, shock_mult, budget=None, steps=40):
"""Дискретная модель петли ретраев.
lam — базовая нагрузка, rps
cap — ёмкость сервиса, rps
k — сколько повторов порождает один отказ (коэффициент петли)
budget — доля базовой нагрузки, сверх которой повторы запрещены
"""
retries, history = 0.0, []
for t in range(steps):
in_shock = shock_at <= t < shock_at + shock_len
base = lam * (shock_mult if in_shock else 1.0)
arrivals = base + retries # замыкание петли: вход зависит от прошлого выхода
served = min(arrivals, cap)
failed = arrivals - served
retries = k * failed # усиливающая связь
if budget is not None: # уравновешивающая связь: бюджет повторов
retries = min(retries, budget * base)
history.append((t, arrivals, served, failed))
return history
Сложность: $O(T)$ по времени и $O(T)$ по памяти для истории (или $O(1)$, если хранить только текущее состояние). Для системы из $n$ связанных петель — $O(nT)$; численное интегрирование непрерывной версии методом Эйлера имеет ту же сложность, но требует шага $dt \ll \tau$ самой быстрой петли, иначе схема сама породит фальшивые колебания.
Что модель говорит без всякого запуска. Стационарная точка удовлетворяет $a = \lambda + k \cdot (a - C)$, откуда
$$a^{\ast} = \frac{k C - \lambda}{k - 1}, \qquad k > 1$$
Производная отображения равна $k$, значит при $k > 1$ эта точка неустойчива: любой всплеск, забросивший систему выше $a^{\ast}$, уводит её в разгон. При $k \le 1$ петля не может себя прокормить, и система возвращается к $\lambda$.
Что модель говорит после запуска (λ = 80 rps, ёмкость = 100 rps, k = 2, всплеск ×3 длиной 2 шага, порог $a^{\ast}$ = 120):
| Шаг | Без бюджета: входящие | С бюджетом 10%: входящие |
|---|---|---|
| 4 (норма) | 80 | 80 |
| 5 (всплеск) | 240 | 240 |
| 6 (всплеск) | 520 | 264 |
| 7 (всплеск снят) | 920 | 104 |
| 8 | 1720 | 88 |
| 9 | 3320 | 80 |
| 12 | 25 720 | 80 |
Всплеск длился два шага. Без бюджета система не вернулась никогда: на шаге 7 внешняя нагрузка уже нормальная, а входящий поток продолжает удваиваться. С бюджетом в 10% от базовой нагрузки — вернулась за три шага.
Отдельно проверяется чувствительность к $k$ — и результат жёстче, чем интуиция:
- $k = 2$: даже кратковременный всплеск ×1.4 (пик 112 rps, чуть выше ёмкости) уводит систему в разгон, потому что за два шага она перепрыгивает порог 120;
- $k = 1$: система выживает при всплеске ×3, но расхлёбывает долго — время возврата примерно $(a_{\max} - C)/(C - \lambda)$ шагов, то есть тем дольше, чем ближе штатная утилизация к ёмкости;
- $k = 0.5$: всплеск гасится за пару шагов.
Это уже инженерные требования, а не философия: коэффициент петли ретраев должен быть строго меньше единицы, и запас ёмкости $C - \lambda$ — не «неэффективно потраченные деньги», а время на восстановление. Как измерять ёмкость и всплески — в главе о нагрузочном тестировании; как ретраи взаимодействуют с гарантиями доставки — в главе об идемпотентности.
Обратите внимание, чего модель не делает: она не знает про jitter, про разное поведение мобильных клиентов, про то, что часть повторов идёт мимо балансировщика. Она отвечает ровно на один вопрос — «может ли контур себя прокормить», — и на него отвечает надёжно.
Пять петель, которые вы уже видели
Очередь и автоскейлер (B с задержкой). Цель — целевая утилизация. Задержка — время старта пода плюс окно усреднения. Симптом доминирования задержки — «пила» на графике числа реплик. Диагноз проверяется без теории: сравните период колебаний с удвоенной постоянной времени петли; совпадение — сильный аргумент за то, что колебания порождает сам регулятор, а не трафик. Лечение — уменьшать задержку (прогретые пулы, предиктивное масштабирование) или снижать усиление (шире гистерезис, длиннее cooldown), а не «настроить пороги точнее».
Кэш и метастабильный отказ (R). Петля: hit rate ↓ → нагрузка на источник ↑ → латентность ↑ → таймауты на прогрев ↑ → hit rate ↓. Ключевая величина здесь — не hit rate, а во сколько раз вырастет нагрузка на источник при его падении. Проверяемое предсказание: если кэш даёт 99% попаданий, то полная потеря кэша означает стократный трафик на базу — и вопрос «переживёт ли база холодный старт» имеет численный ответ, который можно получить на стенде.
Техдолг (R). Петля правдоподобна и знакома каждому, но признаем честно: это самая слабая по доказательной базе петля в списке. «Объём техдолга» не имеет общепринятой операционализации, а измеримые прокси (время сборки, доля правок в одних и тех же файлах, lead time изменения, доля откатов) измеряют не долг, а его следствия. Что можно сделать проверяемым: сформулировать конкретную стрелку — «медиана времени от коммита до прода в модуле X растёт месяц к месяцу при неизменном размере изменений» — и проверить её на исторических данных. Что нельзя: рисовать схему из шести узлов со словом «качество» и считать её знанием.
Наём и онбординг (B, обвитая R). Уравновешивающая часть: нехватка людей → наём → больше рук → нехватка меньше. Усиливающая часть, которая всё портит: новые люди требуют времени опытных → у опытных меньше времени на работу и на ревью → сроки горят → нанимаем ещё. Задержка между офером и продуктивностью — месяцы, поэтому эффект «добавили людей, стало медленнее» вполне может быть не мифом, а нормальной динамикой B-петли с большой $\tau$ и паразитной R. Проверяемый признак: если провал производительности длится примерно столько же, сколько онбординг, и его глубина растёт с долей новичков — гипотеза работает. Если провал не кончается после онбординга — дело не в петле найма. Практика найма разобрана в главе «Наём».
Дежурство и алерты (R + перенос проблемы). Шумные алерты → усталость → медленнее реакция и меньше времени на починку причин → добавляем ещё алертов «чтобы точно не пропустить» → больше шума. Классический перенос проблемы: симптоматическое решение (алерт) работает быстро, фундаментальное (убрать причину) — медленно, и петля симптоматического решения побеждает по времени отклика. Проверяемая метрика — доля алертов, потребовавших действия; если она падает квартал к кварталу, петля работает. Организация дежурств — в главе «Наблюдаемость и дежурства»; отдельный трек про надёжность на портале пока в работе.
Типовые ловушки
«Петля есть везде». Две метрики движутся вместе — это ещё не контур. Прежде чем рисовать стрелку в обратную сторону, ответьте: каким механизмом B влияет на A и за какое время? Если ответ «ну, косвенно» — стрелки нет.
Забыли ограничитель. Схема с одной R-петлей всегда предсказывает бесконечный рост, а значит заведомо неверна. Если вы не нарисовали B, которая её остановит, вы просто не знаете, где предел — и получите его в виде аварии, а не в виде плавного выхода на полку.
Перепутанная полярность из-за формулировок. Смешение «растёт/падает» в узлах вместо величин: узел должен называться «длина очереди», а не «очередь растёт». Иначе знак связи удваивается и полярность контура ломается.
Перенос проблемы (shifting the burden). Быстрое симптоматическое решение снимает боль и одновременно снижает мотивацию решать причину; со временем вокруг костыля вырастает зависимый процесс, и убрать его дороже, чем терпеть. Признак — «временное решение» старше года, у которого есть свой владелец и своя документация.
Эскалация. Две R-петли, замкнутые через сравнение: каждая сторона усиливает действие в ответ на действие другой. Инженерный вид — гонка таймаутов между сервисами: A уменьшает таймаут, чтобы не ждать B; B видит рост отказов и добавляет ретраи; A видит рост нагрузки и уменьшает таймаут ещё сильнее.
Трагедия общего ресурса. Каждый потребитель локально рационально увеличивает потребление общего ресурса (пул соединений к базе, общий кластер, квота на CI), потому что издержки размазаны на всех. Итог — деградация для всех. Лечится не уговорами, а квотами и видимостью потребления, то есть достройкой отсутствующей B-петли.
Локальная оптимизация. Каждая команда честно оптимизирует свою метрику; сумма локальных оптимумов не даёт глобального. Разбор — в главе «Локальная оптимизация», а про то, как метрика превращается в цель B-петли и перестаёт быть измерением, — в главе о продуктовых метриках.
Систематический каталог этих структур — в главе «Системные архетипы». Здесь важно другое: архетип — это шаблон для поиска, а не диагноз. Узнав архетип, вы получаете список того, что стоит измерить, а не право утверждать, что так оно и есть.
Пределы метода
Теперь честная часть. Диаграмма причинных петель — самый соблазнительный инструмент системного мышления и самый лёгкий для самообмана. Вот чего она не делает.
Не даёт величин. Схема говорит, что R-петля есть. Она не говорит, доминирует ли эта петля при текущих параметрах. Пример из разобранного эксперимента: контур ретраев существует всегда, но разрушает систему только при $k > 1$ и только при всплеске выше порога. Схема одинакова для безопасной и смертельной конфигурации.
Не даёт времени. На картинке B1 и B2 — две одинаковые стрелки со знаком минус. В реальности между ними три порядка по времени отклика, и именно это определяет исход. Без постоянных времени схема систематически вводит в заблуждение.
Знак связи может меняться. «Больше реплик → меньше латентность» верно до точки, где реплики начинают конкурировать за соединения к базе, и дальше знак переворачивается. Диаграмма с фиксированными знаками неявно предполагает линейность там, где её нет; см. «Нелинейность и пороги».
Схема неопровержима, если её не приземлить. Диаграмму из десяти узлов можно нарисовать для чего угодно, и она будет выглядеть убедительно. Это ровно тот случай, когда объяснительная сила максимальна, а предсказательная равна нулю. Хорошая проверка: какое наблюдение заставило бы вас стереть эту стрелку? Если ответа нет — стрелка декоративная.
Ретроспективная подгонка. После инцидента любая схема отлично объясняет случившееся. Ценность имеет только та петля, которую вы описали до следующего инцидента и которая предсказала его форму.
Как сделать петлю проверяемой
Рабочая процедура, пять шагов, каждый обязателен:
- Назовите узлы величинами, которые кто-то уже измеряет или может начать измерять завтра. Не «качество кода», а «доля PR, потребовавших более двух раундов ревью».
- Для каждой стрелки укажите знак, время отклика и порядок величины («+, 30–60 с, рост очереди на 1000 добавляет ~200 мс к p99»).
- Сформулируйте предсказание в форме, которую можно опровергнуть: «если увеличить cooldown автоскейлера с 1 до 5 минут, амплитуда колебаний числа реплик упадёт не менее чем вдвое».
- Постройте минимальную численную модель — двадцать строк, как выше. Не для точности, а чтобы обнаружить, что схема не воспроизводит даже качественно то, что видно на графиках.
- Проверьте на исторических данных прошлого инцидента, а потом — проспективно, на следующем.
Если шаги 3–5 невозможны — так и напишите на схеме: «гипотеза, не проверена». Это нормальное состояние для многих петель; ненормально выдавать её за вывод.
Не всякую петлю стоит доводить до численной модели. Ориентир по приоритетам:
Логика простая: быстрые и хорошо наблюдаемые петли обязаны иметь численную модель и тест — они убивают систему за минуты, и цена ошибки высока. Медленные и плохо наблюдаемые петли (техдолг, выгорание) численной модели не заслуживают: точность будет фальшивой. Для них честный формат — записанная гипотеза с одной-двумя прокси-метриками и регулярный возврат к ней.
Честно про доказательную базу
Аппарат петель пришёл из двух разных традиций, и у них очень разный статус.
Что имеет твёрдую опору. Теория автоматического управления: устойчивость, запас по фазе, влияние запаздывания на колебания — это математика с доказательствами и стопроцентно инженерная практика. Всё, что в этой главе сказано про постоянные времени, коэффициент петли и порог $k > 1$, живёт именно там, и проверяется на стенде за час.
Что имеет опору экспериментальную. Эксперименты Стермана с «пивной игрой» (Management Science, 1989) — воспроизводимые лабораторные результаты: люди систематически недооценивают задержки в цепочке поставок и порождают колебания там, где спрос стабилен. Это одно из немногих количественных подтверждений того, что «неверная оценка обратной связи» — реальный и измеримый эффект, а не метафора.
Что остаётся спорным. Крупные модели социальных систем. «Пределы роста» (1972) на модели World3 вызвали содержательную критику: Уильям Нордхаус в «World Dynamics: Measurement Without Data» (The Economic Journal, 1973) указывал, что ключевые уравнения не откалиброваны по данным, а результаты чувствительны к произвольно выбранным коэффициентам. Позднейшие сверки — Turner, 2008 и Herrington, 2021 — показывают, что часть агрегированных траекторий сценария «business as usual» лежит близко к фактическим данным; критики отвечают, что близость агрегатов при неверной механике — слабое подтверждение, и что модель не проходила проверку вне выборки. Спор идёт пятьдесят лет и не закрыт.
Практический вывод для инженера, а не для спорщика: чем крупнее объект модели, тем слабее её предсказательная сила и тем осторожнее формулировки. Петля ретраев в одном сервисе проверяется за час. Петля техдолга в компании — годами и с неоднозначным результатом. Использовать один и тот же уверенный тон для обеих — интеллектуально нечестно.
И отдельно: не стоит превращать системное мышление в пересказ одной книги. У Медоуз («Thinking in Systems», 2008) — лучший из известных введений в язык петель, запасов и точек воздействия, и одновременно текст, где нормативные утверждения соседствуют с описательными. У Форрестера — сильная инженерная интуиция и слабая эмпирическая дисциплина. У Стермана («Business Dynamics», 2000) — самый аккуратный учебник, с главами о валидации моделей и о том, почему большинство моделей проваливает проверку. У Сенге («Пятая дисциплина», 1990) — популяризация архетипов, полезная как словарь и бесполезная как доказательство. Читать стоит всех, ссылаться как на авторитет — ни на кого.
Чеклист: разбор петли за пятнадцать минут
- Назовите величину, поведение которой вас беспокоит, и нарисуйте её график за реальный период.
- Определите форму: экспонента, полка, S-кривая, колебания.
- Выпишите 3–6 величин, влияющих на неё, и проверьте, замыкается ли хоть одна обратно.
- Расставьте знаки, считая только «от роста». Посчитайте минусы: чётно — R, нечётно — B.
- Для каждой стрелки припишите время отклика. Сравните времена конкурирующих петель — обычно исход определяет самая быстрая.
- Найдите ограничитель у каждой R-петли. Не нашли — вы не знаете, где предел.
- Найдите цель у каждой B-петли и спросите, кто её задал и можно ли её изменить.
- Сформулируйте одно опровержимое предсказание.
- Решите по квадранту выше: строить численную модель или оставить гипотезой.
- Запишите дату и вернитесь к записи после следующего инцидента.
Мини-итог
- Петля — замкнутая причинная цепочка с ненулевым временем обхода. Не замкнуто — не петля; корреляция — не связь.
- Полярность считается, а не угадывается: чётное число минусов — усиливающая R, нечётное — уравновешивающая B.
- R даёт экспоненту; её единственная важная характеристика — время удвоения, и она всегда обрывается о какой-то предел.
- B даёт выход на цель; её важная характеристика — постоянная времени, и она сопротивляется вашему вмешательству так же, как чужому.
- Когда петель несколько, исход определяет не наличие петли, а соотношение усилений и времён. Быстрая B побеждает быструю R; медленная B бессильна.
- Уравновешивающая петля с задержкой не стабилизирует, а раскачивает.
- Метастабильный отказ — практическое имя для ситуации, когда R замкнулась и снятие исходной причины больше не помогает.
- Схема без чисел не предсказывает. Двадцать строк симуляции превращают картинку в инструмент.
- Статус утверждений разный: теория управления — доказана, эксперименты Стермана — воспроизводимы, крупные социальные модели — спорны. Тон должен соответствовать.
Источники
- Donella Meadows. Thinking in Systems: A Primer (2008) — chelseagreen.com; её же эссе «Leverage Points: Places to Intervene in a System».
- John Sterman. Business Dynamics: Systems Thinking and Modeling for a Complex World (2000) — учебник с главами о валидации моделей.
- John Sterman. Modeling Managerial Behavior: Misperceptions of Feedback in a Dynamic Decision Making Experiment — Management Science, 1989.
- William Nordhaus. World Dynamics: Measurement Without Data — The Economic Journal, 1973.
- Graham Turner. A comparison of The Limits to Growth with 30 years of reality — Global Environmental Change, 2008.
- Gaya Herrington. Update to Limits to Growth — Journal of Industrial Ecology, 2021.
- Van Jacobson. Congestion Avoidance and Control — SIGCOMM 1988, PDF.
- Bronson et al. Metastable Failures in Distributed Systems — HotOS 2021, PDF.
- Huang et al. Metastable Failures in the Wild — OSDI 2022.
- Google SRE Book: Addressing Cascading Failures, Handling Overload.
- AWS Builders’ Library: Timeouts, retries and backoff with jitter.
- System Dynamics Society — systemdynamics.org, журнал System Dynamics Review.
Что дальше
Мы разобрали, как петли задают поведение, но обошли вопрос, что именно в них накапливается. Автоскейлер реагирует на длину очереди, а не на нагрузку; шторм ретраев страшен тем, что копит невыполненную работу. Величина, которая накапливается, и величина, которая течёт, — разные сущности с разной математикой, и путаница между ними порождает самые дорогие ошибки в рассуждениях о системах.
Дальше — Запасы и потоки: почему очередь растёт, а нагрузка та же.