Примечание переводчика: В нашем блоге мы много пишем о построении облачного сервиса 1cloud, но немало интересного можно почерпнуть и из опыта по работе с инфраструктурой других компаний. Инженер фотосервиса Imgur Джейкоб Гринлиф (Jacob Greenleaf) опубликовл в блоге на Medium материал, в котором изложил несколько советов по созданию высокодоступного кода для отказоустойчивых систем. Мы представляем вашему вниманию адаптированный перевод этой заметки.

Я работаю в Imgur уже больше двух лет и за это время усвоил несколько принципов, которые помогают создавать отказоустойчивые системы. Часто бывает, что какая-то из наших систем «падает», и когда я прихожу утром на работу, то вижу, что сработал заранее предусмотренный «предохранитель» или сервис автоматически перезапустился после сбоя — этого удается достичь с помощью нескольких принципов проектирования. Ниже представлены некоторые из них.

Все нужно ограничивать


Предположим, у вас есть очередь для обработки множества элементов. Но действительно ли она должна быть ничем не ограничена? Можно поставить лимит в 1 млн элементов (чем бы они ни были), и отбрасывать слишком старые или слишком новые элементы. При соединении с сервисом по сети, действительно ли нужно использовать бесконечную блокировку? Можно же добавить таймаут. Должны ли соединения к серверу жить вечно, или хватит и пяти минут, а потом их можно убить? Ну вы поняли суть.

У нас в Imgur есть задача cron, которая называется «убийцей длинных запросов» — она сканирует активные зарпосы в MySQL, которые выполняются от имени запросов пользователей, и проверяет, как долго они выполняются, убивая те, что превышают заданный порог. Учитывая тот факт, что в PHP таймаут (max_execution_time) равняется 30 секундам, то запросы не должны выполняться больше нескольких минут. Этот убийца запросов, вполне вероятно, спас нас от многих бессонных ночей. Если у вас такого нет, создайте. Потом сами же скажете себе спасибо.

Используйте повторный запуск, но ограниченное число раз


Джим Грей написал в книге Why Do Computers Stop and What Can Be Done About It («Почему компьютеры останавливаются, и что с этим можно сделать») такую фразу: «большинство сбоев промышленных систем являются мягкими. Если просто перезапустить не выполнившуюся задачу, то обычно во второй раз сбоя не будет». Бывают баги, которые всплывают лишь время от времени, поэтому повысить доступность систем можно с помощью добавления функции повторного запуска. Однако, тут нужно быть аккуратным, чтобы не устроить DDoS на свои системы собственными руками!

Следует последовать первому совету и использовать ограниченное количество попыток перезапуска и заставлять систему ждать все больше времени при каждой попытке повторного пуска. Это поможет распределить нагрузку.

Нужно использовать контрольные процессы


Для создания софта с высокими требованиями по части доступности часто используется Erlang. В нем есть паттерн контроля (supervisors): каждая задача, которую выполняет программа, структурирована таким образом, чтобы работать под надзором контролирующего процесса (супервизора). Если супервизор обнаруживает неожиданное завершение задачи, он ее перезапускает (как в предыдущем правиле) с известного безошибочного состояния. Нет никакого смысла перезапускать то, что все равно не будет работать. Хорошим средством автоматического перезапуска веб-сервера или процессов-демонов является Monit.

Важно добавлять проверки здоровья и использовать их для перераспределения запросов


Разработчик должен думать о том, как свести всю кучу переменных в коде системе к простому булевому вопросу «здорова ли эта вещь? Работает ли она?» В Imgur используется встроенный в ELB мониторинг здоровья, который проверяет, живы ли сетевые узлы, и автоматически перераспределяет запросы к ним в случае падения.

Избыточность не просто «хорошо бы иметь», она обязательно должна быть


Если вы используете облачные сервисы, то может случиться так, что запущенные инстансы будут время от времени умирать. Так что избыточность в таком случае не просто что-то, что хорошо бы иметь, но требования для создания отказоустойчивых систем.



Как-то раз в Imgur пришло уведомление о выключении виртуальных машин в облаке Amazon. Обычно такие алерты приходят заранее, но в тот раз это случилось уже после удаления виртуалок (и после того, как PagerDuty и Nagios предупредили о наличии проблем).

