Перенос проектов между ЦОДами. Часть 2
Apr 9, 2019 01:09 · 897 words · 5 minutes read
С чего начать и что делать?
Определиться с требованиями:
- выделить роли контейнеров
- единая точка для service-discovery (front контейнеры)
- приложение должно получать конфигурацию через env переменные или dot.env файлы
- доступ к ресурсам только через haproxy или фронты
База данных Percona
Необходимо получить реплику БД в нашем проде. Решив эту проблему, мы бы смогли перетащить данные в dev и встроить обновление данных в нашу баз данных.
Сервер с базой данных (Percona):
- 600GB данных на ext4
- 4 Kq/s.
- находится в Нижнем Новгороде (НН)
- может не подняться после ребута
Чтобы получить реплику, мы подцепили наш сервер обычным слейвом, в обход percona xctradb. Так было сделано потому, что для полноценной интеграции в кластер, необходимо было перезагрузить инстанс percona. 600 Gb данных переливались примерно 3 дня, так как канал между цодами НН и Урал у нас ограничен. 600Gb на zfs превратились в 400Gb. К этой реплике мы подключили percona кластер на zfs, и уже с него начали снимать zfs снэпшоты, для отправки в dev. Так у нас появилась БД в нашем дев окружении.
Sphinx
Когда данные появились в кластере, то получить из него индексы для сфинкса было делом техники. Пакет sphinx под arch linux был уже собран и протестирован. Все свелось к настройке параметров индексации данных БД в поисковые индексы. Полная индексация sphinx занимает около 6 часов.
Openstack Swift
Самая тяжелая часть приложения. 20ТБ статики, которую необходимо перенести. Swift оперирует следующими понятиями: - object - наименьшая единица информации - файл с картинкой, extended attributes - container - хранилище групп объектов. Напоминает папку с файлами - ring - группа инстансов swift
Как работала раздача статики:
- нужно раздавать картинок, либо кропы картинок
- поднят nginx, в котором настроена большая кэшзона на 350GB для статики
- при cache miss запрос уходит в swift, результат складывается в cache
- при отсутствии картинки в swift, предполагается что это запрос картинки на кроп
- запрос уходит на сервис ресайза, итог ресайза складывается в специальный контейнер swift и отдается в stdout
- результат кропа сохрянеятся в кэшзону
Что сделали:
- добавили инстанс swift в ЕКБ к кольцу серверов в НН
- поставили максимальный вес для нового инстанса swift, чтобы новые картинки сохранялись туда
- попробовали перелить данные средствами swift - медленно
Проблема в том, что расположение файлов на файловой системе не соответсвует контейнерам. То есть нельзя по расположению объекта на файловой системе понять, к какому контейнеру он относится. Пришлось запускать rsync -rv и перекачивать все данные. Переливка заняла примерно 14 дней. Вроде все работает, файлы сохраняются, раздаются.
Memcached
Для отказоустойчивости принято поднимать несколько инстансов memcache. В нашем случае ребята использовали 2 memcached, ip адреса которых были захардкожены в коде.
Тут может быть несколько вариантов организации доступа к memcached.
- Поднимаем haproxy и через него балансируем запросы, добавляем health чеки. 1 инстанс мастер, другой backup
- Используем шардирование ключей по нескольким инстансам (twemproxy, mcrouter, dynomite)
Мы решили попробовать пойти по 2му варианту, но: twemproxy не умеет отдавать правильный ответ на команду version; mcrouter имеет очень много зависимостей и сложно собирается под arch; с dynomite тоже возникли некоторые проблемы.
Было решено использовать 1 жирный memcached и ходить в него через haproxy. Выделяется основной memcached, 2й ставится бэкапным. При возникновении проблем с основным инстансом, haproxy переключится на резернвый.
PHP7 + laravel
Часть проекта была на php7.1, что хорошо. Плохо, что была россыпь репозиториев, в которые были выделены сервисы проекта. Общая база, общий memcached, общий sphinx. Все пересекается. Каждый сервис имел свой клиент, который был реализован на lumen. Неиспользуемые файлы не были почищены. Функционал и роутинг каждой составляющей сервиса так же в отдельной репе. Как этим всем пользоваться:
- пишем сервис
- пишем клиента для этого сервиса
- пишем laravel пакет, в котором реализуем функционал с использованием только этого сервиса. Роутинг зашиваем сюда же.
- подключаем к проекту
- имеем 1 пустую монорепу, к которой подключается > 10 пакетов
Что еще имеем, к вышесказанному:
- фасады laravel, что ломает нативную работу IDE
- отсутствие тестов, то есть единственный профит фасадов не используется
- laravel - конфиги production внутри git
- нет единой системы конфигурирования
- отказоустойчивость - haproxy на другом хосте
- логи отправляются по http
PHP56
Большая часть проекта написана на php56. Основная бизнес-логика так же там. 1.3M строк кода. Отсутствие роутинга, только вызов конкретных файлов. Подключены все библиотеки php, которые возможно. По коду захардкожено > 100 ip адресов, везде абсолютные url, при подключении файлов. В том числе и в js+css.
Что сделали
Необходимо было собрать php56, php71 под arch linux. На момент проведения этих действий, актуальный пакет php > 7.2. Провели аудит кода на предмет использования php extensions. Выяснилось, что больше половины расширений не нужно и в принципе не используется. Некоторые расширения можно удалить, переделав все немного по другому. Например memcache -> memcached. После того, как стало понятно, какой набор софта нам необходим, собрали необходимые пакеты. Для того, чтобы начать разрабатывать, мы собрали тестовые среды (у нас это набор контейнеров + бд). Попробовали завести код, который работает на php7. Микросервисы вызывают микросервисы. Начали конфигурировать сервисы через конфиг, который генерируется при старте контейнера. Он может измениться в любой момент времени. Весь сервис дискавери зарулили на фронты. Только фронты знают, где находится тот или иной сервис. Фронтов у нас 2. Доступ ко всем внешним ресурсам организовали через haproxy, который стоит на контейнере с каждым сервисом.
Со 2й частью проекта оказалось все сложнее. Там еще был и apache -> >100 файлов .htaccess внутри проекта.
- убрали неиспользуемые расширения php
- выпилили часть сервисов, которые не нужны
- убрали хардкод ip адресов
- убрали конфиги внутри приложения
- переписали конфиги apache на nginx
- подняли prod сервера и начали использовать из для теста
Полезные инструменты
- ngrep
- xdebug
- var_dump
- https://winginx.com/ru/htaccess
- https://php.net/
- vim + /etc/hosts