[Перевод - recovery mode ] DevOps зоопарк или как 500px обслуживает более 500TB изображений
От переводчика: Я выбрал эту статью для перевода, как яркий пример развивающегося западного стартапа с выраженными для этой группы признаками: очень много новых технологий, использование большого количества сторонних сервисов, эксперименты с архитектурой. В статье затронуты особо интересные темы связанные с построением платформы из микросервисов, DevOps и совсем мало освещенное на Хабре явление под названием ChatOps. Enjoy!
О 500 px 500 px — это онлайн сообщество, сформировавшееся вокруг фотографии. Миллионы пользователей со всего мира просматривают, делятся, продают и покупают самые красивые фотографии. Мы ценим дизайн, простоту кода и ответственность.Я DevOps. В 500 px, работаю над платформой: бэкенд, мониторинг, управление конфигурацией, автоматизация и конечно же развертывание системы.Разработка В 500 px команда разработчиков разделена на 4 группы: Веб, Мобильные приложения, Качество и Тестирование, и конечно же наша команда ответственная за платформу и архитектуру, которая занимается проектированием API и бэкенда, включая управление инфраструктурой в целом.Наши команды достаточно многофункциональны и границы между ними практически размыты, так что разработчики свободно переходят из одной команды в другую чтоб поработать с разными интересными для них технологиями. Это очень помогает легко распространять знания внутри коллектива и предотвращать застои. Еще, между командами разработчиков, дизайнеров, поддержки налажена очень тесная связь, что позволяет нам быть гибкими, честными и сосредоточиться на действительно важных вещах.
Архитектура Архитектура 500 px может быть представлена как огромный Ruby on Rails монолит, окруженный целым созвездием микросервисов. Rails отвечает за веб и за API, который в свою очередь обслуживает мобильные приложения и всех наших API клиентов.Микросервисы предоставляют различный функционал для основного приложения-монолита, а так же обрабатывают некоторые API запросы напрямую.
Rails монолит достаточно стандартный: приложение и API обслуживают запросы с помощью Unicorn, за которым стоит Nginx. У нас целые кластера этих Rails серверов, которые стоят либо за HAProxy или за LVS балансировщиками. Основные базы данных с которыми работает главное Rails приложение: MySQL, MongoDB, Redis и Memcached. Еще у нас куча Sidekiq серверов для тяжелых задач, работающих в фоне. На данный момент все это хостится на собственном железе в датацентре.
Микросервисы более интересны. На данный момент у нас их около 10 типов, каждый из которых сосредоточен на предоставлении отдельной и независимой бизнес логики платформы. Некоторые из микросервисов:
Поиск похожего контента, работает на Elasticsearch Сервис отвечающий за прием/сохранение изображений, AWS S3 Фиды активности пользователей, работают на Roshi и AWS Kinesis Динамическое пережатие изображений и добавление ватермарка Специализированные API для наших веб и мобильных приложений Микросервисы работают как на Amazon EC2 так и на своем железе в датацентре. В основном они написаны на Go, но есть и исключения на NodeJS или Sinatra. На самом деле, независимо от языка мы стараемся создавать наши микросервисы хорошими 12-факторными приложениями, которые позволяют снизить сложность развертывания и управления конфигурацией. Все эти сервисы работают либо за HAProxy либо за AWS Elastic Load Balancer-ами.
Использование микросервисов очень помогает, позволяя избежать сложностей за счет вынесения логики за пределы основного приложения. Все что надо знать команде фронтенд разработчиков использующей эти сервисы — это только API. А если что-то необходимо изменить в каком либо из компонентов — это легко сделать. К примеру очень просто использовать микросервис поиска, не зная ничего про ElasticSearch. Такая гибкость доказала свою пользу по мере того как мы развиваем нашу платформу, потому что она позволяет нам пробовать новые технологии безопасным, изолированным способом. Если вам интересно использование микросервисов, то бывший разработчик 500 px Paul Osman в прошлом году на QConSF рассказал о нашем опыте миграции от большого монолита к микросервисам (от переводчика: очень интересно, советую посмотреть).
Обработка Изображений Пожалуй самые интересные из микросервисов которые мы используем в 500 px это обработка и обслуживание изображений. Ежемесячно мы поглощаем миллионы фотографий высокого качества от нашего сообщества и отдаем терабайты картиночного трафика с основного CDN, Edgecast. В прошлом месяце мы отдали порядка 569TB трафика, а 95-й перцентиль полосы пропускания составил около 2308Mbps. Людям действительно нравится смотреть красивые фотки!
Для сохранения и раздачи графического контента работают 3 группы микросервисов в EC2, все построенные вокруг S3 где мы и храним все наши картинки. Все они написаны на Go и нам действительно понравилось использовать Go для таких вещей, потому что это позволяет писать маленькие, но очень быстрые многопоточные сервисы. А это значит мы можем их размещать на меньшем количестве машин, держа под контролем счета за хостинг.
С первым микросервисом посетители сталкиваются когда они загружают фотографии, — мы его называем Медиа Сервис. Медиа Сервис достаточно прост: он принимает загрузку, сохраняет в S3, а потом просто добавляет задачу в очередь RabbitMQ для последующей обработки.
Далее, принимающий задачи из RabbitMQ — второй микросервис, названный Конвертером. Сервис Конвертации скачивает исходное изображение из S3, производит определенное количество обработок по генерации миниатюр различого размера и опять сохраняет их в S3. Мы используем эти миниатюры в разных местах: как на сайте так и в мобильных приложениях.
Все это скорее не является удивительным для сервиса обмена фотографиями, и в течении некоторого времени эти два микросервиса справлялись со всеми нашими задачами — мы просто сделали S3 хранилище с миниатюрами источником для нашего CDN. Однако с ростом всей системы это решение оказалось не только дорогим и неэффективным в плане использования дискового пространства, но также и недостаточно гибким в случаях, когда добавлялись новые продукты, требующие других размеров изображений.
Чтобы решить эту проблему мы недавно создали Сервис Генерации Изображений (и да, мы склонны выбирать наглядные имена для таких вещей). Этот новый сервис работает за CDN, динамично генерируя из S3 оригинала изображение любого размера или формата на лету. Он так же умеет накладывать водяные знаки или символику фотографа, что особенно нравится нашему сообществу.
Сервис Генерации Изображений достаточно высоконагруженный, кластер обрабатывает порядка 1000 запросов/секунду в часы пик. Динамическая перегенерация и наложение водяных знаков ресурсоемкий процесс, поддерживать разумное время отклика при высокой нагрузке — непростая задача. Мы упорно трудились над этой проблемой, и на пике посещений мы в состоянии поддерживать 95-процентиль времени отдачи контента ниже 180ms. Это стало возможным при помощи классной и быстрой библиотеки для обработки изображений VIPS, агрессивному кэшированию, и просто сумасшедшим оптимизациям. Вне часов пик, обычное время отдачи для картинок ниже 150ms.
И мы не останавливаемся на достигнутом! Почти наверняка еще много оптимизаций будет найдено, мы надеемся все больше и больше снижать время отдачи картинок в будущем.
Рабочий Процесс Мы используем GitHub и практикуем непрерывную интеграцию (CI) для всех наших основных репозиториев.Для Rails монолита мы используем Semaphore и Code Climate, стандартную rspec конфигурацию для юнит тестирования и небольшое количество Capybara/Selenium тестов для интеграционного тестирования. Наш 500 px сотрудник и просто классный парень Devon Noel de Tilly подробно описал как мы используем эти инструменты, так что не буду здесь останавливаться.
Для наших Go микросервисов мы используем Travis CI под тесты и для сборки Debian пакетов. Travis после билда загружает собранные пакеты во временное S3 хранилище, после чего другой микросервис скачивает их, подписывает и импортирует в наш собственный Apt репозиторий. Для создания пакетов мы используем FPM, Aptly — для управления своими репозиториями. Недавно для этих задач я пробовал packagecloud.io и мне он действительно понравился, так что возможно мы перейдем на него в ближайшем будущем.
Для развертывания мы используем целую группу инструментов. На самом низком уровне мы используем Ansible и Capistrano, Chef — для управления конфигурацией. На более высоком уровне нам в 500 px действительно понравилась ChatOps практика, так что мы заскриптовали все наши сценарии использования этих инструментов в всегда верного Hubot бота, которого прозвали BMO.
Каждый в 500 px может с легкостью развернуть сайт или микросервис сообщением в чате:
bmo deploy