4. Мы тоже приняли в этом участие
• Существующее решение одной из служб такси не справлялось с
ростом нагрузки
• За 4 месяца надо было понять как работает существующая
система
• Разработать новый сервис тарификатора
• Реализовать набор новых требований
• Выполнить интеграцию с существующими системами
5. Проблемы существовавшего решения
• Биллинг, реализованный в виде хранимок в БД
• Монолитные функции, которые умеют слишком многое
• Отсутствие документации
• Существующие нагрузки все чаще приводили к блокировкам в БД
• Необходимость развивать систему
6. Наши задачи
• Разработка системы тарифов и бизнес правил для тарификации
услуг такси
• Предоставление API для управления тарифами из панели
администратора
• Интеграция с существующей структурой БД
• Поддержка популярных БД (SqlServer, MySQL, PgSQL)
• Обработка потока 60 тыс. заказов в сутки
7. Что мы использовали
• Java Runtime 1.6.x -> 1.7.x
• Java EE 6.0 Glassfish 3.x
• JAX-WS (Metro)
• EJB 3.1
• JPA 2.0 (EclipseLink)
• Quartz Scheduler 2.x
• SqlServer 2005, PostgreSQL
11. Особенности архитектуры
• Приложение разделено на две группы сервисов
• Управления доменной областью / базой даных
• Выполнения задач и бизнес логики
• Все действия оператора сводятся только к управлению
справочниками в БД
• При старте приложения планируются необходимые задачи
• Вся бизнес логика выполняется отложенно / асинхронно через
планировщик
12. Сервер приложений Java EE
• Самые популярные Java EE сервера приложений
• Jboss / Wildfly
• Glassfish
• Tomcat + TomEE
• WebLogic / WebSphere
• EJB Interceptor
• Реализация логгирования на базе Interceptor – стоит примерно 15-20%
производительности
• Glassfish как сервер приложений
• Это Reference Implementation для Java EE и не более
13. Реализация API
• REST или SOAP
• Современное поколение выбирает REST, мы выбрали SOAP
• Автоматическая генерация API
• Аннотации наше все
• Не все так хорошо
• Генерация документации по API на базе комментариев
• Безопасность
14. Работа с БД
• JPA как абстракция для БД
• Минимум кода для управления сущностями
• Позволило легко добавить поддержку PostgreSQL
• Версионирование БД
• Общие таблицы в БД
• Отсутствие или нарушение constraints между сущностями БД
• Мусор в таблицах
• Multitenancy с JPA уже возможно
15. Асинхронная обработка задач
• Популярный паттерн проектирования
• Простейшая реализация – отдельный поток, который вычитывает
задачи из БД
• Обычно реализуют на базе Message Queue
• Мы использовали планировщик Quartz и очередь задач
в БД
16. Асинхронная обработка задач
• Плюсы
• Упрощение масштабирования системы
• Выделение логики обработки задач в отдельные компоненты
• Минусы
• Зависимости между задачами
• Необходимы средства мониторинга очередей
• Мы не знаем когда задача будет выполнена
• Восстановление работы после простоя
17. Производительность
• Плановая нагрузка легко обрабатывается существующей
архитектурой
• Основное время тратится на работу с БД
• После анализа работы системы часть таблиц БД можно
кэшировать
• JProfiler для анализа работы системы и анализа
производительности
• Лишние обращения к БД (повторные чтения)
• Чтение из БД неизменных данных (возможность кэширования)
20. Впечатления после внедрения
• В первые недели работы мы узнали сразу несколько кейсов, когда
заказчик хотел одно, а мы реализовали другое
• Без доступа к БД разбираться в проблемах намного сложнее,
поэтому активно дополняли логирование событий
• Поиск виноватых в связке Админка - Billing. Все кивали друг на
друга, пришлось логгировать большинство входящих запросов (а
еще SOAP)
• Сторонние системы не соблюдали форматы обмена данными.
21. Чем мы гордимся
• Система работает в режиме 24 * 7 без сбоев и замечаний
• Система логирования предоставляет достаточно информации для
объяснения 98% ситуаций
• API возваращает понятное описание ошибок, поэтому оператор
может сам исправить некорректные данные
• Валидация данных не позволяет создавать некорректные
сущности
• Мы смогли добиться этого без помощи тестировщиков
22. Немного статистики
100%
80%
60%
40%
20%
0%
Задачи 2012-2014
2012 2013 2014
Доработки Ошибки Консультации
23. Планы на будущее
• Переход на SaaS модель
• Поддержка Multitenancy
• Использование REST для public API
• Использование SoapUI для TDD
• Оптимизация слоя работы с БД
24. Советы
• Пишите подробные логи, которые позволят вам без доступа к
production стенду понять что происходило в системе
• Очень аккуратно работайте с чужими таблицами
• Кэширование сущностей БД позволят выиграть 30%
производительности, но может быть источником проблем
• Избегайте зависимостей между асинхронными задачами
• Автоматизируйте тестирование с самого начала
• Не публикуйте внутреннее API
25. Спасибо за внимание
Email: pavel_vinogradov@epam.com
Twitter: pavelvinogradov
Editor's Notes
В последние несколько лет службы такси растут быстрыми темпами. Причем вслед за региональными операторами в игру вступили агрегаторы типа Яндекс Такси, а в последний год у всех на слуху стартап Uber.
Кто НЕ слышал про Uber? А кто им уже пользовался?
Ижевск активно участвует в этой движухе. Мне известно как минимум 5 компаний в Ижевске, который занимаются разработкой и внедрением сервисов автоматизации таксопарков. Я со своей командой тоже не остался в стороне, в последние 3 года мы приняли активное участие в разработке одного из коробочных решений, которое сейчас предлагается на рынке.
Заказчика я вам сегодня не назову, т.к. считаю это не важным моментом. Мой доклад будет о практических вопросах разработки тарификатора, а не маркетинговой рекламе превосходства нашего продукта над конкурентами.
Привяза к конкретной СУБД
Сложна в поддержке и отладке
Признайтесь, кто из вас писал биллинг на хранимках?
Все действия оператора сводятся только к управлению справочниками в БД
Перевод водителя с одного тарифа на другой
Постановка на смену / Блокировка / Увольнение
Регистрация платежа
Если возникают зависимые задачи
Списать комиссию за выполненные заказы до смены тарифа
В случае простоев системы
Пропуск задачи запланированной на 00:00
Реализация нового функционала как новой задачи планировщика
Возможность Feature Toggling
Изоляция бизнес логики новой фичи от остальных задач
Контроль ресурсов / приоритетов каждой из задач
Management API отдельный компонент системы
Использование SoapUI для интеграционного тестирования
Для каждой фичи создается тест со своим миром (тариф, водитель, заказы)
Реализуются шаги в соответствии с бизнес-сценарием
Автоматическая генерация stubs для всего API на базе WSDL
Тесты не зависят от низкоуровневой реализации и привязаны только к Public API
Для этого пришлось открыть доступ к некоторому служебному API
Попробуйте решать проблемы без доступа к БД
Не верьте описанию полей в документации
Очень аккуратно работайте с асинхронными задачами, избегайте зависимостей
Автоматизированное тестирование (неважно модульное или интеграционное) сохранит вам огромное количество времени
Никогда не включайте в поставку эмуляторы, тестовое API, недоделанный функционал