Лучше проверенные временем средства, чем горячие новинки


Противостоять искушению попробовать в деле новые популярные инструменты довольно сложно. К прмиеру, DevOps-сообщество сходит с ума по CoreOS и легким контейнерам «в стиле LXC». Однако когда Джейкоб Гринлиф попробовал с ним работать, выяснилось, что в компоненте ядра (FleetD) содержался баг, затрагивавший работу с планировщиком, который мог повлечь остановку работы системы. Гринлиф смог разобраться с проблемой после многих часов отладки, завершившейся в два часа утра. Новые технологии часто могут содержать никому еще неизвестные ошибки и причины для сбоя.

Кроме того, у более новых проектов есть общая черта — часто они слишком сырые для работы в продакшене. Например, у Golang нет официального отладчика, а альтернативный открытый отладчик появился всего несколько месяцев назад. Также инструменты мониторинга и трассировки языка Go ни в какое сравнение не идут с Java JMX и Erlang.

Комментарии (12)


  1. atomlib
    03.10.2015 16:26
    +5

    1. kloppspb
      04.10.2015 12:25
      -1

      btw, в первом же комменте речь идёт о гигабайтах. Мне доводилось иметь дела с сотнями мегабайт на диске, и единицами мегабайт памяти на той же 3.12. Не 93 год, но ещё прошлый век.

      Вот что действительно дрессирует, и знаний добавляет нехило…


  1. Olej
    04.10.2015 12:21
    -3

    > Например, у Golang нет официального отладчика, а альтернативный открытый отладчик появился всего несколько месяцев назад. Также инструменты мониторинга и трассировки языка Go ни в какое сравнение не идут с Java JMX и Erlang.

    Смешной афтор… ;-):
    … ну сырой тебе Go — не пользуйся.
    Пользуйся: BASIC, COBOL… проверено годами!


  1. Olej
    04.10.2015 12:24

    > Инженер фотосервиса Imgur Джейкоб Гринлиф

    В принципе, чтобы почерпнуть знания об отказоустойчивых системах, нужно бы читать не мнения сотрудников облачных сервисов, а пойти и почитать, скажем, публикации из операционной системы QNX…


  1. miga
    04.10.2015 13:36
    +4

    Мда. Я вотчдогов, кронов, которые убивают длинные запросы в базу и прочих костылей стыдился… А оказывается, надо было гордиться надо было.


    1. dbf
      04.10.2015 14:56

      А чего стыдиться? Записал в лог для последующего разбора ситуации и грохнул, чтобы система не повисла и тебе звонить не начали. Потом проблему исправил спокойно днем.


    1. stavinsky
      04.10.2015 16:48

      А еще надо понаставить вотчдогов которые следят за вотчдогами)


      1. khim
        04.10.2015 21:46

        Всё зависит от масштабов. Если у вас система на миллионы компьютеров и соответствующее количество ресурсов и админов, то там и вотчдоги которые следят за вотчдогами которые следят за вотчдогами могут быть.


    1. PsychodelEKS
      04.10.2015 17:07
      +2

      Стыдиться надо, когда у Вас что-то не работает, а Вы узнаете об этом от пользователей. Лучше перебдеть, чем недобдеть.


  1. Stas911
    06.10.2015 16:12

    Мне еще понравилось — в Амазоне(?) вся инфраструктура построена на сервисах и чтобы убедиться, что все сделано отказоустойчиво и надежно, специальный сервис Crazy Monkey в рабочее время ходит по машинам и случайным образом изредка гасит одну из них :))


  1. catanfa
    09.10.2015 15:06

    По-моему специальный демон убийца медленных SQL запросов это всё-таки вредный совет. Если уничтожить «долгий» запрос, то та задача, которую выполнял скрипт, выполнена не будет. Страница не покажется, скрипт не сделает свою работу и т.д. Это скорее закапывание проблемы глубже, а не отказоустойчивость. По крайней мере, нужно куда-то логировать такие запросы и пытаться избежать их появления в будущем.


    1. stavinsky
      10.10.2015 00:45

      В слоу лог вообще полезно заглядывать. Благо в 5.6 это можно прямо из бд смотреть