Главная страница
Навигация по странице:

  • Сложности непрерывной интеграции

  • Герметичное тестирование

  • ГЕРМЕТИЧНЫЙ GOOGLE ASSISTANT

  • Делай как вGoogle


    Скачать 5.77 Mb.
    НазваниеДелай как вGoogle
    Дата31.05.2022
    Размер5.77 Mb.
    Формат файлаpdf
    Имя файлаDelay_kak_v_Google_Razrabotka_programmnogo_obespechenia_2021_Tom.pdf
    ТипДокументы
    #559735
    страница62 из 69
    1   ...   58   59   60   61   62   63   64   65   ...   69
    481
    НЕПРЕРЫВНАЯ ИНТЕГРАЦИЯ — ЭТО СИСТЕМА ОПОВЕЩЕНИЯ
    Титус Винтерс
    Как и в случае ответственных систем, для надежного обслуживания программных систем необходим постоянный автоматический мониторинг. По аналогии с системами монито- ринга и оповещения в продакшене, которые помогают понять, как эти среды реагируют на изменения, система непрерывной интеграции показывает, как наше ПО реагирует на из- менения в своей среде. Подобно мониторингу, использующему пассивные предупреждения и активные средства контроля, непрерывная интеграция использует юнит- и интеграцион- ные тесты для обнаружения изменений в ПО до его развертывания. Сравнение этих двух областей позволяет нам переносить опыт и знания из одной области в другую.
    И система непрерывной интеграции, и система оповещения в продакшене служат одной цели: максимально быстро выявлять проблемы. Непрерывная интеграция ориентирована на раннее выявление проблем в процессе разработки и обнаруживает ошибки с помощью тестирования. Система оповещения следит за противоположным концом того же рабочего процесса и выявляет проблемы, наблюдая за показателями и сообщая, когда они превы- шают некоторые пороговые значения. Обе системы являются формами «автоматического выявления проблем как можно скорее».
    Надежная система оповещения помогает гарантировать выполнение целей уровня об- служивания (SLO, service-level objectives). Хорошая система непрерывной интеграции помогает гарантировать, что процесс сборки выполняется корректно — код компили- руется, тесты завершаются успехом, и вы можете развернуть новую версию, если это потребуется. Передовой опыт в обеих областях в значительной степени сосредоточен на идеях точности и полезности предупреждений: тесты должны терпеть неудачу, только когда нарушается какое-то важное базовое условие, а не потому, что тест хрупкий или нестабильный. Нестабильный тест, терпящий неудачу через каждые несколько циклов непрерывной интеграции, является такой же проблемой, как и ложное предупреждение, срабатывающее каждые несколько минут. Если такое предупреждение невозможно ис- править, оно не должно быть предупреждением. Если базовое условие не нарушается, тест не должен терпеть неудачу.
    Системы непрерывной интеграции и оповещения имеют общую концептуальную основу.
    Например, существует определенная связь между локальными сигналами (юнит-тесты, мониторинг изолированной статистики или оповещение на основе причин) и перекрест- но-зависимыми сигналами (интеграционные тесты и тесты предварительной версии, зон- дирование методом черного ящика). Самыми точными индикаторами работоспособности комплексной системы являются сквозные сигналы, но за их точность приходится платить нестабильностью, увеличенной ресурсоемкостью и трудностями в устранении основных причин.
    Также есть связь между отказами в обеих областях. Неустойчивые оповещения срабаты- вают при пересечении произвольного порогового значения (например, числа повторных попыток за последний час), без наличия фундаментальной связи между этим порогом и ра- ботоспособностью системы с точки зрения конечного пользователя. Хрупкие тесты терпят неудачу, когда нарушается произвольное условие, и при этом не обязательно существует фундаментальная связь между этим условием и корректностью тестируемого ПО. Чаще всего такие тесты легко пишутся и могут пригодиться при отладке более серьезной про- блемы. В обоих случаях они являются приблизительными показателями общего состояния работоспособности, не отражая целостного поведения. Если нет простого сквозного сигнала,

    482
    Глава 23. Непрерывная интеграция но вы легко можете получить некоторую совокупную статистику, то команды напишут по- роговые предупреждения на основе произвольной статистики. Если нет высокоуровневого способа сказать: «Тест должен терпеть неудачу, если декодированное изображение не по- хоже хотя бы примерно на это декодированное изображение», то команды создадут тесты, проверяющие идентичность потоков байтов.
    Предупреждения, основанные на причинах, и хрупкие тесты все еще могут иметь значение.
    Они просто не являются идеальным способом выявления потенциальных проблем в сце- нарии оповещения. В случае фактического сбоя для отладки полезно иметь как можно больше сведений. Когда специалисты по надежности отлаживают сбой, их интересует информация в форме: «Час назад пользователи начали чаще сталкиваться с неудачами при выполнении запросов. Примерно в то же время стало расти количество повторных попыток.
    Начнем расследования оттуда». Точно так же хрупкие тесты могут дать дополнительную отладочную информацию: «Конвейер отображения изображений начал выдавать мусор.
    Один из юнит-тестов предполагает, что мы получаем разные байты от компрессора JPEG.
    Начнем расследования оттуда».
    Мониторинг и оповещения относятся к области управления надежностью, где хорошо из- вестно понятие «бюджет ошибок»
    1
    , тогда как непрерывная интеграция все еще опирается на абсолютные значения. Отношение к непрерывной интеграции как к «сдвигу оповещений влево» позволяет шире рассуждать об этих политиках и находить более удачные практики:
    • Обеспечение 100 % зеленых тестов на этапе непрерывной интеграции, как и 100 % без- отказности службы в продакшене, стоит ужасно дорого. Если вы действительно ставите перед собой такую цель, то одной из самых больших проблем для вас станет состояние гонки между тестированием и фиксациями.
    • Рассматривать все оповещения как равноценные причины для тревоги обычно непра- вильно. Если оповещение появляется в продакшене, но в действительности не влияет на работу службы, то правильнее будет отключить такое оповещение. То же относится к ошибкам в тестах: пока наши системы непрерывной интеграции не научатся говорить:
    «Известно, что этот тест терпит неудачу по несущественным причинам», — нам, вероятно, следует более либерально принимать изменения, которые отключают тест, терпящий неудачу. Не все неудачи при тестировании могут служить признаками предстоящих проблем в продакшене.
    • Политики, гласящие: «Никто не должен выполнять фиксацию в репозиторий, пока цикл непрерывной интеграции не завершится успехом», — скорее всего, ошибочны. Если не- прерывная интеграция сообщает о проблеме, ее обязательно нужно исследовать, прежде чем позволить инженерам зафиксировать новые изменения или усугубить проблему.
    Но если причина хорошо изучена и не влияет на работоспособность в продакшене, то блокировать фиксации будет неразумно.
    Такое отношение к системе непрерывной интеграции, как к «системе оповещения», пока не получило широкого распространения, и мы все еще пытаемся понять, какие параллели более уместны. Принимая во внимание высокие ставки, неудивительно, что специалисты по надежности тщательно проанализировали опыт, связанный с мониторингом и опове-
    1
    Стремление к 100%-ной работоспособности — ошибочная цель. Выберите другой порог, на- пример 99,9 или 99,999%, в качестве компромисса, определите и отслеживайте фактическое время безотказной работы и используйте этот «бюджет» как исходную информацию о том, насколько агрессивно вы готовы продвигать рискованные версии.

    Идеи непрерывной интеграции
    483
    щениями, но все еще считают непрерывную интеграцию роскошью
    1
    . В ближайшие не- сколько лет задача программной инженерии будет состоять в том, чтобы переосмыслить существующую практику поддержания высокой надежности и безотказности в контексте непрерывной интеграции, чтобы помочь реформировать ландшафт тестирования и непре- рывной интеграции — и, возможно, передовой опыт тестирования сможет помочь прояснить цели и политики мониторинга и оповещения.
    Сложности непрерывной интеграции
    Мы обсудили некоторые из устоявшихся практик непрерывной интеграции и позна- комились с некоторыми связанными с этим проблемами, такими как потенциальное нарушение продуктивности инженеров из-за медленных и конфликтующих тестов или просто из-за слишком большого их количества. Ниже перечислено еще несколько дополнительных проблем, сопутствующих внедрению непрерывной интеграции:
    y
    Оптимизация предварительной проверки, в том числе определение, какие тесты запускать во время проверки перед фиксацией с учетом потенциальных проблем, описанных выше, и как их запускать.
    y
    Выявление причин и изоляция сбоев, в том числе определение, какой код или измене- ние вызывает проблему и в какой системе произошел сбой. «Интеграция с вышесто- ящими микросервисами» — это один из подходов к изоляции сбоев в распределенной архитектуре, когда требуется выяснить, что является источником ошибки — соб- ственные службы или внешние. Этот подход предполагает опробование в проме- жуточной среде комбинаций ваших стабильных служб с новыми внешними микро- сервисами (то есть интеграцию последних версий внешних микросервисов в свои тесты). Этот подход может осложняться явлением перекоса версий: эти среды не только часто оказываются несовместимыми, но также содержат ложноположитель- ные срабатывания при комбинациях, которые не будут наблюдаться в продакшене.
    y
    Ограниченный объем ресурсов. Для выполнения тестов требуются ресурсы, и боль- шие тесты могут быть очень дорогостоящими. Кроме того, затраты на поддержку инфраструктуры для автоматизированного тестирования могут оказаться весьма значительными.
    Существует также проблема управления сбоями — что делать, если тесты завершаются неудачей. Обычно мелкие проблемы можно быстро исправить, но многие наши ко- манды считают, что очень трудно обеспечивать постоянный успех тестового набора, когда в нем присутствуют большие сквозные тесты. Они по своей природе склонны к нестабильности и сложны в отладке. Должен быть механизм для их временного отключения и отслеживания без остановки процесса выпуска. В Google широко используется метод «горячих списков» ошибок, которые заполняются дежурным
    1
    Мы считаем, что на самом деле непрерывная интеграция играет важнейшую роль в экоси- стеме программной инженерии: это не роскошь, а обязательный элемент. Но пока не все это поняли.

    484
    Глава 23. Непрерывная интеграция инженером или специалистом по выпуску и передаются соответствующей команде.
    Еще лучше, когда эти ошибки могут автоматически генерироваться и регистриро- ваться. Такая возможность поддерживается в некоторых наших крупных продуктах, таких как Google Web Server (GWS) и Google Assistant. Горячие списки должны тщательно проверяться, чтобы гарантировать немедленное исправление любых ошибок, блокирующих выпуск. Также следует исправлять другие, менее срочные ошибки, чтобы набор тестов продолжал приносить пользу, а не превратился в груду старых отключенных тестов. Часто проблемы, обнаруживаемые при анализе сбоев сквозных тестов, на самом деле связаны с тестами, а не с кодом.
    Узкая специализация тестов подрывает уверенность в них, поскольку сбой в них происходит непостоянно и найти в таких тестах изменение для отката труднее, чем в тестах, терпящих неудачу. Некоторые команды полагаются на инструменты вре- менного исключения узкоспециализированных тестов из предварительной проверки, пока их поведение исследуется и исправляется. Это сохраняет высокую степень уверенности в тестах и дает больше времени на устранение проблемы.
    Нестабильность тестов порождает еще одну серьезную проблему, которую мы рассматривали в контексте предварительной проверки. Один из способов решения этой проблемы — выполнять такие тесты несколько раз. Это достигается с помо- щью обычного параметра конфигурации тестов, который широко используют наши команды. Кроме того, в различных точках в коде теста тоже могут выполняться повторные попытки.
    Другой подход, помогающий справиться с нестабильностью тестов (и с другими проблемами непрерывной интеграции), — герметичное тестирование, которое мы рассмотрим в следующем разделе.
    Герметичное тестирование
    Поскольку взаимодействиям с живым сервером присуща некоторая ненадежность, для выполнения тестов с широким охватом мы часто используем герметичные сер- веры (
    https://oreil.ly/-PbRM
    ). Это особенно полезно, когда тесты должны выполняться на этапе предварительной проверки перед фиксацией и стабильность имеет перво- степенное значение. Идею герметичного тестирования мы упоминали в главе 11:
    Герметичные тесты выполняются в тестовой среде (то есть используют серве- ры приложений и их ресурсы), которая полностью автономна (то есть не имеет внешних зависимостей, таких как серверы).
    Герметичные тесты обладают двумя важными свойствами: высоким детерминиз- мом (то есть стабильностью) и изолированностью. Герметичные серверы зависят от системного времени, генерации случайных чисел и состояний гонки, но герметич- ные тесты не зависят от внешних зависимостей, поэтому при каждом выполнении с одним и тем же приложением код теста возвращает одни и те же результаты. Если герметичный тест терпит неудачу, высока вероятность, что это связано с изменени- ем кода приложения или тестов (они могут завершаться неудачей из-за редчайшей

    Идеи непрерывной интеграции
    485
    реорганизации герметичной тестовой среды). По этой причине, когда системы не- прерывной интеграции повторно запускают тесты через несколько часов или дней, чтобы получить дополнительные сигналы, герметичность упрощает локализацию ошибок тестирования.
    Другое важное свойство — изолированность — означает, что проблемы продакшена не должны влиять на тесты. Обычно мы выполняем такие тесты на одном компьютере, по- этому нам не нужно беспокоиться о проблемах с подключением к сети. Верно и обрат- ное: проблемы, выявленные герметичными тестами, не должны влиять на продакшен.
    Успех герметичного теста не должен зависеть от пользователя, выполняющего тест.
    Это позволяет инженерам воспроизводить тесты, выполняемые системой непре- рывной интеграции, и запускать тесты (например, разработчикам библиотек), при- надлежащие другим командам.
    Один из видов герметичного тестирования основан на использовании фиктивного сервера. Этот подход может обойтись дешевле, чем запуск реального сервера, но требует усилий для поддержки и имеет ограниченную точность (глава 13).
    Самый чистый вариант интеграционного тестирования перед фиксацией — создать полностью герметичную конфигурацию, то есть запустить весь стек в изолированной программной среде
    1
    , и в Google есть готовые конфигурации таких тестовых сред для популярных компонентов, таких как базы данных. Этот вариант проще реализовать для небольших приложений с незначительным количеством компонентов, но в Google есть исключение: DisplayAds запускает около четырехсот серверов на этапе предва- рительной проверки перед каждой фиксацией, а также после фиксации. Однако уже после создания этой системы большую популярность приобрела парадигма записи и воспроизведения для тестирования крупных систем, которая обходится дешевле, чем запуск большого стека в изолированной среде.
    Системы записи и воспроизведения (глава 14) записывают ответы действующих сер- веров, кешируют их и воспроизводят в герметичной тестовой среде. Запись и воспро- изведение — мощный инструмент, помогающий уменьшить нестабильность во время тестирования, но увеличивающий хрупкость тестов. Трудно найти баланс между:
    Ложноположительными результатами
    Тест выполняется успешно из-за слишком частого попадания в кеш, хотя так не должно быть, потому что есть вероятность упустить проблемы, которые могут возникнуть при получении нового ответа.
    Ложноотрицательными результатами
    Тест терпит неудачу из-за слишком редкого попадания в кеш, хотя так не должно быть. Для решения этой проблемы требуется обновить кеш с ответами, что может занять много времени и привести к сбоям тестов, требующим исправления, многие
    1
    На практике часто сложно создать полностью изолированную тестовую среду, тем не менее стабильность можно повысить, уменьшив до минимума количество внешних зависимостей.

    486
    Глава 23. Непрерывная интеграция из которых могут не быть реальными проблемами. Этот процесс часто блокирует фиксацию изменений и далек от идеала.
    В идеале система записи и воспроизведения должна обнаруживать только про- блемные изменения и реагировать на промах кеша, только если запрос существенно изменился. Если такое изменение вызывает проблему, автор изменения должен повторить тестирование с обновленным ответом, убедиться, что тест по-прежнему терпит неудачу, и только тогда интерпретировать неудачу как предупреждение о проблеме. На практике узнать, когда в большой и постоянно меняющейся системе запрос изменился значимым образом, может быть невероятно сложно.
    ГЕРМЕТИЧНЫЙ GOOGLE ASSISTANT
    Google Assistant предлагает инженерам платформу для выполнения сквозных тестов, в том числе средства тестирования с возможностью настройки запросов, позволяющие указать, следует ли смоделировать процессы на телефоне или на устройстве умного дома, и про- верить ответы во время обмена с Google Assistant.
    В качестве примера можно вспомнить одну из самых известных историй успеха полной герметизации набора тестов на этапе предварительной проверки. На начальном этапе ко- манда выполняла негерметичные тесты, которые часто терпели неудачу. Через несколько дней члены команды заметили, что более 50 изменений приняты, невзирая на результаты тестирования. После перевода предварительной проверки в герметичный режим время на выполнение тестов сократилось в 14 раз и они стали завершаться практически без сбоев.
    Сбои по-прежнему были, но их было легко найти и откатить.
    После того как негерметичные тесты были перенесены на этап проверки после фиксации, сбои стали накапливаться там. Отладка сквозных тестов, терпящих неудачу, все еще оста- ется сложной задачей, и у некоторых команд нет времени даже попытаться их исправить, поэтому они просто отключают такие тесты. Это лучше, чем остановить разработку для всех, но может привести к сбоям в продакшене.
    Одна из текущих задач команды — продолжить настройку механизмов кеширования, чтобы предварительная проверка могла выявлять больше типов проблем, которые в прошлом обнаруживались только после фиксации, и не была излишне хрупкой.
    Другой вопрос — как выполнить предварительную проверку для децентрализованного
    Assistant, учитывая, что отдельные компоненты переносятся в свои микросервисы. По- скольку Assistant имеет большой и сложный стек, затраты на запуск герметичного стека на этапе предварительной проверки будут очень высокими.
    Наконец, команда воспользовалась преимуществами этой децентрализации в новой полити- ки изоляции ошибок на этапе проверки после фиксации. Для каждого из N микросервисов в Assistant команда запускала тестовую среду для проверки после фиксации, содержащую микросервис, собранный из главной ветви, вместе с продакшен- (или близкими к ним) версиям N – 1 микросервисов, чтобы изолировать проблемы, порождаемые новыми вер- сиями. Если считать упрощенно, стоимость такой конфигурации равна O(N
    2
    ), но команда использовала интересную возможность под названием hotswapping (горячая замена), чтобы сократить эту стоимость до O(N). Это позволило давать серверу команду «поменять места- ми» микросервисы для вызова. В результате требовалось запустить только N микросерви- сов, по одному экземпляру каждого, собранных из главной ветви, и можно было повторно использовать один и тот же набор служб, подключенных к каждому из этих N «сред».

    Непрерывная интеграция в Google
    1   ...   58   59   60   61   62   63   64   65   ...   69


    написать администратору сайта