SlideShare a Scribd company logo
Путь от монолита на PHP к
микросервисам на Scala
Иванов Денис
2gis.ru
2GIS WebAPI
Данные
3
Данные
•  8 стран
•  300 городов
•  50 тыс населенных пунктов
4
Данные
•  8 стран
•  300 городов
•  50 тыс населенных пунктов
•  5 млн организаций
5
Данные
•  8 стран
•  300 городов
•  50 тыс населенных пунктов
•  5 млн организаций
•  50 млн гео-объектов
И еще много всего
6
Нагрузка
7
Нагрузка
•  30 млн. пользователей в месяц
8
Нагрузка
•  30 млн. пользователей в месяц
•  2000 RPS
9
Нагрузка
•  30 млн. пользователей в месяц
•  2000 RPS
•  3 датацентра
10
Одна нода
•  16 CPU
•  16 GB RAM
•  Минимальная нагрузка - 50%
11
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Проблемы
13
Проблемы
•  Долго работают скрипты (95% - 500ms)
14
Проблемы
•  Долго работают скрипты (95% - 500ms)
•  Невозможно параллельно, многопоточно выполнять какие-то задачи
15
Проблемы
•  Долго работают скрипты (95% - 500ms)
•  Невозможно параллельно, многопоточно выполнять какие-то задачи
•  Приложение - один большой кусок, который нужно выкатывать очень
часто и целиком
16
Проблемы
•  Долго работают скрипты (95% - 500ms)
•  Невозможно параллельно, многопоточно выполнять какие-то задачи
•  Приложение - один большой кусок, который нужно выкатывать очень
часто и целиком
•  Кеширование не спасает
17
Проблемы
•  Долго работают скрипты (95% - 500ms)
•  Невозможно параллельно, многопоточно выполнять какие-то задачи
•  Приложение - один большой кусок, который нужно выкатывать очень
часто и целиком
•  Кеширование не спасает
•  Много команд разработчиков, сервисов, интеграций
18
Проблемы
•  Долго работают скрипты (95% - 500ms)
•  Невозможно параллельно, многопоточно выполнять какие-то задачи
•  Приложение - один большой кусок, который нужно выкатывать очень
часто и целиком
•  Кеширование не спасает
•  Много команд разработчиков, сервисов, интеграций
•  Много тестов, которые долго работают
19
Решения
20
Решения
•  Поддерживать существующее и жить дальше
21
Решения
•  Поддерживать существующее и жить дальше
•  Переписать всё нафиг
22
Решения
•  Поддерживать существующее и жить дальше
•  Переписать всё нафиг
•  Подумать и распилить приложение на независимые куски
23
Севисная архитектура (SOA)
— модульный подход к разработке программного обеспечения,
основанный на использовании распределённых, слабо связанных
заменяемых компонентов, оснащённых стандартизированными
интерфейсами для взаимодействия по стандартизированным
протоколам
24
Микросервисная архитектура
• Малый размер
• Тонкое масштабирование
• Быстрый деплой
• Лёгкость тестирования (Мок)
• Любой язык
25
Микросервисная архитектура
• Десятки приложений вместо одного
• Сложность интеграционного тестирования
26
Поехали!
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Shipyard
•  https://shipyard-project.com/
•  Котейнеры
•  Образы
•  Реестры
•  Ноды
•  Логи
•  Консоль
38
Consul
•  https://www.consul.io/
•  Дискаверинг
•  Key-value
•  Проверки
•  DNS
39
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Consul-template
•  https://github.com/hashicorp/consul-template
41
Consul-template
{{range tree "service/redis@east-aws"}}
{{.Key}} {{.Value}}{{end}}
42
Cadvisor
•  https://github.com/google/cadvisor
43
Путь от монолита на PHP к микросервис��м на Scala  / Денис Иванов (2GIS)
Схема работы
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Router
{
"route": "/api/1.0/some/method",
"chain": [
...
]
}
53
Router chain
{ "key": "ms4",
"method": "/api/0.0.1/ms4",
"data": {},
"timeout": 2000,
"maxRetries": 0,
"isVital": true,
"waitFor": ["ms1", "ms2"] }
54
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Базовый образ для контейнера
•  Ubuntu ~500мб, deb-пакеты
59
Базовый образ для контейнера
•  Ubuntu ~500мб, deb-пакеты
•  BusyBox ~50мб, нет пакетов
60
Java SDK
61
Java SDK
•  Gradle
62
Java SDK
•  Gradle
•  Jetty
63
Java SDK
•  Gradle
•  Jetty
•  BoneCP
64
Java SDK
•  Gradle
•  Jetty
•  BoneCP
•  JDBC
65
STOP!
Как распилить?
67
Как распилить?
•  Выделить каждую группу методов в отдельный сервис
68
Как распилить?
•  Выделить каждую группу методов в отдельный сервис
•  Начать с самого мелкого и несвязного сервиса
69
Как распилить?
•  Выделить каждую группу методов в отдельный сервис
•  Начать с самого мелкого и несвязного сервиса
•  Постепенно выделять сервисы, переходя к более крупным
70
Прототип
71
Прототип
•  Тяжелый метод - поисковый запрос, запросы в БД, формирование
2000 маркеров с хешами, куча json-а
72
Прототип
•  Тяжелый метод - поисковый запрос, запросы в БД, формирование
2000 маркеров с хешами, куча json-а
•  PHP, PHP7, Java, Scala
73
Прототип
•  Тяжелый метод - поисковый запрос, запросы в БД, формирование
2000 маркеров с хешами, куча json-а
•  PHP, PHP7, Java, Scala
•  SLA - 95% за 300ms
74
Бенчмарк
75
Бенчмарк
Реализация SLA Смерть
php 30 rps 40 rps
php7 70 rps 80 rps
java 160 rps 180 rps
scala 180 rps 200 rps
76
Scala vs Java
77
Scala vs Java
•  Те же библиотеки + свои
78
Scala vs Java
•  Те же библиотеки + свои
•  Меньше кода, чем на Java
79
Scala vs Java
•  Те же библиотеки + свои
•  Меньше кода, чем на Java
•  Много success-story в микросервисах
80
Scala vs Java
•  Те же библиотеки + свои
•  Меньше кода, чем на Java
•  Много success-story в микросервисах
•  Асинхронность и многопоточность намного проще из коробки +
сторонние библиотеки
81
Scala vs Java
•  Те же библиотеки + свои
•  Меньше кода, чем на Java
•  Много success-story в микросервисах
•  Асинхронность и многопоточность намного проще из коробки +
сторонние библиотеки
•  В компании есть несколько команд, использующих Scala на
продакшене
82
Интеграция
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Путь от монолита на PHP к микросервисам на Scala  / Денис Иванов (2GIS)
Библиотечки
87
Библиотечки
•  Spray
88
Библиотечки
•  Spray
•  Spray json
89
Библиотечки
•  Spray
•  Spray json
•  Typesafe config
90
Библиотечки
•  Spray
•  Spray json
•  Typesafe config
•  Akka
91
Библиотечки
•  Spray
•  Spray json
•  Typesafe config
•  Akka
•  HikariCP
92
Библиотечки
•  Spray
•  Spray json
•  Typesafe config
•  Akka
•  HikariCP
•  JDBC
93
Spray
path("api" / "1.0" / "some" / "method") {
parameters('id.as[String]) { id =>
val response = DoSomeWork(id)
onSuccess(response) { content =>
complete(content)
}
}
}
01.
02.
03.
04.
05.
06.
07.
08.
94
Spray json
case class User(name: String, isOk: Boolean)
implicit val UserFormatter = jsonFormat2(User)
val json = """{"name": "Denis", "isOk": true}"""
val user = json.parseJson.convertTo[User]
01.
02.
03.
04.
05.
06.
07.
95
Typesafe config
databases {
catalog {
host = "127.0.0.1"
port = 5432
timeout = 5s
}
}
01.
02.
03.
04.
05.
06.
07.
96
Инвентарь
97
Инвентарь
•  Scala - основной язык для микросервисов
98
Инвентарь
•  Scala - основной язык для микросервисов
•  TeamCity - сборка и деплой
99
Инвентарь
•  Scala - основной язык для микросервисов
•  TeamCity - сборка и деплой
•  Ansible - деплой
100
Тестирование
101
Тестирование
•  Функциональные и интеграционные тесты на ваш продукт, которые у
вас должны быть
102
Тестирование
•  Функциональные и интеграционные тесты на ваш продукт, которые у
вас должны быть
•  Для нагрузки - yandex tank, gatling
103
Тестирование
•  Функциональные и интеграционные тесты на ваш продукт, которые у
вас должны быть
•  Для нагрузки - yandex tank, gatling
•  Для реверс-инжиниринга - gor
104
Тестирование
•  Функциональные и интеграционные тесты на ваш продукт, которые у
вас должны быть
•  Для нагрузки - yandex tank, gatling
•  Для реверс-инжиниринга - gor
•  Простой скрипт, кидающий запрос на 2 хоста и делающий diff
105
Стало
106
Стало
•  Сборка - 2 минуты
107
Стало
•  Сборка - 2 минуты
•  Тесты (с нагрузкой) - 5-10 минут
108
Стало
•  Сборка - 2 минуты
•  Тесты (с нагрузкой) - 5-10 минут
•  Деплой - 5 минут
109
Стало
•  Сборка - 2 минуты
•  Тесты (с нагрузкой) - 5-10 минут
•  Деплой - 5 минут
•  Серверов - 6 вместо 18 (по 2 в каждом ДЦ)
110
Одна нода
•  4 CPU
•  4 GB RAM
•  Средняя нагрузка - 5%
•  Максимальная нагрузка - 30%
111
Грабли
112
Грабли
•  CORS
113
Грабли
•  CORS
•  gzip
114
Что дальше?
115
Что дальше?
•  Продолжать распиливать сервисы
116
Что дальше?
•  Продолжать распиливать сервисы
•  Двигаться к поставленной цели (к "идеалу")
117
Итоги
118
Итоги
•  Поменьше велосипедов
119
Итоги
•  Поменьше велосипедов
•  Ставьте себе четкие, достижимые цели в короткий срок
120
Итоги
•  Поменьше велосипедов
•  Ставьте себе четкие, достижимые цели в короткий срок
•  Делайте задачи итеративно
121
Итоги
•  Поменьше велосипедов
•  Ставьте себе четкие, достижимые цели в короткий срок
•  Делайте задачи итеративно
•  Решайте проблемы по мере из возникновения
122
Итоги
•  Поменьше велосипедов
•  Ставьте себе четкие, достижимые цели в короткий срок
•  Делайте задачи итеративно
•  Решайте проблемы по мере из возникновения
•  Преждевременная оптимизация - зло
123
Вопросы?
Иванов Денис
dv.ivanov@2gis.ru
124

More Related Content

Путь от монолита на PHP к микросервисам на Scala / Денис Иванов (2GIS)