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

У нас было 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

Заключение


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

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


  1. v_sadist
    09.12.2016 13:24
    +3

    Просто настоящей боли пост.
    С нетерпением жду, как Вы все это разгребли (сам был в той же ситуации, но тоже вышел из нее с щитом)


    1. br0ziliy
      12.12.2016 16:09

      Продолжение: https://habrahabr.ru/post/317408/


  1. olku
    09.12.2016 13:36
    +1

    Интересно, продолжайте! На самом деле, это естественный ход вещей. Стартап за 2 года подрос, набрал клиентов, теперь задумался о качестве услуг и процессов, масштабировании и гибкости не в ущерб имеющимся клиентам. Можно лишь поздравить! Не все доживают.


    1. br0ziliy
      12.12.2016 16:09

      Продолжение: https://habrahabr.ru/post/317408/


  1. MgmZog
    09.12.2016 13:45
    +3

    Да, Gentoo это мило и прекрасно на проде. А могла быть слакварь :)


  1. SchmeL
    09.12.2016 15:22

    Кто-то от Gentoo плюется, кто-то от Slackware, мы вот от CentOS с его dracut плевались, когда при создании снапшота lvm — он отказывался грузиться. Не важно в принципе какой дистрибутив используется, все зависит от того сколько процентов в команде могут с ним нормально управляться, если только один человек, то беда…


    1. br0ziliy
      09.12.2016 15:55
      +1

      Ну количество человеко-часов затраченое на поддержку Gentoo всё-ж поболее будет, чем на поддержку rpm- или deb-based дистрибутива. «Какой дистрибутив» в контексте «Debian или CentOS» и правда не имеет значения, но вот «source-based или binary» — очень даже. Я про это немного во второй части пишу.


    1. Singaporian
      12.12.2016 16:09

      Мы в нашем приложении автоматически при каждой сборке создаем около 120 пакетов. Релизимся примерно 2-3 раза в день. Плюс около 30-40 билдов тестеров и столько же дев. Пакеты не простые: каждый апгрейд умный и делает все как надо при помощи pre/post inst/rm скриптов, включая миграции SQL.
      Сделаете тоже самое на Gentoo?


  1. rodial
    09.12.2016 15:52

    Очень интересно, жду продолжения, всегда тяготел к подобным историям.
    Боль с Gentoo на сервере ощутил на себе.


    1. br0ziliy
      12.12.2016 16:05

      Продолжение: https://habrahabr.ru/post/317408/


  1. niko1aev
    09.12.2016 17:02
    +2

    Вопрос скорее не к администраторам, а к разработчикам:
    — В какой ситуации такая архитектура имеет смысла?
    — Зачем срез состояний хранить в Redis?
    — Зачем шина?
    — Зачем вообще такое кол-во баз данных?
    — Зачем хранить состояния в NoSQL базах?


    1. br0ziliy
      09.12.2016 18:50

      Я в следующей части пройдусь по некоторым моментам из списка.


    1. br0ziliy
      12.12.2016 16:06

      Продолжение: https://habrahabr.ru/post/317408/


  1. tgz
    09.12.2016 20:23

    Тема с 0MQ не раскрыта.


    1. avigmati
      12.12.2016 16:09
      +1

      Попытаюсь угадать: не удовлетворяет условиям масштабируемости (хороша для сообщений точка-точка), надежности (сообщения не персистентны).


      1. tgz
        12.12.2016 16:19

        Плохо угадываете. Если инструмент не подходит по своим характеристикам, его просто не будут использовать. Или как вы себе представляете, люди взяли 0mq, а через год поняли что персистентности нет?


  1. jewubinin
    12.12.2016 16:06

    Очень интересно. Пишите еще.

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

    То ест весь этот зоопарк хоть как-то себя оправдывал или нет?


    1. br0ziliy
      12.12.2016 16:08

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

      Продолжение: https://habrahabr.ru/post/317408/


  1. Acuna
    13.12.2016 10:33
    +1

    У меня объяснение это всему одно (особенно насчет админки): девопс просто принципиально не хотел пользовать PHP как несерьезный, и ему даже было невдомек, что он просто идеально подходит для таких задач. В конечном итоге сам себя в лужу и посадил.