133
Как 200 строк на Go освободили 15 серверов Pavel Murzakov

«Как 200 строк на Go помогли нам освободить 15 серверов» – Паша Мурзаков (Badoo)

Embed Size (px)

Citation preview

Как 200 строк на Go освободили 15 серверов

Pavel Murzakov

Badoo — это

✦ 320 млн пользователей

✦ 400 тыс регистраций каждый день

✦ ~3000 серверов

✦ 70 тыс клиентских запросов на бэкенды в секунду

Grigoriy

Igor

Diego

✦ 4 больших отдела: Features, Billing, Back Office, Platform

✦ В каждом по ~10-25 человек (разделены на команды)

✦ Вопроса о выборе языка не встаёт (есть куча других важных проблем!)

PHP в Badoo

PHP в Badoo

Здесь может быть твоё фото

Go в Badoo

Go в Badoo

первый демон на GO в продакшене - 2014 г.

Go в Badoo

http://goo.gl/cGU1gU

Go в Badoo

PHP в Badoo

Go в BadooЗдесь может быть

твоё фото

О чём доклад

О чём доклад

✦ Задача, которую мы решали

О чём доклад

✦ Задача, которую мы решали

✦ Прежняя реализация на PHP

О чём доклад

✦ Задача, которую мы решали

✦ Прежняя реализация на PHP

✦ Релаизация на Go

Задача

Профайл

Блок Friends

Блок Friends

Блок Friends

Блок Friends

✦ Основан на друзьях из Facebook

Блок Friends

✦ Основан на друзьях из Facebook

✦ Общие друзья

Блок Friends

✦ Основан на друзьях из Facebook

✦ Общие друзья

✦ Особенно интересны не зарегистрированные на Badoo

Общие друзья

A

X

Y

Мы

Общие друзья

A B

X

Y

Z

Y

Мы Кого мы смотрим

Общие друзья

A B

X

Y

Z

Y

Мы Кого мы смотрим

Общий друг

Реализация #1

✦ Заранее скачиваем с FB друзей текущего пользователя

A X Y

Реализация #1

✦ Заранее скачиваем с FB друзей текущего пользователя

✦ Заранее скачиваем с FB друзей просматриваемого пользователя

A X Y BZ Y

Реализация #1

✦ Заранее скачиваем с FB друзей текущего пользователя

✦ Заранее скачиваем с FB друзей просматриваемого пользователя

✦ Пересекаем списки в момент показа

A X Y BZ Y

Реализация #1

✦ Заранее скачиваем с FB друзей текущего пользователя

✦ Заранее скачиваем с FB друзей просматриваемого пользователя

✦ Пересекаем списки в момент показа

✦ PROFIT!!!!

A X Y BZ Y

Апдейт FB API v2.0

Апдейт FB API v2.0Было

Friends endpoint

* Зарегистрированные (дали доступ Badoo на FB) * Незарегистрированные

Апдейт FB API v2.0Было Стало

Friends endpoint

* Зарегистрированные * Незарегистрированные

Friends endpoint

* Только зарегистрированные

Апдейт FB API v2.0Было Стало

Friends endpoint

* Зарегистрированные * Незарегистрированные

All Mutual Friends endpoint

* Зарегистрированные * Незарегистрированные * Нужно 2 fb_id

Friends endpoint

* Только зарегистрированные

Реализация #1 — крах

✦ Предварительно скачать всех друзей мы не можем

✦ => Надо получать общих друзей в онлайне

Реализация #2

✦ Предварительно скачиваем списки зарегистрированных друзей

Реализация #2

✦ Предварительно скачиваем списки зарегистрированных друзей

✦ В клиентском запросе на профайл делаем HTTP-запрос в Facebook за общими друзьями

Время на запросы к FB

Время на запросы к FBГрубо ~1 сек

Реализация #2

✦ Предварительно скачиваем списки зарегистрированных друзей

✦ В клиентском запросе на профайл делаем HTTP-запрос в Facebook за общими друзьями

Мы не можем ждать 1с на отрисовку профиля!

Реализация #3

✦ Предварительно скачиваем списки зарегистрированных друзей

✦ В клиентском запросе на профайл отдельном асинхронном запросе делаем HTTP-запрос в Facebook за общими друзьями

PHP

PHP-FPMMaster process

Child process 1

Child process 2

Child process 3

Child process 4

Child process N

Client 1

Client 2

✦ 100 воркеров PHP-FPM на сервер

Реализация #3

