Лежим красиво

October 28, 2016

Как я писал на днях, падения - не стыдно, это часть жизненного цикла любого программного продукта и сегодня хочу рассказать как продакшен падает.

Если у вас в системе есть ограниченный ресурс, то когда-нибудь он обязательно кончится. Коннекшенов будет мало, процесс убьет OOM killer, место на диске перестанет хватать, десятиминутный крон будет выполнятся полчаса и так далее. А да, сертификат вы продлить забудете, домен не оплатите, кредитку заблокируют. И хотя вроде Большой Бизнес (TM) не должен допускать таких банальных ошибок, давайте просто вспомним, что Гугл как-то на несколько минут потерял контроль над своим доменом. У Инстаграмма день был просрочен сертификат. Стек Оверфлоу вырубил умный балансер и тяжелый регексп. Там же не дураки работают? Конечно нет! Умнейшие люди! Просто когда нужно контролировать очень много параметров и процессов любая система начинает сбоить.

Под трафиком проявятся разнообразные гонки, конфликты, блокировки, какие только могут быть. Магия рейлс частенько дает сбой в нагруженных местах. Всякие constraint violation, dead locks станут обычным делом, как только нагрузка подрастет. Вообщем весело. Раскажу несколько случаев которые были у нас.

1) Бесконечный цикл. Был примерно такой же код, как в выпуске Securing an API только для генерации человеко-френдли номера класса. Естественно через пару лет метод стал сильно деградировать по перформансу, а потом и вообще отвалилься по таймауту.

before_create :generate_number
def generate_numer
  begin
    self.number = ...
  end while self.class.exists?(number: number)
end

2) Конфликт IP адресов. В Селектеле есть два вида внешних IP - Floating IP, который можно подцепить к произвольному интерфейсу, и публичная подсеть, IP из которой рекомендуют использовать для нагруженных проектов. Так вот, выдается подсеть /29, но использовать из нее можно только 5 адресов, так как первый - гейтвей. Ну у нас кто-то поставил зарезервированный IP на бокс и сайт стал очень прикольно деградировать. Он работал несколько минут, а потом переставал открываться. Все это было на фоне повышенной нагрузки и сначала мы думали, что сервера не справляются с трафиком.

3) Добавление колонок с дефалтовым значением в большую таблицу, создание индекса без CONCURRENTLY. Ну это вообще классика. Если вы не роняли продакшен тяжелой миграцией, то у вас впереди еще много интересного. Алексей Васильев написал прекрасную статью про эту тему Safe and unsafe operations for high volume PostgreSQL.

4) Мутация константных хэшей. Очень мерзкий баг. Где в инициализаторах в константу грузился yml-файл и кто-то ее случайно модифицировал в коде с помощью bang-методов (которые зло). Поэтому часть юникорнов начинала глючить. Вот здесь конечно я позавидовал языкам, в которых вшита защита от таких безобразий. К счастью дефект был наглый и очень быстро проявлялся, поэтому мы его исправили в тот же день.

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

comments powered by Disqus