Майкл Т. Нигард, 2007, ISBN: 978-0-9787-3921-8
Мой дайджест и обзор книги.
Рассмотрение
Из книг, которые я прочитал, выпусти это! это то, что мне нужно прочитать всем «старшим» разработчикам (вместе с чем-то вроде « Архитектурные решения для предприятий: шаблоны для высокопроизводительных интернет-систем» ). Особенно первую часть о стабильности с ее шаблонами и анти-шаблонами необходимо прочитать. Не зная и не применяя их, мы создаем системы, которые реагируют на такие проблемы, как сухая саванна или горящая спичка. Рядом с предыдущей главой я также обнаружил, что очень ценно прозрачность № 17, особенно метрики и дизайн OpsDB и практики наблюдения.
Одна вещь, которую я оставил вне дайджеста, которую действительно стоит прочитать, это военные истории, которые представляют каждый раздел, они действительно интересные, вдохновляющие и познавательные.
Дополнительные ссылки
- Выпусти это! слайды: http://gotocon.com/dl/jaoo-sydney-2009/slides/MichaelT.Nygard_FailureComesInFlavoursPart2.pdf
- https://github.com/Netflix/Hystrix/
- Команда зависимости Netflix рассказывает об использовании автоматических выключателей и ограничении пула потоков http://techblog.netflix.com/2012/02/fault-tolerance-in-high-volume.html
- Руководство по MSDN для облачных приложений: шаблоны проектирования — автоматический выключатель и многие другие очень полезные шаблоны
стабильность
Стабильность х долголетия ошибок
Стабильность антипаттернов
Точки интеграции
Точка интеграции = вызов БД, WS,…. Риск стабильности № 1.
- Каждый в конечном итоге потерпит неудачу
- Много возможных ошибок: сеть, приложение,…
- Симптомы: нарушение протокола, медленный ответ, зависание, внезапно закрытые соединения,…
- Будьте осторожны, чтобы избежать каскадных сбоев, когда в удаленной системе возникают проблемы — автоматический выключатель, тайм-ауты, разъединение промежуточного программного обеспечения, рукопожатие; используйте Test Harness для тестирования
- Пример: в соединениях отказано (поймать: может потребоваться много времени, чтобы выяснить, что вы не можете подключиться, например, когда он прослушивает, но не может обработать запросы или когда ACK не приходят и он продолжает повторять попытки); брандмауэр может выбросить старое соединение, никому не сказав, молча отбрасывая пакеты
Цепные реакции
Приложение с балансировкой нагрузки с дефектом (обычно утечка ресурсов или сбой, связанный с нагрузкой). Если дефект вызван в одном случае, и он терпит неудачу, остальные, более вероятно, потерпят неудачу (увеличенная нагрузка,…). Перегородки могут помочь, разделив узлы на отдельные наборы с отдельными, более мелкими цепными реакциями, которые, вероятно, происходят в разное время Может привести к каскадному сбою в вызывающем слое.
- Один сервер не работает, остальные
- Охота на утечки ресурсов
- Охотьтесь за неясными ошибками времени — трафик может вызвать неясные условия гонки; если тупик убивает сервер, то повышенная нагрузка на оставшиеся, скорее всего, также вызовет его
- Защищайтесь с помощью перегородок, используйте автоматический выключатель на стороне вызывающего
Каскадные сбои
= проблемы в одном слое вызывают проблемы у абонентов — часто из-за истощенных пулов ресурсов
- Будьте параноиком по поводу точек интеграции
- CF часто возникает из пула ресурсов, который истощается, когда потоки извлекают ресурс и блокируются, потому что их вызов никогда не возвращается, и другие потоки ожидают ресурс. Безопасный пул ресурсов должен всегда ограничивать время, в течение которого поток может ожидать извлечения ресурса.
- Автоматический выключатель защищает вашу систему, предотвращая вызовы в проблемную точку интеграции, а тайм-ауты гарантируют, что вы сможете вернуться от вызова к проблемному.
пользователей
- Пользователи используют память => минимизируют размер сеанса, используют сеанс только для кэширования, чтобы вы могли очистить его содержимое, если объем памяти будет ограничен (и заново создавать при необходимости). F.ex. в Java используйте SoftReferences. Остерегайтесь того, что сеанс длится до последнего взаимодействия + время ожидания, которое по умолчанию составляет 30 минут (умножьте это на слишком много пользователей…)
- Пользователи делают странные, случайные вещи, не ожидайте, что они будут вести себя так, как вы ожидаете; если будет слабое место, они его найдут
- Вредные пользователи всегда в курсе последних событий, предотвращают внедрение SQL и т. Д.
- Иногда пользователи приходят в действительно, очень большие мобы => зависания, тупики, непонятные условия гонки; запустить специальные стресс-тесты, чтобы забить глубокие ссылки или горячие URL
- Остерегайтесь искусственных пользователей, таких как боты и индексирующие пауки — они делают много запросов в одно мгновение, могут игнорировать куки (=> каждый из них приводит к новому сеансу)
Заблокированные темы
- f.ex. При извлечении ресурсов из пула соединений, работе с кешами или реестрами объектов, совершении вызовов во внешние системы или синхронизации потоков
- Шаблон заблокированных потоков является непосредственной причиной большинства сбоев; привести к цепным реакциям и каскадным сбоям
- Исследовать пулы ресурсов — потоки часто блокируются на них; f.ex. тупик в БД или неправильная обработка исключений (и, следовательно, сбой соединения)
- Используйте проверенные примитивы для параллелизма вместо создания своих собственных (см.
java.util.concurrent
) - Защищайтесь с помощью таймаутов, чтобы тупик не длился вечно — всегда используйте их
- Остерегайтесь кода, который вы не видите — например, в библиотеках
Атаки самоотречения
Пример: электронное письмо от маркетинга выбранной группе пользователей со специальным предложением, которым они будут делиться дальше, и внезапно страница будет заполнена пользователями. Все серверы, ожидающие получения блокировки для обновления одного и того же популярного элемента (=> предпочитают архитектуру без общего доступа или, по крайней мере, применяют разделительное промежуточное ПО или делают сам разделяемый ресурс горизонтально масштабируемым с помощью избыточности и протокола синхронизации).
- Будьте в курсе — убедитесь, что если есть маркетинговая кампания, вы об этом знаете. Убедитесь, что он не использует глубокие ссылки (в обход вашего кеширующего прокси), следите за нашими встроенными идентификаторами сеансов в URL. Создайте статические страницы «посадочной зоны» для первого клика из этих предложений.
- Защита общих ресурсов в случае скачков трафика. Не упустите повышенную нагрузку на интерфейс, вызывающую экспоненциально увеличивающуюся обработку.
- Ожидайте быстрое перераспределение (то есть широкое и широкое распространение) любого интересного или ценного предложения — такого понятия, как распространение среди ограниченного набора пользователей, не существует.
Масштабирующие эффекты
То, что работало в небольших масштабах, приводит к проблемам при масштабировании системы. Всякий раз, когда у нас есть отношения «многие к одному» или «многие к немногим», мы можем столкнуться с проблемами, когда увеличивается сторона «больше», например сбой БД при переходе от 2 БД AS — 1 к 10 БД AS — 1. Распространенной проблемой является двухточечное общение.
- Изучите различия в масштабах между производственной средой и средой контроля качества, чтобы определить эффекты масштабирования — шаблоны, которые отлично работают в небольших средах или в средах «один на один», могут замедляться или полностью отказывать при переходе к рабочим размерам
- Следите за двухточечным общением — оно плохо масштабируется, так как число соединений увеличивается по мере увеличения площади участников
- Не упустите общие ресурсы — они могут быть узким местом, ограничением емкости и угрозой стабильности. Если у вас есть, стресс-тест это сильно. Удостоверьтесь, что его клиенты продолжат работать, если это замедляется или блокируется.
Несбалансированные возможности
UC — это особый случай Scaling Effects: одна сторона отношения масштабируется намного больше, чем другая сторона. Пример: многие веб-серверы, которые обычно обслуживают в основном статический контент и только несколько динамических страниц, предоставляемых внутренними серверами; если структура трафика (рабочая нагрузка) внезапно изменится, т. е. многие пользователи переходят к динамическим функциональным возможностям, внешние серверы затопят несколько внутренних. Возможно, было бы нецелесообразно сопоставлять их возможности для редких всплесков, поэтому создайте их обоих, чтобы они были устойчивыми перед лицом цунами запросов. Для внешнего интерфейса автоматический выключатель поможет сбросить давление на внутреннем конце, когда отклики замедляются или в соединениях отказывают. Для серверной части используйте Handshaking, чтобы сообщить клиенту о необходимости дросселировать запросы. Также рассмотрите возможность перегородки зарезервировать емкость на сервере для других типов транзакций.
- Изучите, сравните количество серверов и потоков, особенно в Prod vs. QA
- Наблюдайте за близкими эффектами масштабирования и пользователями
- Подчеркните обе стороны интерфейса; если вы бьете серверную часть с 10 * большим количеством запросов, чем в историческом максимуме, для самой дорогой транзакции, произойдет ли сбой или замедлится и в конечном итоге восстановится? Что делает интерфейс, когда сервер перестает отвечать или становится очень медленным?
Медленные ответы
Генерация медленного ответа хуже, чем отказ в соединении или возврате и ошибке, поскольку это связывает ресурсы как в вызывающей, так и в вызываемой. Они обычно являются результатом чрезмерного спроса или из-за основной проблемы, например утечки памяти и возникающая в результате сборка мусора, перегрузка сети.
- Медленные отклики запускают каскадные сбои, восходящая система слишком замедляется и становится уязвимой для проблем стабильности
- Для веб-сайтов медленные ответы вызывают больше трафика, так как пользователи нажимают «перезагрузить»
- Рассмотрим Fail Fast — например, если ваш SLA требует ответа в 100 мс, а скользящее среднее за последние 20 вызовов превышает его, вы можете начать отклонять запросы (для этого должна быть подготовлена вышестоящая система)
- Охота на утечки памяти или нехватку ресурсов (например, слишком мало соединений с БД)
SLA Inversion
Инверсия SLA = система, которая должна соответствовать SLA высокой доступности, зависит от систем более низкой доступности. Но лучший SLA, который вы можете предоставить, — это ваша зависимость от худшего SLA.
Решение: 1) Отсоедините от систем более низкого SLA, чтобы ваше приложение могло продолжать работать без них, изящно ухудшаться. Развязка промежуточного программного обеспечения отлично подходит для этого. По крайней мере, используйте автоматические выключатели для защиты от ваших зависимостей. 2) Определить реалистичный SLA и вместо всей системы сосредоточиться на доступности определенных функций / функций с их зависимостями.
Пример: разрешить клиентам продолжать покупки, даже если расписание доставки недоступно.
- Для каждой службы ваша система зависит от доступности транспортного уровня, служб имен (DNS) и протоколов уровня приложений, и любой из них может дать сбой.
- Если построено наивно, вероятность отказа вашей системы является общей вероятностью отказа в любом компоненте или услуге, поэтому P (вверх) = (1 — P (внутренний отказ)) * P (зависимость 1 вверх) *… * P ( Зависимость N вверх). Таким образом, для пяти зависимостей с доступностью 99,9% мы можем получить не более 99,5%.
Неограниченные наборы результатов
«Дизайн со скептицизмом, и вы достигнете. Спросите: «Что может сделать система X, чтобы причинить мне боль?» а затем придумайте способ уклоняться, нырять, опускаться, нырять и уклоняться от любого рывка, который выкинет ваш предполагаемый союзник. p95 Одной из этих систем является ваша БД — что если она вдруг возвращает 5M строк вместо обычных сотен?
- Используйте реалистичные объемы данных в тестировании / dev
- Не полагайтесь на производителей данных для создания ограниченного объема данных
- Установите ограничения для других протоколов уровня приложений: вызовы WS, RMI, XML-RPC и т. Д. — все они уязвимы для возврата огромных коллекций объектов, что потребляет слишком много памяти (и продолжает работать еще долго после того, как пользователь потерял интерес)
- Неограниченные наборы результатов являются частой причиной медленных ответов; они могут возникнуть в результате нарушения устойчивого состояния
Шаблоны стабильности
Использовать тайм-ауты
Редко хочется ждать вечно (или много минут).
- Применить к точкам интеграции, заблокированным потокам и медленным ответам; они препятствуют тому, чтобы вызовы I.Points становились заблокированными T. и таким образом предотвращали Cascading Failure.
- Совместите с автоматическим выключателем (срабатывает при слишком большом количестве) и Fail Fast (чтобы сообщить вызывающим абонентам, что вы не можете обрабатывать запросы).
- Подайте заявку на восстановление после неожиданных сбоев — когда операция занимает слишком много времени, нам иногда все равно, почему, нам просто нужно сдаться и продолжать двигаться
- Рассмотрим отложенные повторные попытки — проблемы с сетью или удаленной системой, вызывающие их, не будут решены сразу, поэтому немедленные повторные попытки только усугубляют ситуацию и заставляют пользователя еще дольше ждать неизбежного ответа на сбой.
Пример HttpClient: RequestConfig.custom()
.setConnectionRequestTimeout(1000).setConnectTimeout(1000).setSocketTimeout(1000).build();
Выключатель
Автоматический выключатель оборачивает точку интеграции и работает как плавкий предохранитель, «таяя» (размыкая), когда несколько вызовов к системе терпят неудачу или время ожидания подряд, таким образом, делая последующий запрос быстрым, не потребляя слишком много ресурсов и облегчая загрузку удаленные системы. Иногда он пропускает вызов, чтобы проверить, не стала ли система снова реагировать.
Он отлично работает с постепенной деградацией, то есть предлагает ограниченную, но все же полезную функциональность пользователям, когда подсистема становится недоступной.
- Не делайте этого, если это больно — CB является фундаментальной схемой защиты вашей системы от всевозможных проблем точек интеграции. Когда с ними возникнут трудности, перестаньте их называть!
- Используйте вместе с таймаутами
- Выставлять, отслеживать и сообщать об изменениях своего состояния в Ops
Страница шаблона автоматического выключателя MSDN довольно хороша. Представление Мартина Фаулера Circuit Breaker с простым примером реализации на Ruby и полезными ссылками.
Impl. в Java с Spring AOP и JMX: https://code.google.com/p/jianwikis/wiki/CircuitBreakerDesignPattern , реализация Clojure .
Перегородки
Переборки — это водонепроницаемые отсеки на корабле; когда есть дыра, вода заливает только один отсек, спасая корабль от затопления. Точно так же вы можете разделить свои ресурсы (серверы и т. Д.) И назначить разделы определенным клиентам / функциям, чтобы сбой не влиял на все и / или более важные функции / клиенты были защищены от сбоев, вызванных менее важными. Физическая избыточность является наиболее распространенной формой защиты от сбоев оборудования. Небольшой пример — привязка процесса только к подмножеству процессоров. Внутри процесса вы можете создать отдельные группы потоков, предназначенные для различных функций — например, отдельный пул потоков обработки запросов для административных функций. Пример: сбой в статусе статуса рейса не помешает регистрации.
- Возможность перегородок шаблона Bulkheads для сохранения частичной функциональности при возникновении плохих вещей
- Разделение приводит к менее эффективному использованию емкости (но виртуализация может уменьшить это до некоторой степени — перемещать виртуальные машины между разделами по требованию)
- Выберите полезную гранулярность — пулы потоков внутри приложения, процессоры на сервере или серверы в кластере
- Очень важно с моделью общих служб, когда в вашем приложении зависит множество систем; Вы не хотите разрушать их, когда происходят цепные реакции
Устойчивое состояние
Для каждого механизма, который накапливает ресурс (данные в БД, файлы журналов, память, используемая кешем), некоторый другой механизм должен перерабатывать этот ресурс.
- Избегайте возни — ручное вмешательство человека ведет к проблемам; Устранить необходимость повторного вмешательства человека (очистка диска, ночные перезапуски) через автоматизацию
- Очистка данных с помощью логики приложения — приложение знает лучше, чем администратор базы данных, как очистить старые данные при сохранении согласованности и здравомыслия (например, в ORM)
- Ограничьте объем памяти, который может использовать кеш, чтобы он не вызывал проблем
- Сверните журналы — не храните неограниченное количество файлов журнала, настройте ротацию файлов журнала в зависимости от размера
Fail Fast
Если система может заранее определить, что она потерпит неудачу в операции, лучше быстро потерпеть неудачу.
- Избегайте медленных ответов и быстрого отказа — если ваша система не может выполнить свой SLA, сообщите об этом вызывающим абонентам быстро, не дожидаясь ошибки или тайм-аута (<> Автоматический выключатель)
- Резервируйте ресурсы, проверяйте точки интеграции заранее — например, сразу же выйдите из строя, если открыт критический CircuitBreaker
- Использовать для проверки ввода — выполнить базовую проверку ввода пользователя даже до того, как вы зарезервируете ресурсы, чтобы не тратить их впустую, если f.ex. отсутствует обязательный атрибут
- Пример: отказаться от подключения сразу, если в системе уже слишком много пользователей (=> регулирование до управляемого уровня, чтобы мы поддерживали разумный уровень обслуживания для пользователей, которые уже там)
Подтверждение связи
- сигнализация между устройствами, которые регулируют связь между ними; он защищает сервер, позволяя ему регулировать свою рабочую нагрузку. К сожалению, HTTP и RMI не хорошо рукопожатие.
- Создайте совместный контроль спроса — используйте клиент-серверное подтверждение связи для регулирования спроса до уровня обслуживания; оба должны быть построены, чтобы поддержать это
- Рассматривайте проверки работоспособности как обходной путь на уровне приложения при отсутствии H. Используйте, когда стоимость дополнительного вызова намного меньше, чем стоимость вызова и сбоя
- Встраивайте H. в свои собственные низкоуровневые протоколы
Test Harness
Испытательный комплект имитирует удаленную систему точки интеграции и может имитировать множество ошибок (сеть, протокол, уровень приложения) для проверки большинства / всех режимов отказа. «Хороший тестовый комплект должен быть хитрым. Это должно быть так же неприятно и злобно, как в реальной системе ». [126] «Испытательный жгут должен вести себя как маленький хакер, пробующий все виды плохого поведения, чтобы сломать абонентов». [128]
- В соединении сокета может быть отказано, сидеть в очереди прослушивания до истечения времени ожидания вызывающего абонента, удаленный конец мой ответ с SYN / ACK, а затем никогда не отправлять какие-либо данные, он может отправлять только пакеты RESET, он может сообщить о полном окне приема и никогда не истощать данные, соединение может быть установлено, но удаленный конец никогда не отправляет байт данных, соединение может быть установлено, но потеря пакетов вызывает задержку повторной передачи, conn.est. но удаленный никогда не ACK, получающий пакет, вызывая бесконечные повторные передачи, служба может принять запрос, отправить заголовки ответа (предполагая HTTP) и никогда не отправлять тело ответа; srv может отправлять 1 байт ответа каждые 30 секунд; он может отправлять HTML вместо ожидаемого XML; он может отправлять МБ, когда ожидается кБ данных; он может отказаться от всего аутентификации. полномочия.
- Эмулировать некондиционные сбои
- Стресс-тест вызывающей стороны — медленные / нет / мусорные ответы, ..
Decoupling Middleware
A well-done middleware integrates (by passing data and events) and decouples (by hiding specific knowledge, calls to other systems) systems.
Scale:
Same host, time, process
- In-process method calls
- Interprocess communication (shared mem, pipes, semaphores, ..)
- RPC (RMI, HTTP, ..) // same time, diff. host and process
- Message Oriented Middleware (MQ, SMTP, SMS, ..)
- Tuple Spaces (Java/Giga/T Spaces)
Different time, host, process
- Decide at the last responsible moment; this is an architecture decision that is expensive to change
- Avoid many failure modes though total decoupling (of servers, layers, applications)
- Learn many architectures, and choose among them
Quiz – what is wrong here:
try { ... }
finally {
if (stmt != null) stmt.close();
if (conn != null) conn.close();
}
- stmt may rarely throw an exception and the conn will thus never be closed, leading to connection pool exhaustion
Capacity
User sessions are the Achilles heel – they consume memory, and, if replication enabled, CPU and bandwidth.
Load testing: real world isn’t polite to the site. Search engine spiders may ignore cookies create a new session on each request (while generating many requests). Scrapers and shopbots do the same.
=> don’t test the system just the way it is meant to be used
Useful tools
- If every request creates a session, verify the client handles cookies properly and send those who don’t to a “how to enable cookies” page
- Capability to cap the number of requests to the system so that we can keep sessions below the crash limit
- Detect and block IPs, subnets etc. that create evil traffic
Capacity
- Performance: how fast the sys processes a single transaction
- Throughput: # tx / a time span
- Scalability: 1) throughput as f(load); 2) how the systems can be scaled up by adding capacity
- Capacity: the max throughput the sys can sustain, for a given workload, while maintaining an acceptable response time for each individual tx (the workload may change radically e.g. when users are interested in different services during a particular season)
- Constraint: There is always one (current) constraint <> theory of constraints
Capacity myths: CPU, bandwidth, and storage are cheap.
Capacity antipatterns
9.1 Resource Pool Contention
“Used well, [DB] connection pools, like all resource pools, can improve capacity by improving throughput. Left untended, however, resource pools can quickly become the biggest bottleneck in an application.” [167] – when there is contention for the resource , i.e. less than needed available; the requesting thread is then blocked indefinitely. Also, each connection – even whine idle – consumes resources on the remote system.
- Eliminate Contention under normal load
- If possible, size resource pools to the request thread pool
- Prevent vicious cycles: contention => tx take longer => more contention
- Watch for the Blocked Threads pattern (capacity => stability issues)
Excessive JSP fragments
AJAX Overkill
Ajax = many more requests coming from the browser to the server, more rapidly. The req and resp will typically be smaller. Used poorly, it will place more burden on the web an app servers.
Session thrashing – ensure session affinity so AJAX req go to the server having the user’s session. Make sure you don’t create a new session for each req.
Overstaying Sessions
How long a session stays in mem after the last req (as we have now way of knowing the user went away for good) – defaul(ed) to 30min in Java. Look at your data to determine session timeout: e.g. avg + 1 std dev. In practice it will be ~ 10 min for a retail site, 5 min for a media gateway, up to 25 for travel-industry sites. Even better is to make sessions unnecessary. F.ex. in-mem copy of persistent data may be dropped and recreated at any time (keep keys, not whole objects).
Wasted space in HTML
Every byte consumes bandwidth, memory, processing resources on different networking equipment and the servers. Omit needless characters, remove whitespace, replace HTML tables with CSS layout.
The Reload button
If the site is slow, users may start hitting Reload in hope of getting a presumabely stuck response, thus increasing the load even more. (The app server doesn’t know it should stop processing the previous one.) Make your site fast so that users never think of doing this.
Handcrafted SQL
ORM => predictable, repetitive SQL. Predictable access patterns of SQL are good for capacity, b/c a competent DBA can tune the DB for them. OO developers suck at relational queries and create expensive queries inconsistent with the tuning for the rest of the app.
Common problems: joins on non-indexed columns, joining too many tables, .. .
=> minimize, check with a DBA, verify gains against real data.
DB Eutrophication
- slow buildup of sludge that eventually kills it
- Create indexes
- Purge sludge = old data (mv from prod servers elsewhere, …)
- Keep reports out of Prod
Integration Point Latency
Calling a remote point takes time + its processing time, don’t ignore that. A performance issue at first may become capacity issue of the whole system. Avoid chatty remote protocols.
Cookie Monsters
=> keep cookies small; they’re sent with every request.
Capacity Patterns
Pool Connections
Use & remember to protect callers from blocking forever. Size them for max throughput.
Use Caching Carefully
Limit cache sizes. Build a flush mechanism. Don’t cache trivila objects. Compare access and change frequency.
Precompute content
Not everything needs to be dynamic and even not all the dynamic stuff changes equally often.
Tune the garbage collector
“In Java applications, garbage collection tuning is the quickest, and easiest way to see some capacity improvements. An untuned application running at production volumes and traffic will probably spend 10% of its time collecting garbage. That should be reduced to 2% or less.” [205] (Remember this was written in 2007.)
PART IV General Design Issues
11. Networking
Topics: Multihomed servers, getting routing right, virtual IP addresses.
12. Security
Topics: The Principle of Least Privilege (separate user/app, …), Configured Passwords (separately in encrypted files, …).
13. Availability
Gathering and documenting requirements (refer to these whenever responsible for defining availability!), load balancing, reverse proxying, clustering .
14. Administration
Does QA match production?
Keeps app separated if sep. in prod to prevent hidden dependencies. Zero, One, Many – if having many nodes in prod, have 2 in QA. Just buy the gear: “I’ve seen hours of downtime result from presence of firewalls or load balancers in production that did not exist in QA.” [238]
14.s Start-up and Shutdown
Build a clear start-up sequence into the app so that everything starts in the right order and must complete before requests are served. Init. at least some conn for each conn. pool (Fail Fast).
Clean shutdown: have a mode where existing tx are completed (remember a timeout) but new request not accepted.
CLI interfaces for administration are best (<> scripting) x GUIs.
PART IV Operations
17 Transparency
= qualities allowing personnel to gain insight into the system’s historical trends, present conditions, instantaneous state, and future projections.
Perspectives
- Historical Trending – system and biz level metrics in the OpsDB => trends
- Predicting the future (how many users can we handle, ..)
- Present status – the state of each app and HW – mem, garbage coll. (frequency ,..), threads for each pool, DB conn pools, traffic stats for each request channel, biz tx for each type, users (demographics, #, usage patterns, errors encountered, …), Integration points, circuit breakers
- instantaneous behavior a.k.a. what the *** is going on? <> monitoring systems, thread dumps, stack traces, errors in log files, …
Designing for Transparency
Start early. You need visibility into the whole system to avoid local optimization.
Enabling Technologies
Logging
- Configurable location (=> a different drive)
- Levels: only log as error/sever what requires attention from Ops; not every exception is an error
- Catalog of messages (asked for by ops) – use the internationalization tool in your IDE to produce it easily; include keys for easy lookup – e.g. the created i8n keys => unique, easy to lookup
- Human factor: convey clear, accurate, actionable information so that humans under stress can interpret it correctly; make it readable for humans and their pattern-matching ability
- Include ID of the transaction to track it across components
Monitoring systems
Standards
- SNMP – widely supported, old; supporting a custom SW is laborious
- CIM (1996, successor to SNMP) – more dynamic, superior; not too widespread
- JMX – great for JVM-based apps
What to expose
- Traffic indicators: page requests [total], tx counts, concurrent sessions
- Resource pool health: enabled state, total resources, r. checked out, high-water mark, # r. created/destroyed, # times checked out, # threads blocked waiting for r., # times a thread has blocked
- DB connection health: # SQL exceptions, # queries, avg response time to q.
- Integration point health: state of circuit breaker, # timeouts, # requests, avg response time, # good responses, # network/protocol/app errors, IP address of the remote endpoint, current # concurrent requests, concurrent req. high-water mark
- Cache health: items in c., memory used by c., cache hit rate, items flushed by garbage collector, configured upper limit, time spent creating items
Operations Database (OpsDB)
Logging & monitoring expose the immediate behavior/status but unsuitable for the historical/future perspective => accumulate status, metrics in a (ops) DB.
OpsDB high-level structure
*|-|*
/-1-Node-*-(needs)*-Feature
*|
Observation-*-1-Observation Type
|
- one of Measurement, Event, Status
Feature – a unit of biz-significant functionality (related to avail SLAs); typically implemented across multiple hosts (web, app, DB, ..), network equipment such as FW, switch etc. – Node represents any of these active nodes (typically it suffices to represent hosts and apps). Optionally track what nodes use other nodes.- Observations: Measurements are mostly periodic performance stats; Statuses are state transitions (c.breaker on/off, …).ObservationType defines the name and concrete subtype of the Obs.
Eventually we add:
/-1-ObservationType
1|
Expectation-*-1-ExpectationType
|
- one of NominalRange, ExpectedTime, ExpectedStatus
Expectation = an allowed range for a metric, a time frame in which an event must [not] occur, an allowed status; violation => alert. Set based on historical data. (Beware false positives = crying the wolf!). Eventually the expectation values may become functions of the business rhythm (day/night, special seasons, …)
Supporting processes
Build an effective feedback process, i.e. only share meaningful data that is act on responsively . See Plan-Do-Check-Act, Boyd’s OODA etc.
Keys to Observation
Watch for both trends and outliers. Include continuous improvement.
- Every week, review the past w. problems, look for recurring ones and most time consuming ones, for particular troublesome subsystems/3rd party/integr.point.
- Every month, look at the total volume of problems, consider the distribution of pr. types. The trends should be decrease in severity and volume.
- Daily or weekly look for exceptions, stack traces in logs => find most common sources, consider whether they indicate serious problems or gaps in error handling.
- Review help desk calls for common issues => UI improvements, more robustness
- If there are too many problems to review, look for top categories and sample them randomly
- Every 4-6 months, recheck that old correlations still hold true
- At least monthly look at data volumes and query stats
- Check the DB for the most expensive queries; have their q. plans changed? Is there a new €€€ query? <=> accumulation of data somewhere. Check for table scans => missing indices.
- Look at the daily and weekly envelope of demand and sys metrics; are traffic patterns changing? if a popular time is dropping in popularity, the sys is probably too slow at those times; if there is a plateau then perhaps there is a limiting factor, e.g. responsiveness of the system.
The emphasis shifts from reactive to predictive. Old metrics/reports loose value.
For each metric being reviewed: How does it compare to the historical norms? If the trend continues, what happens to the correlated metric (# users x responsiveness); how long can it continue before hitting a limiting factor and what will happen then? => interpretation & decisions
18. Adaptation
Topics: Adaptatable SW design, dependency injection, object design, XP coding practices, agile DBs, adaptable enterprise architecture, dependencies within a system, d. between systems: protocols/DBs, releases shouldn’t hurt (0 downtime deployments, …)