Analysis of the architecture of the game server on Haskell. From a high-level model to code features - transactional memory, immutable data structures, actors, queues, parallel and concurrent computing. The model of dynamic scaling, optimization, solved problems and trade-offs.
Reasons for choosing Haskell
What technologies were considered and why they were not used (no spoilers)
Full stack of used technologies and their highload potential
Universal design patterns
2. Точка отсчета
• Когда влияние ошибки и неэффективного решения имеет значительное влияние на
бизнес
• App - код для дефолтной инфраструктуры, Highload App - код и особая
инфраструктура
• Паттерны универсальны, решение уникально
3. Выбор технологий
• Зависит от бизнес задачи
• Чем каждая технология плоха в контексте задачи
• Маппинг технологии на бизнес домен, модель данных и процессы
• Оптимизация расходов и tradeoff в пользу стратегических целей
4. Пространство изменяемых данных
• Рост числа решений с единым пространсвом данных
• История - nginx, haproxy, varnish etc
• Обработка своих данных пользователя vs участие в большой модели данных
5. Архитектурные паттерны
• Паттерн зависит от контекста
• Понимание контекста - зависит от опыта
• Паттерны эффективной разработки vs эффективной работы приложения
• Composability of patterns
6. Прожигаете регистры или ленты
• Наличие пользователя, ждущего ответа прямо сейчас
• Многократный проход код через малый объем данных
• Минимальный процессинг растущих данных + фоновая обработка
7. Горизонт сложности
• Когда сам факт внедрения HL ориентированной технологии не решает
• Когда нюансы начинают иметь решающее значение
• У решения есть границы. Их понимали создатели решения, их раздвигали
commiting пользователи
8. Базовые инструменты - ранее
передовые решения
• Они редко становятся проще в использовании
• Их возраст не делает их менее нужными
• Load Balancing, Replication, Sharding
9. Cache - от простого к сложному
• Dogpile protection
• Cache invalidation
• in app, memcached, redis >> С*
10. Умение расставаться с (любимыми)
технологиями
• Когда node.js уже не работает
• C10K раньше и node.js сейчас. HL - всегда решения on the edge
• Решаемо: Code complexity > TypeScript
• Не решаемо: Single thread, CPU, MEM
• Время для Erlang, Go, C++ etc
11. Клин клином - когда нужны
сложные решения
• Но требуют серьезных архитектурных изменений
• Компоновка блоков vs структура блоков
• Performant код, входы и выходы, side effects, связность с другими блоками -
структура блока
• Определенная внутрення структура позволяет использовать готовые highload
элементы или инфраструктуру
12. Коммуникация - интерфейсы,
протоколы и шина
• Внутренние между модулями или микросервисами, Actor Model
• Неожиданные места: SCSI, IDE, SATA, Thunderbolt, сеть
• Compression
• ProtoBuf
• Dedup, ZFS
13. CPU Time
• Эффективная работа (два байта обновить) и накладные расходы
• Respect CPU - ресайз картинок от оригинала, от промежуточных
• Close to hardware. время операций от L1 кеша до сети
• Важно ли большое O - зависит от объема трансформации данных + нужно ли это
дать в ответ (а не рассчитать на фоне)
• Parallel, Concurrent
• Граф выполнения, параллельные и последовательные блоки
15. Данные
• Структура данных определит процессы обработки
• Универсальные процессы могут работать только с метаданными
• Степень надежности хранения
• Layers of persistency
• Место операций над данными между пространством кода и БД
• Модификация (программа трансформации данных). «Причинные» данные и расчетные
• Materialized view
16. CQRS
• Command Query Responsibility Segregation
• Зачем?!
• Если бы я знал почему, я бы..
17. Очереди
• Low level pattern for high level Actor Model
• Решение проблемы числа CPU. С приоритетами или без
• TCP request queue, throttling, rate limiting, load balancing
• Fast in mem, message queue (расширяет модель данных)
• External MQ
18. Actor Model
• Runtime. Akka, Cloud Haskell, Erlang OTP Platform
• Модель актеров -> immutable data
• Supervisor, let it fail
• vs PubSub
19. Event Sourcing
• vs CRUD
• Накладывает серьезные изменения на app model & logic
• Reverse TX
23. Гибкость мышления
• Кеш в проце, в коде, кеш как tcp сервис, SAAS
• Транзакции в базе, в коде (stm, mnesia), в cpu
24. Почему на примере игрового сервера
• Требования пользователей к latency и uptime часто выше, чем в бизнес
приложениях
• Но часто там в одном проекте стоит более широкий набор проблем
25. Почему Haskell
• CPU / MEM / Time
• Мультипарадигменность
• Скорость разработки
• Управление качеством ПО
• Многие языки и так более 10 лет переносят конструкции, базовые для Haskell
26. Какие технологии рассматривались
• С++: manual locking. Same as Cocos MVP / Unreal logic
• Erlang: inefficient CPU
• Scala, Java: inefficient MEM, almost world stop GC
• JavaScript: very inefficient CPU, limited MEM, single thread
• F#: can mix C# from Unity. Network code is Slow/Unstable vs Haskell
27. Разбор архитектуры игрового сервера
• Auth
• Auto register, login, change client
• Client need update for new game rules
• Metagame
• Match make
• Select server
• Save match results
• Championship logic
• Payments
• Analytics
• User stats
• Gameplay
• Generate “fair buffer”
• Pass turns
• Hi-Res timeouts
• Hide choice, process consequences
• Chaos gems map to random energy