Страх и ненависть в отдельно взятом стартапе. Часть 1 — Cтрах

    Пришло время описать архитектуру и особенности эксплуатации одного приложения. И для себя, чтоб не забыть, и для других — попробовать показать, как делать не нужно. Все совпадения случайны, все персонажи выдуманы. Реальны только используемые технологии и описаные, гхм, архитектурные решения. Поехали.

    У нас было 2 балансировщика, 7 серверов для приложения, 5 самописных gem’ов, самописный конфиг ядра и целое множество языков программирования и технологий всех сортов и расцветок, база данных, а также списки todo в Basecamp, NodeJS, soсket.io и 2 дюжины ключей на одну сущность в Redis. Не то чтобы это был необходимый запас для стартапа, но если начал писать код, становится трудно остановиться. Единственное, что вызывало у меня опасение — это ZeroMQ. Ничто в мире не бывает более беспомощным, безответственным и порочным, чем самописная шина сообщений на основе ZeroMQ. Я знал, что рано или поздно мы перейдем и на эту дрянь.

    А начиналось всё невинно: проект на Ruby on Rails, архитектура микро-сервисов, отдельный балансировщик с “горячим” бэкапом… Только потом я узнал, что: сервера работают на Gentoo; микросервисы используют хитрый алгоритм регистрации себя в приложении, что приводит к взрыву всего приложения если падает хотя бы один сервис; мониторинга нет; документации нет; населена роботами. Но достаточно лирики, давайте посмотрим как жил проект, когда в него пришёл я.

    На сегодняшний день 90% написаного ниже неактуально — так это выглядело примерно два года назад. Повествование, однако, ведётся в настоящем времени — мне так удобнее.

    Как я уже сказал, имеется Rails-приложение, и некоторое количество сервисов на бэкэнде. Обмен сообщениями между Rails-приложением и сервисами осуществляется через самописную шину сообщений. Рядом крутится Redis, в котором хранится срез текущего состояния сущностей, приложение на NodeJS + socket.io (обмен сообщениями между фронтэндом и бекендом). Упрощённо это выглядит примерно так:

    Архитектура приложения

    Приложение оперирует некими сущностями, которые хранятся в базе “Rails db”. Сервисы оперируют теми же самыми сущностями, что и основное приложение, но имеют каждый свою отдельную базу. Синхронизация сущностей происходит через сообщения в ZeroMQ по сообытиям, которое генерирует основное приложение. Каждый сервис состоит из собственно самого сервиса, и набора event listener’ов (отдельные процессы по сути), которые принимают сообщения (каждый listener обрабатывает сообщения одного типа), и сообщают сервису что нужно сделать (какие поля в базе нужно поменять). Процесс самого сервиса тоже принимает определённый тип сообщений, по которым отдаёт в основное приложение данные из своей базы. И сервисы, и основное приложение активно работают с Redis (читают и пишут); синхронизации/локинга нет (т.е. возможны гонки, и они есть). Это что касается архитектуры приложения. Теперь пройдёмся кратко по серверам, и перейдём к самому интересному — особенностям экслпуатации.

    Итак, сервера — обычные выделеные сервера (кто сказал “виртуалка”? обычные железяки). Средняя конфигурация — 2х Core i7, 32–64 GB RAM, 2x 1T HDD / RAID1. По количеству — считаем. Два “балансера” (один основной, второй — “горячий” резерв, переключение — плавающий IP). Три сервера для сервисов. Один сервер для БД. Один сервер для брокера и Redis. Один сервер — тестовый (на нём крутятся все компоненты разом). Итого — 8 штук. LAN между серверами нет, весь трафик гуляет по ДЦ (некоторые сервера разнесены по разным стойкам).

    Что же с написаным выше не так, спросите вы? Да всё так, но дьявол, как обычно, кроется в деталях, а в нашем случае это — повседневная эксплуатация и поддержка. Дальше просто неструктурировано опишу некоторые моменты, которые я считаю проблемными.

    Инструкция по добавлению нового сервера начинается со слов “устанавливаем Gentoo”. Да, весь стек крутится на Gentoo, со всеми вытекающими. Provisioning делается баш-скриптом. Для управления конфигурациями используется synctool (такой rsync на стероидах по сути). Деплой приложения — git pull руками на всех семи серверах. В коде основного приложения в десятке мест гвоздями прибиты имена хостов БД, Redis, брокера. Разделение в коде на production/development весьма условное (программисту настроить окружение для разработки занимает 2–3 дня). Сервисы настолько тесно интегрированы с основным приложением, что при падении одного — валится вся платформа. Сам сервис представляет из себя от трёх до пятнадцати процессов, каждый из которых просто пускается руками в screen (да, на одном из серверов постоянно запущено 15–20 сессий screen, и в репозитории с документацией лежит файлик “вот такие скрины должны быть на этом сервере после ребута”).

    И самое главное — админка приложения. Рождённая в потаённых закоулках сознания сумрачного тевтонского гения гремучая смесь из bash, Ruby и Falcon. Вот вы знали, что есть такой язык программирования — Falcon? Теперь знаете (пройдите по ссылке, к слову, язык достоин внимания в качестве расширения кругозора). Сама “админка” представляет из себя просто набор SQL запросов, и кусков кода Ruby, которая позволяет оперировать разными параметрами сущностей. В ней нет ни-че-го, что оправдало бы использование чего-то ещё, кроме bash. Тот же falcon — за каким чёртом он там используется я так и не понял; реально всё, что делают falcon скрипты— по определённым условиям формируют примерно такое, и выполняют это через system():

    echo "SELECT stuff FROM entities" | psql -U postgres db_name

    Заключение


    Всё, что описано выше создавалось одним человеком в течение двух лет. Его программерские скилы оценивать не возьмусь, но админ (или девопс, как хотите) из него, прямо скажем, херовый — чего стоит одна Гента на проде, вместо нормального бинарного дистрибутива. В какой-то момент даже бизнес понял что дальше нормально оно жить не будет, и меня попросили посмотреть, что можно сделать, чтоб со всей этой хернёй попробовать взлететь. В следующей части расскажу, что и как я делал, чтобы приуменьшить количество энтропии во Вселенной.
    Share post

    Similar posts

    Comments 21

      +3
      Просто настоящей боли пост.
      С нетерпением жду, как Вы все это разгребли (сам был в той же ситуации, но тоже вышел из нее с щитом)
        0
        Продолжение: https://habrahabr.ru/post/317408/
        +1
        Интересно, продолжайте! На самом деле, это естественный ход вещей. Стартап за 2 года подрос, набрал клиентов, теперь задумался о качестве услуг и процессов, масштабировании и гибкости не в ущерб имеющимся клиентам. Можно лишь поздравить! Не все доживают.
          0
          Продолжение: https://habrahabr.ru/post/317408/
          +3
          Да, Gentoo это мило и прекрасно на проде. А могла быть слакварь :)
            0
            Кто-то от Gentoo плюется, кто-то от Slackware, мы вот от CentOS с его dracut плевались, когда при создании снапшота lvm — он отказывался грузиться. Не важно в принципе какой дистрибутив используется, все зависит от того сколько процентов в команде могут с ним нормально управляться, если только один человек, то беда…
              +1
              Ну количество человеко-часов затраченое на поддержку Gentoo всё-ж поболее будет, чем на поддержку rpm- или deb-based дистрибутива. «Какой дистрибутив» в контексте «Debian или CentOS» и правда не имеет значения, но вот «source-based или binary» — очень даже. Я про это немного во второй части пишу.
                0
                Мы в нашем приложении автоматически при каждой сборке создаем около 120 пакетов. Релизимся примерно 2-3 раза в день. Плюс около 30-40 билдов тестеров и столько же дев. Пакеты не простые: каждый апгрейд умный и делает все как надо при помощи pre/post inst/rm скриптов, включая миграции SQL.
                Сделаете тоже самое на Gentoo?
                0
                Очень интересно, жду продолжения, всегда тяготел к подобным историям.
                Боль с Gentoo на сервере ощутил на себе.
                  0
                  Продолжение: https://habrahabr.ru/post/317408/
                  +2
                  Вопрос скорее не к администраторам, а к разработчикам:
                  — В какой ситуации такая архитектура имеет смысла?
                  — Зачем срез состояний хранить в Redis?
                  — Зачем шина?
                  — Зачем вообще такое кол-во баз данных?
                  — Зачем хранить состояния в NoSQL базах?

                    0
                    Я в следующей части пройдусь по некоторым моментам из списка.
                      0
                      Продолжение: https://habrahabr.ru/post/317408/
                      0
                      Тема с 0MQ не раскрыта.
                        +1
                        Попытаюсь угадать: не удовлетворяет условиям масштабируемости (хороша для сообщений точка-точка), надежности (сообщения не персистентны).
                          0
                          Плохо угадываете. Если инструмент не подходит по своим характеристикам, его просто не будут использовать. Или как вы себе представляете, люди взяли 0mq, а через год поняли что персистентности нет?
                        0
                        Очень интересно. Пишите еще.

                        А как там по производительности?
                        Какую нагрузку держал такой зоопарк на таком железе в начале вашей разборки?
                        А были ли средства отказоустойчивость обеспечивающие? Падение одного сервера не рушило систему?

                        То ест весь этот зоопарк хоть как-то себя оправдывал или нет?
                          0
                          Плохо всё было по производительности. Упёрлись в пару говённо сделаных реализаций, и при 400-500 пользователей динамическая часть сайта тормозила страшно.
                          Отказоустойчивости не было, если падал один сервис — ложилось всё.

                          Продолжение: https://habrahabr.ru/post/317408/
                          +1
                          У меня объяснение это всему одно (особенно насчет админки): девопс просто принципиально не хотел пользовать PHP как несерьезный, и ему даже было невдомек, что он просто идеально подходит для таких задач. В конечном итоге сам себя в лужу и посадил.
                            0
                            Ну, с PHP я бы так не горячился. Питон/Перл, да тот же Руби, на котором остальной проект писан — было бы идеальным решением (не потому, что PHP плох, но потому, что Питон и Перл есть вообще везде, Руби — язык проекта, т.е. тоже в наличии по-умолчанию).
                              0
                              А, ну это да, и правда, Раби из коробки, да еще и на рельсах. Нет, насчет PHP все понимаю, просто надо смотреть сколько лет сему стартапу, лично я начинал свой крупный проект (у меня CMS) еще в те времена, когда писать что-либо для веба на чем-либо, отличном от PHP, считалось самоубийством. Нет, это было не так давно, просто те же Питон и Раби еще не завоевали свою популярность в этой области.

                          Only users with full accounts can post comments. Log in, please.