36
«Облако» в Badoo год спустя Юрий Насретдинов

Облако в Badoo год спустя

Embed Size (px)

DESCRIPTION

Доклад на highload++ в 2014 про «облако» в Badoo

Citation preview

Page 1: Облако в Badoo год спустя

«Облако» в Badoo год спустя

Юрий Насретдинов

Page 2: Облако в Badoo год спустя

О компании

225M пользователей

160K регистраций в сутки

2K серверов40K RPS на PHP-FPM

4M загрузок фото в день

50 языков интерфейса

Page 3: Облако в Badoo год спустя

О чём доклад• Общая архитектура: история создания, распределение нагрузки, отказоустойчивость.

• Логи скриптов: сбор, индексация, различные виды просмотра.

• Влияние Google App Engine — «облачный» разборщик очередей.

• Планы на будущее

• Как мы бы реализовали «облако» сейчас

Page 4: Облако в Badoo год спустя

Стек технологий• OS — SLES (SUSE Linux Enterprise Server)

• ЯП — PHP 5.5, C/C++, Go, Java

• Базы данных — MySQL, Tarantool, SQLite

• Кеширование — Memcached

• Веб-сервер — Nginx

Page 5: Облако в Badoo год спустя

Общая архитектура

• «Старая система»: mcron — утилита для раскладки crontab по машинам

• Общая архитектура новой системы («облака»)

• Распределение нагрузки по машинам, «попугаи»

• Способы обеспечения отказоустойчивости

Page 6: Облако в Badoo год спустя

mcron

sendSMS.phpanonChat.php #1moderation.php

config

scripts1 scripts2

facebook.phpanonChat.php #2

errorlogs.php

translate.phpanonChat.php #9

cleanup.php

scripts50

Page 7: Облако в Badoo год спустя

mcron

sendSMS.phpanonChat.php #1moderation.php

config

scripts1 scripts2

facebook.phpanonChat.php #2

errorlogs.php

translate.phpanonChat.php #9

cleanup.php

scripts50

Page 8: Облако в Badoo год спустя

mcron

sendSMS.phpfacebook.php

anonChat.php #1moderation.php

config

scripts1 scripts3

google.phpanonChat.php #2anonChat.php #3

migration.php

translate.phperrorlogs.php

anonChat.php #9cleanup.php

scripts50

Page 9: Облако в Badoo год спустя

Недостатки старой системы

• Ручное распределение нагрузки по серверам

• Ручной перенос скриптов с «упавших» машин — очень большой downtime

• Наличие «особенных» машин, на которых установлен дополнительный софт

Page 10: Облако в Badoo год спустя

«Облако»• Запуск заданий по расписанию / через API

• Автоматическая балансировка нагрузки

• Отсутствие «особенных» машин (на всех машинах стоит весь необходимый софт)

• Отказоустойчивость к «падению» машин — автоматический перезапуск после таймаута

Page 11: Облако в Badoo год спустя

«Облако» (для разработчика)

Page 12: Облако в Badoo год спустя
Page 13: Облако в Badoo год спустя

«Облако» (для разработчика)

script

job #1

job #2 job #3

job #4job #5

Page 14: Облако в Badoo год спустя

Архитектура

MySQL

MySQL

cloudsys1

cloudsys2

cloud1

cloudN

• • •

replication

heartbeat

mysql

Легенда:

master

phproxyd

Page 15: Облако в Badoo год спустя

«Облако»• Около 1 000 машин*

• 15K SQL RPS (50/50 read/write)

• 1 000 запусков скриптов в секунду

• «Запускалка» на PHP, 16 процессов

• Планировщик на go

* Цифры приведены для 1 ДЦ, у нас их 2

Page 16: Облако в Badoo год спустя

Планировщик

PHP

Go

Page 17: Облако в Badoo год спустя

Балансировка нагрузки

1000300

600250

2000230

1000200

2000180

weighted round-robin

Page 18: Облако в Badoo год спустя

Балансировка нагрузки

Page 19: Облако в Badoo год спустя

Отказоустойчивость• MySQL — ручное (!) переключение на slave в случае аварии

• Управляющая логика работает «циклами» — перед началом цикла берется лок в базе, по окончании цикла лок отпускается

• Если машина «упала» в середине цикла, то через wait_timeout на сервере соединение будет разорвано и, соответственно, отпущен лок, давая возможность работать логике другой машине

Page 20: Облако в Badoo год спустя

Отказоустойчивость• По умолчанию wait_timeout составляет 8 часов…

• Мы выставили wait_timeout = 60 сек

• Cпецифичная для Percona настройка innodb_kill_idle_transaction = 60 сек

• Таким образом, при любых проблемах с сетью или с машинами, максимальный простой управляющей логики составляет 1 минуту

Page 21: Облако в Badoo год спустя

Отказоустойчивость• «Задания» запускаются с лимитом на максимальное время их работы, который задает пользователь

• При наступлении лимита скриптами присылается SIGTERM

• Если машина не отвечает — скрипт сам «погибает» от SIGALRM, поскольку при запуске скрипта мы вызываем alarm(макс.время работы + 3 секунды)

• Часы на всех машинах идут с точностью до 1 секунды

