- Регистрация
- 14.05.16
- Сообщения
- 11.398
- Реакции
- 501
- Репутация
- 0
В Badoo я работаю в команде, которая разрабатывает на PHP. Одна из фич, которой мы занимаемся, со временем начала отъедать всё больше и больше железячных ресурсов. В итоге мы едва успевали добавлять серверы под растущую нагрузку. При этом вечера, проведённые с Go дома, подсказывали, что можно сделать на порядки производительнее, не затратив на разработку много времени.
Я расскажу о том, почему наша фича так плохо ложится на PHP и хорошо – на Go, как уговорить всех всё переписать и не показаться сумасшедшим. Ну и, конечно же, как из 19 серверов оставить только 4.
Павел Мурзаков (далее – ПМ): – Меня зовут Паша Мурзаков, я работаю в Badoo. Всем спасибо, что пришли на meet-up. Сегодня будем говорить о том, как 200 строк на Go помогли нам освободить 15 серверов.
Что думают о Badoo и какова роль PHP?
Вообще, когда мы готовим доклады, мы начинаем с того, что Badoo – это большой-большой dating, что у нас много тысяч серверов и вроде highload. Думаю, здесь все об этом знают, и я хочу сменить фокус на то, чтобы рассказать немного о команде и сказать про роль Go в Badoo.
Вообще, в сообществе нас знают так: Badoo – это что-то о PHP. Ребята сидят, шпилят на PHP, потом выкладывают какие-то статьи на «Хабр» о том, как пошпилили. Иногда что-то в open source выкладывают. В общем, всё что-то о PHP…
Когда я готовился к докладу, то зашёл в нашу корпоративную директорию и написал “php” с помощью CTRL+F – получилось 62 результата. Хотел показать, что, если написать “go”, получится 0, но что-то пошло не так:
Надо было писать “golang”, как это обычно бывает.
Вообще, это правда, что PHP в «Баду» очень распространён. Больше всего девелоперов пишет именно на PHP. У нас есть четыре больших отдела, которые пишут только на PHP. Я, например, тимлид в отдел Features – мы тоже пишем только на PHP, решая на самом деле много интересных задач, порой сложных: когда у тебя много клиентов, разные версии, надо поддерживать «Андроид», iOS, мобильный веб, веб, и ещё все эти данные гонять между дата-центрами, и вообще highload…
…каждый запрос, отосланный в MySQL или MemCache, можно случайно завалить, если сделать что-то не так. Поэтому нужно вопросов надо решить. Вопрос о выборе языка перед всеми этими людьми в принципе не стоит:
Это команда PHP в «Баду». Вы спросите: «Какова роль Go в «Баду» и каково его место»?
Go в Badoo
Видите белый пробел (на предыдущем слайде справа)? Это место Go в «Баду» по состоянию на 2012 год. В 2014-м силами этих трёх бойцов (Марко Кевац, Андрей Нигматуллин и Дмитрий Новиков).
написан первый daemon на Go. Они выложили его в продакшн. Об этом рассказывал Тоха Поваров у нас на «кухне», на точь-в-точь таком же митапе два года назад. Тогда был Go 1.3 или 1.4. Ребята написали демона, который хранит уйму объектов в памяти (просто какое-то нереальное количество памяти было занято).
Все помнят истории про Garbage Collector: как пауза там была 30 секунд и всё такое. Доклад очень интересный – всем советую
Потом тот же Тоха Поваров и Саша Холодов написали несколько других сервисов на Go:
В итоге стало как-то так:
Эти 5 человек – из отдела «Си». В принципе, только они и писали что-то на Go. Но у нас в компании принят прагматичный подход – ориентированность на результат. Поэтому не важно, откуда ты: если ты знаешь, как сделать что-то эффективнее, сэкономить, то – welcome!
К тому же это ж си-шники, а не go-шники! Но пишут на Go. Почему бы PHP-шникам не начать, кстати?.. Попробую ответить на этот вопрос.
Содержание доклада
Задача
Кто-нибудь из зала когда-нибудь пользовался Badoo? Поднимите, пожалуйста, руки… Отстой, мало! Всем установить «Баду», посмотреть. На первый раз прощаю. Расскажу немного о том, как он работает.
Как я уже сказал, мы – dating. Очень многое у нас крутится вокруг профайлов:
Профайл – это аватарка, имя, где работаешь, возраст. Можно пролистать дальше и увидеть одну из составляющих – блок «Друзья». Немного увеличу, чтобы лучше было видно:
Продуктовый смысл, думаю, всем более-менее понятен. Ты смотришь на профайл: видишь, что это не какие-то маньяки-педофилы, а тут вообще твои друзья (на «Баду») и можно этой компании можно доверять…
Из зала: – Вот жена! =)
ПМ: – Вообще, это повышает вовлечённость пользователей: они начинают больше кликать, больше проводить времени, совершать больше действий. И одна из самых важных составляющих – это, что мы можем сподвигнуть пользователя на приглашение других. Мы говорим: «Этот человек ещё не на «Баду», пригласи его».
Я хочу, чтобы вы часть слева «забыли» (friends). Сегодня нас будет интересовать то, что называется in common:
Блок Friends
Что такое общие друзья, думаю, понятно. На всякий случай быстренько пройдёмся:
Мы – пользователь А, у нас есть друзья Х и Y. Смотрим на пользователя B: у него есть друзья Z и Y. Y – общий друг. Выглядит всё просто, детский сад. Как реализовать:
Обновление API (v2.0) «Фейсбука»
Так и работало до того момента, когда «Фейсбук» обновил свой API на версию 2.0:
Когда готовился к докладу, пытался что-нибудь из логов вставить, но они с позором выпилили эту часть истории, поэтому мне придётся вам рассказать на словах.
Раньше, когда мы просили у «Фейсбука» друзей, он возвращал нам тех, кого я называю зарегистрированными: когда человек кликает «Авторизоваться через Facebook», у него спрашивается, даёт ли он доступ к «Фейсбуку»; если дал – мы начинаем считать зарегистрированным через наше приложение.
Мы также могли получить и тех, кто не зарегистрирован.: ели мы просим друзей у какого-нибудь пользователя, мы получаем даже тех, кто вообще ничего о «Баду» не знает. Было отличное время, но потом всё стало хуже…
Реализация № 1 (крах)
«Фейсбук» начал заботиться о приватности и стал выдавать на запросы друзьями только зарегистрированных пользователей. Чтобы это как-то компенсировать, он добавил новый endpoint, который возвращал только общих друзей между двумя.
Это в принципе то, что нам нужно – общие друзья. Он возвращал как зарегистрированных, так и незарегистрированных. Но проблема в том, что нам для получения этого нужно два Facebook id.
Если взять нашу базу, в которой 300 миллионов [пользователей]: чтобы предварительно получить все пересечения, нам нужно сделать 3002 млн запросов, что не очень реалистично. Потом ещё и поддерживать это в актуальном состоянии. Поэтому надо получать друзей в онлайне.
Реализация № 2
Окей. Что надо получать – мы получаем. Скачиваем зарегистрированных (так же, как и было). Потом, когда клиент делает запрос на профайл, мы делаем запрос в «Фейсбук» за общими друзьями.
Есть диаграммка (детский сад, но уже второй курс):
Клиент делает запрос к нам в PHP. Мы готовим профайл. Делаем запрос в «Фейсбук». С результатом возвращаемся. Никаких проблем нет, но вот так «Фейсбук» отвечал нам в последнюю неделю:
Это время ответа. Можно заметить, что он сильно разнится. Грубо говоря, это 1 секунда. Это полный провал, потому что пользователь будет видеть что-то такое:
Эта реализация нам не подходит – надо что-то менять, потому что наши пользователи в игре «Да-нет» могут проголосовать за 3 профайла за секунду. Скажем так, они очень «скиловые» парни…
Проблема ясна. Решение суперпростое.
Реализация № 3
Мы просто делаем запрос в «Фейсбук» не в этом же запросе на профайл, а в отдельном:
Клиент говорит: дай мне профайл без друзей. Потом говорит: дай мне просто друзей. И в момент, когда профайл полностью получен, мы лезем в «Фейсбук» и отдаём его:
Я здесь упростил – клиент может делать запросы и параллельно. В худшем случае у нас будет выглядеть так: профайл есть, друзья догружаются – такое редко когда случается, потому что мы стараемся пресекать:
PHP
Есть ли в зале кто-то, кто пишет на PHP? Я видел на Mac’ах, что у кого-то «Шторм» открыт, так что давайте честно. А есть те, кто реально любит PHP?
Мы в Badoo очень любим PHP. У нас много инструментов написано под него. Мы знаем, как его готовить, что в нём хорошего и что плохого. Я расскажу, как работает PHP-FPM.
Образно его паттерн работы можно назвать thread pool, но на самом деле у него не треды, а процессы:
Есть Master process, который спаунит n child’ов. Каждый child обрабатывает в единицу времени только одного клиента. Можно видеть, что child’ы 1 и 2 заняты, остальные свободны – если какой-то клиент придёт, он может их обработать. Теперь попробуем это знание положить на нашу последнюю реализацию.
Реализация № 3. PHP-FPM
Представим, что у нас есть 100 таких child’ов на каждый сервер. Имеется 100 серверов, то есть всего на кластер у нас 10 000 child’ов. Представим, что у нас нагрузка 1000 requests/сек.
И в какой-то момент «Фейсбук» начинает тупить – отвечает за 10 секунд. Тогда мы получим, что у нас через 10 секунд все 10 тысяч воркеров будут чем-то заняты.
Внимательный слушатель скажет: что такое 100 воркеров? Валюта? Почему не наспаунить 300 или 7300 воркеров?
Наспаунить-то можно, но вопрос в том, что у нас в основном на кластере CPU-bound нагрузка. Это означает, что нам нужно какие-то более мощные серверы ставить или больше серверов в кластер. Память и Context Switch’es тоже играют роль. А самое главное, всё это умножается тем, что «Фейсбук» отвечает не столько медленно, сколько непредсказуемо медленно.
Тот же график показываю:
Он отвечает секунду за последнюю неделю, но в течение каких-то пары часов начала отвечать за 3 секунды. И вообще, легко может быть такое, что он отвечает за 10 секунд. И поскольку это сеть, мы через половину глобуса ходим в «Фейсбук» за ответом – это может быть вообще что угодно, сколько угодно секунд.
Поэтому вопрос в том, что нам нужно всегда перезакладываться, если мы хотим полностью обеспечить ресурсоёмкость кластера. Получится так, что мы в 10 раз кластер увеличили. При этом основное время используется только 10 % ресурсов. И это всё ради того, чтобы, когда «Фейсбук» тупит 10 минут, мы смогли бы справиться.
Это звучит как-то нерационально. Мы сделали вывод, что так делать не надо:
Badoo существует уже 10 лет. С такой проблемой столкнулись не вчера, не месяц назад и не год назад.
Продолжение будет совсем скоро…
Немного рекламы
Спасибо, что остаётесь с нами. Вам нравятся наши статьи? Хотите видеть больше интересных материалов? Поддержите нас, оформив заказ или порекомендовав знакомым,
Dell R730xd в 2 раза дешевле в дата-центре Equinix Tier IV в Амстердаме? Только у нас
Я расскажу о том, почему наша фича так плохо ложится на PHP и хорошо – на Go, как уговорить всех всё переписать и не показаться сумасшедшим. Ну и, конечно же, как из 19 серверов оставить только 4.
Павел Мурзаков (далее – ПМ): – Меня зовут Паша Мурзаков, я работаю в Badoo. Всем спасибо, что пришли на meet-up. Сегодня будем говорить о том, как 200 строк на Go помогли нам освободить 15 серверов.
Что думают о Badoo и какова роль PHP?
Вообще, когда мы готовим доклады, мы начинаем с того, что Badoo – это большой-большой dating, что у нас много тысяч серверов и вроде highload. Думаю, здесь все об этом знают, и я хочу сменить фокус на то, чтобы рассказать немного о команде и сказать про роль Go в Badoo.
Вообще, в сообществе нас знают так: Badoo – это что-то о PHP. Ребята сидят, шпилят на PHP, потом выкладывают какие-то статьи на «Хабр» о том, как пошпилили. Иногда что-то в open source выкладывают. В общем, всё что-то о PHP…
Когда я готовился к докладу, то зашёл в нашу корпоративную директорию и написал “php” с помощью CTRL+F – получилось 62 результата. Хотел показать, что, если написать “go”, получится 0, но что-то пошло не так:
Надо было писать “golang”, как это обычно бывает.
Вообще, это правда, что PHP в «Баду» очень распространён. Больше всего девелоперов пишет именно на PHP. У нас есть четыре больших отдела, которые пишут только на PHP. Я, например, тимлид в отдел Features – мы тоже пишем только на PHP, решая на самом деле много интересных задач, порой сложных: когда у тебя много клиентов, разные версии, надо поддерживать «Андроид», iOS, мобильный веб, веб, и ещё все эти данные гонять между дата-центрами, и вообще highload…
…каждый запрос, отосланный в MySQL или MemCache, можно случайно завалить, если сделать что-то не так. Поэтому нужно вопросов надо решить. Вопрос о выборе языка перед всеми этими людьми в принципе не стоит:
Это команда PHP в «Баду». Вы спросите: «Какова роль Go в «Баду» и каково его место»?
Go в Badoo
Видите белый пробел (на предыдущем слайде справа)? Это место Go в «Баду» по состоянию на 2012 год. В 2014-м силами этих трёх бойцов (Марко Кевац, Андрей Нигматуллин и Дмитрий Новиков).
написан первый daemon на Go. Они выложили его в продакшн. Об этом рассказывал Тоха Поваров у нас на «кухне», на точь-в-точь таком же митапе два года назад. Тогда был Go 1.3 или 1.4. Ребята написали демона, который хранит уйму объектов в памяти (просто какое-то нереальное количество памяти было занято).
Все помнят истории про Garbage Collector: как пауза там была 30 секунд и всё такое. Доклад очень интересный – всем советую
You must be registered for see links
.Потом тот же Тоха Поваров и Саша Холодов написали несколько других сервисов на Go:
В итоге стало как-то так:
Эти 5 человек – из отдела «Си». В принципе, только они и писали что-то на Go. Но у нас в компании принят прагматичный подход – ориентированность на результат. Поэтому не важно, откуда ты: если ты знаешь, как сделать что-то эффективнее, сэкономить, то – welcome!
К тому же это ж си-шники, а не go-шники! Но пишут на Go. Почему бы PHP-шникам не начать, кстати?.. Попробую ответить на этот вопрос.
Содержание доклада
- Я расскажу о задаче, которую мы решали.
- Расскажу про реализацию на PHP и что в ней не так.
- Как был создан прототип на Go и что с этим получилось.
Задача
Кто-нибудь из зала когда-нибудь пользовался Badoo? Поднимите, пожалуйста, руки… Отстой, мало! Всем установить «Баду», посмотреть. На первый раз прощаю. Расскажу немного о том, как он работает.
Как я уже сказал, мы – dating. Очень многое у нас крутится вокруг профайлов:
Профайл – это аватарка, имя, где работаешь, возраст. Можно пролистать дальше и увидеть одну из составляющих – блок «Друзья». Немного увеличу, чтобы лучше было видно:
Продуктовый смысл, думаю, всем более-менее понятен. Ты смотришь на профайл: видишь, что это не какие-то маньяки-педофилы, а тут вообще твои друзья (на «Баду») и можно этой компании можно доверять…
Из зала: – Вот жена! =)
ПМ: – Вообще, это повышает вовлечённость пользователей: они начинают больше кликать, больше проводить времени, совершать больше действий. И одна из самых важных составляющих – это, что мы можем сподвигнуть пользователя на приглашение других. Мы говорим: «Этот человек ещё не на «Баду», пригласи его».
Я хочу, чтобы вы часть слева «забыли» (friends). Сегодня нас будет интересовать то, что называется in common:
Блок Friends
- Основан на друзьях из «Фейсбука».
- Мы там показываем общих друзей (сегодня нас интересуют только общие).
- Особенно интересные те, кто на «Баду» не зарегистрирован.
Что такое общие друзья, думаю, понятно. На всякий случай быстренько пройдёмся:
Мы – пользователь А, у нас есть друзья Х и Y. Смотрим на пользователя B: у него есть друзья Z и Y. Y – общий друг. Выглядит всё просто, детский сад. Как реализовать:
- Скачиваем заранее из «Фейсбука» список друзей A;
- Скачиваем из «Фейсбука» список друзей B;
- Когда смотрим на них – пересекаем списки и получаем Y;
- Всё отлично – расходимся!
Обновление API (v2.0) «Фейсбука»
Так и работало до того момента, когда «Фейсбук» обновил свой API на версию 2.0:
Когда готовился к докладу, пытался что-нибудь из логов вставить, но они с позором выпилили эту часть истории, поэтому мне придётся вам рассказать на словах.
Раньше, когда мы просили у «Фейсбука» друзей, он возвращал нам тех, кого я называю зарегистрированными: когда человек кликает «Авторизоваться через Facebook», у него спрашивается, даёт ли он доступ к «Фейсбуку»; если дал – мы начинаем считать зарегистрированным через наше приложение.
Мы также могли получить и тех, кто не зарегистрирован.: ели мы просим друзей у какого-нибудь пользователя, мы получаем даже тех, кто вообще ничего о «Баду» не знает. Было отличное время, но потом всё стало хуже…
Реализация № 1 (крах)
«Фейсбук» начал заботиться о приватности и стал выдавать на запросы друзьями только зарегистрированных пользователей. Чтобы это как-то компенсировать, он добавил новый endpoint, который возвращал только общих друзей между двумя.
Это в принципе то, что нам нужно – общие друзья. Он возвращал как зарегистрированных, так и незарегистрированных. Но проблема в том, что нам для получения этого нужно два Facebook id.
Если взять нашу базу, в которой 300 миллионов [пользователей]: чтобы предварительно получить все пересечения, нам нужно сделать 3002 млн запросов, что не очень реалистично. Потом ещё и поддерживать это в актуальном состоянии. Поэтому надо получать друзей в онлайне.
Реализация № 2
Окей. Что надо получать – мы получаем. Скачиваем зарегистрированных (так же, как и было). Потом, когда клиент делает запрос на профайл, мы делаем запрос в «Фейсбук» за общими друзьями.
Есть диаграммка (детский сад, но уже второй курс):
Клиент делает запрос к нам в PHP. Мы готовим профайл. Делаем запрос в «Фейсбук». С результатом возвращаемся. Никаких проблем нет, но вот так «Фейсбук» отвечал нам в последнюю неделю:
Это время ответа. Можно заметить, что он сильно разнится. Грубо говоря, это 1 секунда. Это полный провал, потому что пользователь будет видеть что-то такое:
Эта реализация нам не подходит – надо что-то менять, потому что наши пользователи в игре «Да-нет» могут проголосовать за 3 профайла за секунду. Скажем так, они очень «скиловые» парни…
Проблема ясна. Решение суперпростое.
Реализация № 3
Мы просто делаем запрос в «Фейсбук» не в этом же запросе на профайл, а в отдельном:
Клиент говорит: дай мне профайл без друзей. Потом говорит: дай мне просто друзей. И в момент, когда профайл полностью получен, мы лезем в «Фейсбук» и отдаём его:
Я здесь упростил – клиент может делать запросы и параллельно. В худшем случае у нас будет выглядеть так: профайл есть, друзья догружаются – такое редко когда случается, потому что мы стараемся пресекать:
PHP
Есть ли в зале кто-то, кто пишет на PHP? Я видел на Mac’ах, что у кого-то «Шторм» открыт, так что давайте честно. А есть те, кто реально любит PHP?
Мы в Badoo очень любим PHP. У нас много инструментов написано под него. Мы знаем, как его готовить, что в нём хорошего и что плохого. Я расскажу, как работает PHP-FPM.
Образно его паттерн работы можно назвать thread pool, но на самом деле у него не треды, а процессы:
Есть Master process, который спаунит n child’ов. Каждый child обрабатывает в единицу времени только одного клиента. Можно видеть, что child’ы 1 и 2 заняты, остальные свободны – если какой-то клиент придёт, он может их обработать. Теперь попробуем это знание положить на нашу последнюю реализацию.
Реализация № 3. PHP-FPM
Представим, что у нас есть 100 таких child’ов на каждый сервер. Имеется 100 серверов, то есть всего на кластер у нас 10 000 child’ов. Представим, что у нас нагрузка 1000 requests/сек.
И в какой-то момент «Фейсбук» начинает тупить – отвечает за 10 секунд. Тогда мы получим, что у нас через 10 секунд все 10 тысяч воркеров будут чем-то заняты.
Внимательный слушатель скажет: что такое 100 воркеров? Валюта? Почему не наспаунить 300 или 7300 воркеров?
Наспаунить-то можно, но вопрос в том, что у нас в основном на кластере CPU-bound нагрузка. Это означает, что нам нужно какие-то более мощные серверы ставить или больше серверов в кластер. Память и Context Switch’es тоже играют роль. А самое главное, всё это умножается тем, что «Фейсбук» отвечает не столько медленно, сколько непредсказуемо медленно.
Тот же график показываю:
Он отвечает секунду за последнюю неделю, но в течение каких-то пары часов начала отвечать за 3 секунды. И вообще, легко может быть такое, что он отвечает за 10 секунд. И поскольку это сеть, мы через половину глобуса ходим в «Фейсбук» за ответом – это может быть вообще что угодно, сколько угодно секунд.
Поэтому вопрос в том, что нам нужно всегда перезакладываться, если мы хотим полностью обеспечить ресурсоёмкость кластера. Получится так, что мы в 10 раз кластер увеличили. При этом основное время используется только 10 % ресурсов. И это всё ради того, чтобы, когда «Фейсбук» тупит 10 минут, мы смогли бы справиться.
Это звучит как-то нерационально. Мы сделали вывод, что так делать не надо:
Badoo существует уже 10 лет. С такой проблемой столкнулись не вчера, не месяц назад и не год назад.
Продолжение будет совсем скоро…
Немного рекламы
Спасибо, что остаётесь с нами. Вам нравятся наши статьи? Хотите видеть больше интересных материалов? Поддержите нас, оформив заказ или порекомендовав знакомым,
You must be registered for see links
, уникальный аналог entry-level серверов, который был придуман нами для Вас:
You must be registered for see links
(доступны варианты с RAID1 и RAID10, до 24 ядер и до 40GB DDR4).Dell R730xd в 2 раза дешевле в дата-центре Equinix Tier IV в Амстердаме? Только у нас
You must be registered for see links
в Нидерландах! Dell R420 — 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB — от $99! Читайте о том
You must be registered for see links