Upload
andrew-minkin
View
11.371
Download
6
Embed Size (px)
Citation preview
Как строить архитектуру для отказоустойчивой службы таксиМинкин АндрейNambaTaxi
Частник
Диспетчерская служба
Uber
О нас• 300k довольных
клиентов • 600+ водителей на
линии• Не менее 8k заказов в
сутки
Суточная нагрузка
5:00 6:00 7:00 8:00 9:00 10:00 11:00 12:00 13:00 14:00 15:00 16:00 17:00 18:00 19:00 20:00 21:00 22:00 23:00 0:000
500
1000
1500
2000
2500
3000
3500
4000
Запросов в секунду
AVG response time on backends• Водители - 20 ms• Операторы - 2.5 ms
О чем доклад• Как строили
архитектуру• Как делали WebRTC
Как все начиналось?
Workflow на софте поставщика
Клиент Оператор Заказ
Водитель Принял заказ
Приехал на место
Забрал клиента
Привез клиента
Менеджер видит отчет
Фичи софта поставщика• Call-центр• SMS оповещения• Автоматизация workflow• Много китайских
навигаторов (Shturmann, A500)
Оповещения по SMS• Водитель принял заказ
на исполнение• Водитель приехал на
место
Почему отказались• Нестабильная работа• Долгий даунтайм• Перестал
удовлетворять нашим требованиям роста и бизнеса
Требования к системе• Минимум изменений в
workflow водителей и операторов
• Гибкость разработки и добавления новых фич
• Водители должны остаться на навигаторах на WinCE
• Заложить поддержку Android для водителей
• Реалтайм в операторской
• Работающая телефония• Возможность сразу
перейти на свое решение
Ограничения• Цена на мобильный
интернет• Серверные ресурсы• Маленькая команда• Результат в
кратчайшие сроки
Проектирование Web
Ядро
Операторы Водители
Менеджеры Платежи
Что выбрали• Python/Django для Ядра• Redis для Publish/Subscribe• Node.js – событийный реалтайм
в операторской• Twisted – socket server для
водителей• Ruby для SMS• WebRTC для телефонии
Почему так?• Ruby -> Ruby-smpp для
sms• Node.js -> socket.io для
реалтайма• Twisted – потому что
клевый
Зачем sip через WebRTC• Open Source решение• Нет привязки к железу и ОС• Экономия рабочих мест в
офисе• Экономия на
коммутационном оборудовании
Реализация
Django
Менеджеры Операторы Водители Платежи
Водители
Навигатор Twisted Django+Redis
TwistedНавигатор
SMS оповещения
Twisted Django
Ruby SMSSMSC
SMS заказы
Клиент SMS SMSC
Ruby SMSDjango
Операторская
Операторы
Заказы Телефония
Операторская. Заказы
МенеджерыDjango
Excel Browser
Percona
Percona 5.5 HA• Master-slave replication• Virtual IP for Master
Первая проверка• Проверили продукт в
реальных условиях• Стабилизировали
WebRTC
Перевод бизнеса на свое решение
Задача по переносу• Перенести 2 000
водителей• Перенести все
короткие смс номера• Перенести телефонию• Перенести 20
операторов
• 7 дней• Техническая команда• Начальник
транспортного отдела• Начальник call центра
Как выглядела операторская
Nginx
Ядро Node.js
Как выглядели водители
TCP proxy Twisted
Первые глаза• Sentry• Nagios• Collectd
День 1
20
20
20
20
5
4
2
Операторы
День 7
День 6
День 5
День 4
День 3
День 2
День 1
2000
2000
1500
1000
500
250
100
Водители
День 2
20
20
20
20
5
4
2
Операторы
День 7
День 6
День 5
День 4
День 3
День 2
День 1
2000
2000
1500
1000
500
250
100
Водители
День 3
20
20
20
20
5
4
2
Операторы
День 7
День 6
День 5
День 4
День 3
День 2
День 1
2000
2000
1500
1000
500
250
100
Водители
День 4
20
20
20
20
5
4
2
Операторы
День 7
День 6
День 5
День 4
День 3
День 2
День 1
2000
2000
1500
1000
500
250
100
Водители
Performance проблемы водителей• Некоторые водители не
могут взять заказ• У некоторых водителей
не обновляется список заказов
Причина• Socket timeout на
навигаторах• Twisted синхронный
РешениеTCP proxy
Twisted1 Twisted2
День 5
20
20
20
20
5
4
2
Операторы
День 7
День 6
День 5
День 4
День 3
День 2
День 1
2000
2000
1500
1000
500
250
100
Водители
Проблемы операторов• Периодически не
обновляется список заказов
• Некоторые события не доходят до операторов
Причина• Node.js не справляется
Решение
Nginx
Node.js
node1 node2
Ядро
День 6
20
20
20
20
5
4
2
Операторы
День 7
День 6
День 5
День 4
День 3
День 2
День 1
2000
2000
1500
1000
500
250
100
Водители
День 6. Проблемы• У некоторых водителей
не обновляется список заказов
• У операторов медленно оформляются заказы
Причина• Django не успевает
отвечать на запросы
Выход
Общее решение
Nginx
Node.js
node1 node2
Ядро
Django1 Django2
Первая балансировка
Но это не все
Series10
50
100
150
200
250
300
Node.js Bandwidth
Выход• Socket.io -> surepost-
socket.io
День 7• Все стабилизировалось
Итог• -8% заказов за время
переезда• Время подачи машины
сократилось с 8 до 5 минут
Ошибки на начальном этапе• Twisted синхронный• Вместо Nodejs erlang
или Python• Нагрузочные тесты не
из реального мира
Начался рост заказов
0
1000
2000
3000
4000
5000
6000
7000
8000
9000
Mobile Apps
Архитектура после
Nginx
Ядро Node.js Apps
Наблюдаем рост
Series10
1000
2000
3000
4000
5000
6000
7000
8000
9000
Chart Title
Заказы Пользователи приложений
1 2 3 4 5 6 7 8 9 10 11 120
100
200
300
400
500
600
700
800
Водители на линии
Проблемы роста• Подводит Синхронный
Twisted нас
План действий• Используем Twisted
правильно• Сделать равномерную
балансировку• Построить HA под
шумок
При этом• 1 сервер загруженнее
другого• 1 точка входа для
операторов, клиентов
Series10
10
20
30
40
50
60
70
80
90
100
Chart Title
s1 s2
Схема водителей на этот момент
Haproxy
Twisted1
Django1
Twisted2
Django2
Nginx
Ядро Node.js Apps
Nginx• 2 nginx с keepalived• DNS round robin
HA для Nginx
Разделяем workflow
Nginx
workflow
Django1
Master DB
Django2
reports
Django3
Slave Db
Django4
Правильный Twisted• Async HTTP• Async Redis• Random upstream
План
Twisted
nginx nginx
Итог
Что еще не HA• СМС демоны• Redis
СМС демоны
Django SMSDaemon
SMSC
Минусы• Много коннектов по TCP• Нет масштабируемости
Выход• Redis pub/sub
СМС демоны
Django Redis
SMS DaemonSMSC
Профит• Persistent connect к redis• Publish/Subscribe • Масштабируемость
Redis Failover
Percona 5.6 HA• Master-Master (GTID)• Virtual IP for Master• Virtual IP for Slave• Master – write• Slave – read for reports
Что получилось • Высоко
масштабируемый продукт
• Отказоуйстойчивый• С sip без flash
Как сделали webrtc стабильным
Первая реализацияsipML5
webrtc2sip
Провайдер
Минусы• Не можем подключать
больше номеров• Не можем
балансировать исходящую связь
• 1 номер = 1 webrtc2sip
Asterisk 11.5
sipml5 asterisk
GSM шлюз/провайдеры
Плюсы• Можем подключать
новые номера• Можем балансировать
нагрузку• Получили полноценную
АТС
Проблемы• Срывается звонок • Нет гудков • Нет правильной работы со
статусами прогресса SIP• Долгое время бриджа
аудио• Входящий звонок мог
крашнуть asterisk
Asterisk 11.6
sipml asterisk
GSM шлюз/провайдеры
Плюсы• Звонок не срывается• Asterisk не падает• Audio бриджуется
отлично
Минусы• Нет гудков и
служебных ответов• Нет правильной работы
со статусами прогресса• Одностороннее аудио
Sipml+webrtc2sip
sipml webrtc2sip
asteriskGSM шлюз/провайдеры
Плюсы• Статусы работают• Есть гудки• Нет проблем с
односторонним аудио• Все работает
Минусы• Рандомно крашится
Почему не починили• Нет документации• Плохое качество кода
FreeSWITCH
sipml5 FreeSWITCH
GSM шлюз/провайдеры
Плюсы• Стабильно работает• Поддерживает webrtc
полностью• Все работает, но…
Минусы• Нет гудков и
служебных ответов от операторов
Решение• FreeSWITCH берет
трубку при исходящем звонке
Проблемы• Звонок не больше 2х
минут из-за SipML5
Выход• Sipml5 -> JSSIP
Итог
jssip FreeSWITCH
GSM шлюз/провайдеры
HA sip
Начальная нагрузка• До 25k звонков в сутки
Итоги проделанной работы• Сократили количество
звонков с 25к до 12к за счет автоматизации процессов и мобильных приложений
• Сократили 30% операторов• Увеличили количество
заказов на 40%
Подводные камни• WebRTC• Отказоустойчивость• Concurrency
Борьба с Concurrency• Redis -> setnx• Percona -> Atomic
transactions + select … for update
Какие ошибки?• Не учли быстрого роста• Не было хорошей
балансировки
Наши глаза• Nagios -> Sensu• Collectd -> Graphite• Newrelic -> Node.js• Cprofilemiddleware ->
Django• Opbeat -> Django
Учебные тревоги• До 2х раз в неделю
проверяем отказоустойчивость любого сервиса
• До 2х раз в месяц перезагружаем любой физический сервер
Выводы• Архитектура должна
подстраиваться под бизнес процессы
• Не надо бояться перестраивать архитектуру проекта
Выводы• Разные workflow
большой системы не должны влиять друг на друга
• Хорошая архитектура растет вместе с вами
Спасибо• Skype: gen1us2k• Habr: @gen1us2k