Процесс, работавший месяцами, редко падает громко. В источнике что-то поменяло формат, и дальше процесс считает по неверным данным.
Содержание5 разделов
Поломка, которая о себе не сообщает
Остановившаяся автоматизация - маленькая беда. Она встала, в течение часа кто-то это заметил, и причина очевидна, потому что сломалось то, что меняли последним.
Дорого обходится поломка, при которой всё продолжает работать. В источнике переименовали поле, код, который его читает, получает пустоту, а пустота в большинстве процессов допустима: незаполненный комментарий, невыставленный флаг, отсутствующая вторая строка адреса. Ошибки не возникает. Процесс выдаёт записи, неотличимые от записей прошлой недели, и выдаёт их до тех пор, пока кто-нибудь не сверит руками два числа.
Что меняется на самом деле
Почти всё сводится к четырём случаям.
Поле переименовали или перенесли, обычно наводя порядок, который никто не считал изменением для внешних потребителей. В ответе появился лишний уровень вложенности, потому что поставщик добавил обёртку для постраничной выдачи или метаданных. В перечислении завелось новое значение, новый статус заказа или новый тип документа, и ветка, которая разбирает известные значения, молча отбрасывает неизвестное. Старую версию API отключили, и вместо ошибки по умолчанию пришёл ответ в старом формате.
Аварией ничто из этого не выглядит: каждая такая перемена - строчка в чужих примечаниях к релизу, написанная во вторник после обеда.
Три защиты, все дешёвые
Первая - одна проверочная запись, которая каждое утро проходит весь маршрут. Это искусственный объект, результат которого на выходе сверяют с заранее известным ответом. Он нагружает стыки между системами, а дрейф возникает именно на стыках: четыре сервиса могут быть исправны каждый по отдельности и при этом передавать друг другу уже изменившиеся данные.
Вторая - проверять структуру ответа, а не статус. Ответ 200 с телом, которое удалось разобрать, не доказывает, что тело значит то же, что месяц назад. Проверяйте, что нужные поля на месте и у них правильный тип, а если это не так, останавливайте процесс с явной ошибкой. Это десять строк кода, и они превращают тихий неверный ответ в заметную остановку.
Третья - оповещения по распределению результатов, а не по исключениям. Если в прошлом месяце на ручную обработку уходил один объект из двадцати, а сегодня уходит один из шести, это и есть сигнал, хотя ни одного исключения не возникло. Работает это, только если обычные числа записали заранее, и зачем это нужно, объяснено в тексте про измеренную базу.
Почему это вопрос границ, а не сопровождения
Любая интеграция - зависимость от чужого графика релизов. Плохой идеей её это не делает: доставка в прокатной компании из текста куда уходят четыре часа берёт данные о наличии из системы, которой мы не управляем, и всё равно окупается. Но такую зависимость нужно оценить заранее.
На практике это выглядит так. Согласуя границы процесса, перечислите всё, что он берёт из внешних систем, и для каждого пункта скажите, что произойдёт, если там поменяется формат. Про большинство пунктов ответ будет «процесс встанет, и пусть встаёт». Там, где ответ звучит как «поедет дальше, и мы не узнаем», проверочная запись нужна до запуска, а не после первого плохого месяца.
То, что называть не хочется
Процесс, за который не отвечает ни один человек, проверяет тот, кто случайно посмотрел, а на практике клиент, приславший жалобу. Имя ответственного попадает в документ передачи вместе со всем остальным, и это должно быть имя человека, у которого есть мнение о том, как процесс устроен, а не того, кто был свободен на той неделе. Почему передача - отдельный этап, а не последний день сборки, объяснено в тексте что обязан выдать аудит процессов. Дописать этот документ потом не получится: человек, который забыл, что было непонятно, уже не сможет это записать.
Часто задаваемые вопросы
Почему изменение интеграции ломает всё тихо?
Потому что у интеграции обычно проверяют, прошёл ли вызов, а не какая структура у ответа. Вызов вернул двести, тело разобралось, процесс поехал дальше. Если поле переименовали, читающий его код получает пустоту и обращается с ней как с обычным пустым значением: комментарий не заполнен, вторая строка адреса отсутствует, приоритет не выставлен. Всё это где-то в процессе допустимо, поэтому ошибки не возникает. Процесс продолжает выдавать записи, неотличимые от записей прошлой недели, и единственный сигнал - сместившиеся результаты, за которыми никто не следит.
Что такое проверочная запись и почему она работает?
Один искусственный объект, каждое утро проходящий весь маршрут целиком: создан, направлен, преобразован, доставлен, - результат которого на выходе сверяют с заранее известным. Работает он потому, что нагружает стыки между системами, а не отдельную систему, а дрейф возникает именно на стыках. Мониторинг, который пингует каждый сервис по отдельности, доложит о четырёх здоровых сервисах, даже если то, что они передают друг другу, уже изменилось. Стоит это одну запись в день и отвечает на вопрос, который поштучные проверки задать не умеют.
Как отличить дрейф от обычного разброса?
Для этого обычный уровень нужно записать до запуска, ради этого и существует этап замера: объёмы за неделю, доля объектов, уходящих в исключения, разброс времени обработки. Дрейф меняет не уровень этих чисел, а их распределение: среднее остаётся прежним, а хвост уезжает, или доля исключений за ночь переходит с одного из двадцати на один из шести. Без базы те же числа нечитаемы, потому что никто не может сказать, необычная эта неделя или нет.
Чья это работа - заметить?
Того, кого назвали по имени до запуска. Процесс без владельца проверяет тот, кто случайно посмотрел, а на практике это означает - после жалобы клиента. Имя стоит в документе передачи рядом с тем, что процесс делает, чего он не должен делать никогда и какое предупреждение о чём говорит. Поэтому передача - этап, а не последний день сборки: система, за которую никого не сделали ответственным, работает на допущении, что ничего не изменится, а что-нибудь меняется всегда.