✦ 100 воркеров PHP-FPM на сервер

✦ 100 серверов

Реализация #3

✦ 100 воркеров PHP-FPM на сервер

✦ 100 серверов

✦ => 100 * 100 = 10 000 воркеров

Реализация #3

✦ 100 воркеров PHP-FPM на сервер

✦ 100 серверов

✦ => 100 * 100 = 10 000 воркеров

✦ нагрузка 1 000 rps

Реализация #3

✦ 100 воркеров PHP-FPM на сервер

✦ 100 серверов

✦ => 100 * 100 = 10 000 воркеров

✦ нагрузка 1 000 rps

✦ FB “подтупляет" и начинает отвечать по 10 сек

Реализация #3

✦ 100 воркеров PHP-FPM на сервер

✦ 100 серверов

✦ => 100 * 100 = 10 000 воркеров

✦ нагрузка 1 000 rps

✦ FB “подтупляет" и начинает отвечать по 10 сек

✦ через 10 сек 1 000 * 10 = 10 000 => все воркеры будут заняты

Реализация #3

100 воркеров на сервер

300 воркеров на сервер

7300 воркеров на сервер

✦ CPU-bound нагрузка (обычно)

✦ Память

✦ Context Switch’es

✦ Непредсказуемость времени ответа от Facebook (нужно “перезакладываться” в десятки раз)

Воркеры — ограничения

Время на запросы к FBНепредсказуемо

✦ Предварительно скачиваем списки зарегистрированных друзей

✦ В клиентском запросе на профайл отдельном запросе делаем HTTP-запрос в Facebook за общими друзьями

Мы не можем себе позволить долгие запросы!(вообще)

Реализация #3

PHProxyd

Долгий скриптКороткие запросы

Реализация #4

Реализация #4

✦ В коротком клиентском запросе запускаем скрипт в PHProxyd

Реализация #4

✦ В коротком клиентском запросе запускаем скрипт в PHProxyd

✦ Клиент перепроверяет (поллит) результаты

Реализация #4

✦ В коротком клиентском запросе запускаем скрипт в PHProxyd

✦ Клиент перепроверяет (поллит) результаты

✦ В скрипте в PHProxyd делаем HTTP-запрос к FB + небольшая бизнес логика

Реализация #4

✦ В коротком клиентском запросе запускаем скрипт в PHProxyd

✦ Клиент перепроверяет (поллит) результаты

✦ В скрипте в PHProxyd делаем HTTP-запрос к FB + небольшая бизнес логика

Теперь точно PROFIT!!!!!!!

Теперь точно PROFIT!!!!!!!

Реализация #4

60M per day => 1000 rps в пике

Реализация #4

Реализация #4

Реализация #4

Реализация #4

Реализация #4

Реализация #4

Реализация #4

Реализация #4

Реализация #4

Реализация #4

Прага Майами

Реализация #4

Прага Майами

Реализация #4

XHProf

PHProxyd — замена

✦ Создание воркера на новый запрос (phproxyd)

PHProxyd — замена

✦ Создание воркера на новый запрос (phproxyd)

Не работает

PHProxyd — замена

✦ Создание воркера на новый запрос (phproxyd)

✦ Преподготовить заранее кучу воркеров (php-fpm)

PHProxyd — замена

✦ Создание воркера на новый запрос (phproxyd)

✦ Преподготовить заранее кучу воркеров (php-fpm)

Не работает

PHProxyd — замена

✦ Создание воркера на новый запрос (phproxyd)

✦ Преподготовить заранее кучу воркеров (php-fpm)

✦ Что-то асинхронное (nodejs, React PHP)

PHProxyd — замена

✦ Создание воркера на новый запрос (phproxyd)

✦ Преподготовить заранее кучу воркеров (php-fpm)

✦ Что-то асинхронное (nodejs, React PHP)

Мы любим PHP…

PHProxyd — замена

✦ Создание воркера на новый запрос (phproxyd)

✦ Преподготовить заранее кучу воркеров (php-fpm)

✦ Что-то асинхронное (nodejs, React PHP)

… но НЕТ!

Мы любим PHP…

PHProxyd — замена

✦ Создание воркера на новый запрос (phproxyd)

✦ Преподготовить заранее кучу воркеров (php-fpm)

✦ Что-то асинхронное (nodejs, React PHP)

✦ Go = пишешь “синхронный” код, работает асинхронно

PHProxyd — замена

✦ Создание воркера на новый запрос (phproxyd)

