August 18th, 2007

HighLoad

Фреймворк для масштабируемых проектов

Немного из области программистских утопий... Давно и у многих есть потребность в фреймворке, который бы легко позволял сделать небольшой простой, но масштабируемый проект. Начальные шаги в области масштабирования проектов почти всегда одинаковые - вынос фронтенда, базы данных на отдельные машины, дублирование бекендов, кеширование. Для большинства проектов этого достаточно. Какие основные моменты вы бы выделили в фреймворке для построение простых масштабируемых проектов? Скажем, небольшого фотосайта, популярного СМИ или небольшого тематического блогохостинга?

  1. Ядро неизменяемо и легко отделяемое от всего остального, от кода проекта, от кода плагинов;
  2. Существует понятие плагина - набор модулей, реализующих определенный API;
  3. Хранение кода в SVN, причем отдельно кода ядра, кода проекта, кода плагина;
  4. Набор команд, желательно make-команд, реализующий функциональность управления фреймворком (в том числе развертывания);
  5. Набор make-файлов должен позволять управление множеством бекендов, множеством бекендов, множество фронтендов;
  6. Множество девелоперских серверов, qa-сервер, различные конфиги для каждого из них;
  7. Чистота юридических прав, код должен быть очищен от претензий крупных компаний. Этот пункт в качестве подготовки к open source;
  8. Один выделенный лог-сервер, один выделенный кэш-сервер (memcached);
  9. Простота использования, например, использование одного механизма формирования SQL-запросов.
  10. Простая документация, возможность работы с фреймворком "по умолчанию", без понимания сути происходящего;

Цель поста - попробовать в онлайн-режиме разработать проект фреймворка для решения строго определенного класса задач. Класс задач - построение небольших простых масштабируемых проектов, размером от одной до десятка машин, размещенных на выделенных серверах. Фреймворк должен быть простым, предоставлять решения для 90% самых распространенных задач, для оставшихся 10% - не мешать их ручному решению.

СХЕМА РАЗРАБОТКИ

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

СХЕМА ВЫКАТКИ

Здесь нужно соблюсти разумный баланс между легкостью настройки и возможностью все кастомизировать. Ясно, что оптимальные решения для нашей цели (проект из 5-10 машин) и проекта из 100 серверов будут совершенно разными. Например, для сотен серверов удобнее было бы определить тип сервера - бекенд - и перечислить через запятую адреса машин, куда надо производить выкатку по типу бекенд.

Для нас подойдет более простой вариант. Опишем три вида выкатки:

  • Бекенд (выкатить конфигурационные файлы "тяжелого" сервера и код);
  • Фронтент (выкатить конфигурационные файлы "легкого" сервера и дизайнерскую графику, css-файлы, статику);
  • База данных (выкатить конфигурационные файлы)
По сути - все, нам этого хватит (хватит?)

Далее для каждого вида выкатки прописываем файл по умолчанию, proto-файл. Из этих файлов разработчики затем будут создавать описания конкретных серверов. Например, выкатка у нас происходит с помощью make-файлов, тогда нам нужно в каждом из make-файлов прописать набор целей. Это будет своего рода API, с помощью которого большая система будет выкатывать каждый конкретный сервер. Сейчас поясню на примере.

У нас проект - одна база данных, два бекенда, два фронтенда. Мы сделали "корневой make-файл" в котором написали:
include "servers/db-1.mk"
include "servers/backend-1.mk"
include "servers/backend-2.mk"
include "servers/frontend-1.mk"
include "servers/frontend-2.mk"

build: db_build backend_1_build backend_2_build frontend_1_build frontend_2_build

Файлы servers/* были предварительно сделаны по образу и подобию наших proto-файлов. Да, из каждого proto-файла описание конкретного сервера надо делать вручную - прописывать адрес, возможно, пути к директориям и т.д. Ну и что? Мы ведь не для сотни серверов это делаем, а для десятка, причем один раз.

Соответственно каждый из mk-файлов умеет выполнять build-цель. Как он это делает - неважно. Если Вам достаточно стандартной сборки на удаленной машине nginx - отлично, используйте proto-файл без изменения. Если недостаточно, то внесите свою специфику. Сложности возникают, когда нам нужно внести свою специфику одновременно в десятки mk-файлов - наверняка, что-нибудь да забудем. Тут вопрос в количестве машин и файлов, за которыми надо следить. Если их десять (как у нас), то можно и последить. Если их сотни, то такая простая система выкатки становится уже не удобной.

Разработчик говорит - "выполни функцию сборки всего требуемого программного обеспечения для всех серверов" или попросту "make build". Система выкатки последовательно вызывает соответствующую build-цель для каждого из серверов. Все просто и гибко.

Продолжение следует...