Page 22: Облако в Badoo год спустя

Сбор логов• Каждое задание получает уникальный id

• Задание — запуск скрипта, с перенаправлением вывода в файлы «logs/phproxyd.<id>.(out|err).log»

• С помощью inotify слушаем изменения в директории с логами и отправляем новые строки в scribe

• С задержкой доставки scribe (несколько секунд) логи скапливаются на отдельной logs-машине

Page 23: Облако в Badoo год спустя

Просмотр логов• Логи для каждого скрипта складываются в отдельный файл

• Файлы «ротируются» (с использованием logrotate) раз в неделю

• Каждая строчка в логе содержит id запуска и hostname, где скрипт запускался

• Логи «индексируются» в MyISAM-таблички для быстрого просмотра истории по конкретному id

Page 24: Облако в Badoo год спустя

Разборщик очередей

• У нас все «важные» очереди хранятся в MySQL, для сохранности и транзакционности посылки событий

• В MySQL довольно тяжело «правильно» разбирать очереди во много потоков

Page 25: Облако в Badoo год спустя

Разборщик очередей• Существует много стратегий «разбора очереди» в MySQL:

• 1) SELECT … WHERE id % N = M

• 2) UPDATE … SET instance_id = N WHERE instance_id IS NULL

• 3) SELECT … WHERE shard_id = N

Page 26: Облако в Badoo год спустя

Разборщик очередей• Почти все стратегии плохо масштабируются при увеличении числа воркеров

• Подход с shard_id масштабируется, но нужно следить за равномерностью распределения + требуется решардинг при смене числа воркеров

• Решили написать обработчик очереди, используя API по добавлению заданий в «облако»

Page 27: Облако в Badoo год спустя

Разборщик очередей• Реализация: На каждую очередь создается 2 «скрипта»:

• 1) мастер, который выбирает id новых событий из очереди (однопоточный)

• 2) воркеры, которые обрабатывают пачки заданий (получают набор id заданий, которые нужно обработать)

• Мастер «помнит» все id, которые он уже выдал и выбирает из очереди с помощью SELECT id … NOT IN(…)

Page 28: Облако в Badoo год спустя

Разборщик очередей• Мастер группирует события в «пачки» для большей эффективности обработки

• Равномерное распределение по воркерам

• Динамическое число воркеров (on demand)

• Можно сделать такой разборщик без API, через fork(), со всеми воркерами на одной машине

Page 29: Облако в Badoo год спустя

Причины «падений»• Суммарный downtime системы составил 3 часа за год эксплуатации, что дает uptime 99,97%:

• 1 час — Duplicate key в MySQL :)

• 1 час — «кривой» merge (неправильно разрешены конфликты) — забыли прогнать тесты

• 30 минут — «сломанный» cron на машинах (баг в одной из версий vixie cron) — не отправлялся heartbeat

Page 30: Облако в Badoo год спустя

Проблемы MySQL• Основные проблемы возникают из-за глобальных mutex’ов или однопоточных подсистем:

• Медленный DROP TABLE больших таблиц — перед unlink() берется глобальный metadata lock и «висят» все транзакции

Page 31: Облако в Badoo год спустя

Проблемы MySQL• Медленный (однопоточный) purge thread — из-за

MVCC «удаленные» записи могут очень медленно «пуржиться» из таблиц — в InnoDB возможна ситуация, когда SELECT COUNT(*) из «пустой» таблицы идет минуты и возвращает 0

• Однопоточная репликация (до MySQL 5.6) — изменения могут не успевать применяться на реплике

Page 32: Облако в Badoo год спустя

Проблемы MySQL

• Высокие накладные расходы на подключение — MySQL плохо «держит» больше N подключений, где N составляет 2-3 тысячи

• В новых версиях MySQL и в MariaDB есть «connection pooling», причём для MySQL эта возможность отсутствует в Community Edition

Page 33: Облако в Badoo год спустя

Проблемы ядра Linux• Баг с выводом ps и «[migration/N]», который якобы

«ест 100% CPU» (на самом деле не ест)

• Очень медленный unlink() больших файлов, даже с ext4 (возникает из-за высокой фрагментации)

• «Плохая» реализация inotify — если в директории активно создают файлы и у вас много «свободной» ОЗУ, inotify_add_watch() будет занимать секунды (!) и полностью блокировать запись в эту директорию

Page 34: Облако в Badoo год спустя

Планы на будущее• Полностью перевести управляющую логику на Go: иметь по одной goroutine на машину «облака» — одна «затупившая» машина не будет тормозить обработку остальных заданий

• Перевести phproxyd на PHP (уже написан, нужно запустить в production) — экономия на запуске интерпретатора

• Возможно, открыть исходные тексты системы

Page 35: Облако в Badoo год спустя

Как бы мы реализовывали сейчас

• Управляющая логика на Go — отличный выбор, если вы почему-то не любите Erlang

• Хранение текущего состояния заданий — Tarantool + Lua процедуры

• Сразу написать новый демон для запуска заданий вместо существующего (на PHP, конечно же)

Page 36: Облако в Badoo год спустя

ВопросыЮрий Насретдинов

@YNasretdinov [email protected]