✦ Преподготовить заранее кучу воркеров (php-fpm)

✦ Что-то асинхронное (nodejs, React PHP)

✦ Go = пишешь “синхронный” код, работает асинхронно

+ “сложились звёзды”

Реализация на Go

✦ Предварительно скачиваем списки зарегистрированных друзей

✦ В коротком клиентском запросе запускаем скрипт в PHProxyd

✦ Клиент перепроверяет (поллит) результаты

✦ В скрипте в PHProxyd делаем HTTP-запрос к FB + небольшая бизнес логика

Реализация #4 (предыдущая)

✦ Предварительно скачиваем списки зарегистрированных друзей

✦ В коротком клиентском запросе запускаем скрипт в PHProxyd

✦ Клиент перепроверяет (поллит) результаты

✦ В скрипте в PHProxyd делаем HTTP-запрос к FB + небольшая бизнес логика (походы в MySQL, memcache итд)

Реализация #4 (предыдущая)

Реализация #5 — отличия

✦ Принимает на вход “образ” http/https запроса

Реализация #5 — отличия

✦ Принимает на вход “образ” http/https запроса

✦ Отвечает “in progress”, начинает исполнять запрос асинхронно

Реализация #5 — отличия

✦ Принимает на вход “образ” http/https запроса

✦ Отвечает “in progress”, начинает исполнять запрос асинхронно

✦ На повторные реквесты отвечает “in progress” либо данными

Реализация #5 — отличия

✦ Принимает на вход “образ” http/https запроса

✦ Отвечает “in progress”, начинает исполнять запрос асинхронно

✦ На повторные реквесты отвечает “in progress” либо данными

✦ Всю остальную бизнес-логику (базы, мемкеши) оставляем снаружи

Реализация #5

✦ Глобальный map с заданиями и результатами

Реализация #5

✦ Глобальный map с заданиями и результатами

✦ HTTP-сервер, принимает “json” образ запроса, шлёт его в канал

Реализация #5

✦ Глобальный map с заданиями и результатами

✦ HTTP-сервер, принимает “json” образ запроса, шлёт его в канал

✦ N горутин читают из канала, шлют запрос в FB

Реализация #5

✦ Глобальный map с заданиями и результатами

✦ HTTP-сервер, принимает “json” образ запроса, шлёт его в канал

✦ N горутин читают из канала, шлют запрос в FB

✦ После получения результата пишут его в глобальный map

Реализация #5

✦ Глобальный map с заданиями и результатами

✦ HTTP-сервер, принимает “json” образ запроса, шлёт его в канал

✦ N горутин читают из канала, шлют запрос в FB

✦ После получения результата пишут его в глобальный map

✦ Повторный запрос отдаёт результат из этого map

Реализация #5

✦ Глобальный map с заданиями и результатами

✦ HTTP-сервер, принимает “json” образ запроса, шлёт его в канал

✦ N горутин читают из канала, шлют запрос в FB

✦ После получения результата пишут его в глобальный map

✦ Повторный запрос отдаёт результат из этого map

Дублируем продакшен-трафик!!!

Pprof

Keep-Alive

Прага Майами

+ демон на GO + демон на GO

Вписываем в инфраструктуру

Вписываем в инфраструктуру

✦ JSON over HTTP -> “homemade” proto (GPB/JSON over TCP)

Вписываем в инфраструктуру

✦ JSON over HTTP -> “homemade” proto (GPB/JSON over TCP)

✦ Tests

Вписываем в инфраструктуру

✦ JSON over HTTP -> “homemade” proto (GPB/JSON over TCP)

✦ Tests

✦ Build / Deploy

Вписываем в инфраструктуру

✦ JSON over HTTP -> “homemade” proto (GPB/JSON over TCP)

✦ Tests

✦ Build / Deploy

✦ Statistics / monitoring

Было Стало

Заключение

✦ Badoo, Фича Friends

Заключение

✦ Badoo, Фича Friends

✦ PHP, PHP-FPM, долгие запросы, запросы к внешним сервисам

Заключение

✦ Badoo, Фича Friends

✦ PHP, PHP-FPM, долгие запросы, запросы к внешним сервисам

✦ Go: прототип, pprof, keep-alive

Заключение

✦ Изолируйте проблему

Выводы

Выводы

✦ Изолируйте проблему

✦ Делайте прототипы

Выводы

✦ Изолируйте проблему

✦ Делайте прототипы

✦ Не бойтесь экспериментировать

Спасибо!