SlideShare a Scribd company logo
Как я перестал бояться и полюбил
асинхронный код
JUG@VRN, 2014
Гребенников Роман,
Sociohub
Содержание
● Модель акторов:
o зачем она нужна;
o что это такое;
o Akka 2 и Scala;
o какие возможности даёт.
● Пример системы:
o система сбора и парсинга данных.
● Личный опыт:
o типичные ошибки;
o подводные камни;
o производительность;
o перспективы.
Free lunch is over
Одно ядро, один поток - путь в никуда:
[1]: http://www.gotw.ca/publications/concurrency-ddj.htm
[2]: PassMark, http://www.cpubenchmark.net
Free lunch is over
Одно ядро, один поток - путь в никуда:
[1]: http://www.gotw.ca/publications/concurrency-ddj.htm
[2]: PassMark, http://www.cpubenchmark.net
Concurrency vs Parallelism
[1]: Rob Pike: Concurrency is not Parallelism (it's better!), http://concur.rspace.googlecode.com/hg/talk/concur.html
Concurrency vs Parallelism
Parallel programming
строго одновременное исполнение
нескольких задач
[1]: Rob Pike: Concurrency is not Parallelism (it's better!), http://concur.rspace.googlecode.com/hg/talk/concur.html
Concurrency vs Parallelism
Concurrent programming
композиция независимо
выполняющихся задач
(не обязательно параллельно)
Parallel programming
строго одновременное исполнение
нескольких задач
[1]: Rob Pike: Concurrency is not Parallelism (it's better!), http://concur.rspace.googlecode.com/hg/talk/concur.html
Concurrency vs Parallelism
Concurrent programming
композиция независимо
выполняющихся задач
(не обязательно параллельно)
Parallel programming
строго одновременное исполнение
нескольких задач
[1]: Rob Pike: Concurrency is not Parallelism (it's better!), http://concur.rspace.googlecode.com/hg/talk/concur.html
Всё это сложно
Корень проблемы
Корень проблемы
Shared mutable state
Корень проблемы
Shared mutable state
и его друзья
Корень проблемы
Shared mutable state
и его друзья
Зачем нужны акторы?
Зачем нужны акторы?
● Чтобы перестать думать о плохом:
o блокировки, race conditions, дедлоки;
o shared state, state visibility;
o потоки, concurrent collections и т.д.
Зачем нужны акторы?
● Чтобы перестать думать о плохом:
o блокировки, race conditions, дедлоки;
o shared state, state visibility;
o потоки, concurrent collections и т.д.
● И начать думать о хорошем:
o single execution flow:
актор работает последовательно;
o слабая связанность всех компонентов:
легко тестировать;
o асинхронность:
больше никакого Await;
o нет никакого shared mutable state.
Зачем нужны акторы?
● Чтобы перестать думать о плохом:
o блокировки, race conditions, дедлоки;
o shared state, state visibility;
o потоки, concurrent collections и т.д.
● Легкость масштабирования:
o часть платформы, не надо ничего изобретать;
o есть восстановление после сбоев: “let it crash”.
● И начать думать о хорошем:
o single execution flow:
актор работает последовательно;
o слабая связанность всех компонентов:
легко тестировать;
o асинхронность:
больше никакого Await;
o нет никакого shared mutable state.
Модель акторов
● Придумана в 1972 году, до сих пор актуальна [1]
● Стала популярной благодаря Erlang
● Всё - актор, даже небо, даже звезды
[1]: http://letitcrash.com/post/20964174345/carl-hewitt-explains-the-essence-of-the-actor
Модель акторов
● Придумана в 1972 году, до сих пор актуальна [1]
● Стала популярной благодаря Erlang
● Всё - актор, даже небо, даже звезды
[1]: http://letitcrash.com/post/20964174345/carl-hewitt-explains-the-essence-of-the-actor
● Акторы:
o функционируют параллельно;
o асинхронно обмениваются сообщениями;
o имеют персональный адрес и почтовый ящик.
● при получении сообщения можно:
o отправить новое сообщение другим акторам;
o создать новых акторов;
o изменить свое поведение для следующего сообщения.
● Напоминает Email
Akka
● Jonas Bonér
o Java champion;
o Terracotta JVM clustering,
JRockit JVM, AspectWerkz AOP,
Eclipse AspectJ.
● Ресурсы
o http://akka.io/docs/
o http://letitcrash.com/
● Код
o http://github.com/akka/akka
o Apache 2.0 License
o Scala API, Java API
Áhkká (Lule Sami: "old woman")
Actor внутри
ActorRef
Actor
Почтовый ящик
Указывает на актора.
Умеет класть сообщения в ящик.
Ваш код тут
Actor внутри
ActorRef
Actor
Почтовый ящик
Указывает на актора.
Умеет класть сообщения в ящик.
Ваш код тут
Берет сообщения по-одному.
Что-то с ними делает.
Единственный способ взаимодействия -
отправка сообщения. Во внутренности
актора доступа нет ни у кого.
Создание актора
Почтовые ящики
Пути как в файловой системе:
● akka://system/user/foo/bar
● akka.tcp://system@srv.example.com/user/foo/bar
Почтовые ящики
Пути как в файловой системе:
● akka://system/user/foo/bar
● akka.tcp://system@srv.example.com/user/foo/bar
Выбор актора:
● каждый актор знает себя, родителя и детей;
● акторов можно выбирать по пути из ActorRegistry:
Почтовые ящики
Пути как в файловой системе:
● akka://system/user/foo/bar
● akka.tcp://system@srv.example.com/user/foo/bar
Выбор актора:
● каждый актор знает себя, родителя и детей;
● акторов можно выбирать по пути из ActorRegistry:
Типы:
● UnboundedMailbox;
● BoundedMailbox;
● UnboundedPriorityMailbox;
● BoundedPriorityMailbox.
Диспетчеры
● Актор != поток
поток 1
поток 2
A1
A2
A4 A1
A1 A2
A4 A4A1
A3
Диспетчеры
● Актор != поток
поток 1
поток 2
A1
A2
A4 A1
A1 A2
A4 A4A1
A3
● Каждый актор жив, только когда работает
● В остальное время он освобождает поток
Диспетчеры
● Актор != поток
поток 1
поток 2
A1
A2
A4 A1
A1 A2
A4 A4A1
A3
● Каждый актор жив, только когда работает
● В остальное время он освобождает поток
● Диспетчер занимается раскладыванием акторов
по потокам:
o Dispatcher;
o PinnedDispatcher;
o BalancingDispatcher;
o CallingThreadDispatcher.
Диспетчеры
● Актор != поток
поток 1
поток 2
A1
A2
A4 A1
A1 A2
A4 A4A1
A3
● Каждый актор жив, только когда работает
● В остальное время он освобождает поток
● Диспетчер занимается раскладыванием акторов
по потокам:
o Dispatcher;
o PinnedDispatcher;
o BalancingDispatcher;
o CallingThreadDispatcher.
● Для непосредственного исполнения:
o fork-join-executor;
o thread-pool-executor.
Падший актор
● Код иногда ломается
● Как жить дальше и что делать?
ActorRef
Parent
Actor
MessageBox
Падший актор
● Код иногда ломается
● Как жить дальше и что делать?
ActorRef
Parent
Actor
MessageBox
Падший актор
● Код иногда ломается
● Как жить дальше и что делать?
ActorRef
Parent
Падший актор
● Код иногда ломается
● Как жить дальше и что делать?
ActorRef
Parent
deadLetters
Могильник для
потерянных сообщений
Падший актор
● Код иногда ломается
● Как жить дальше и что делать?
ActorRef
Parent
deadLetters
Могильник для
потерянных сообщений
● И что?
Supervision
● Можно делать иерархии акторов
● Каждый актор в ответе за своих детей
● Упавшего ребенка можно:
Supervision
● Можно делать иерархии акторов
● Каждый актор в ответе за своих детей
● Упавшего ребенка можно:
● Stop: остановить;
● Restart: перезапустить;
● Continue: оставить полу-лежачим;
● Escalate: передать обработку выше.
Supervision
● Можно делать иерархии акторов
● Каждый актор в ответе за своих детей
● Упавшего ребенка можно:
● Stop: остановить;
● Restart: перезапустить;
● Continue: оставить полу-лежачим;
● Escalate: передать обработку выше.
● Решение рекурсивно
● Есть хуки preStart, preRestart, postStop, etc.
Supervision
● Можно делать иерархии акторов
● Каждый актор в ответе за своих детей
● Упавшего ребенка можно:
● Stop: остановить;
● Restart: перезапустить;
● Continue: оставить полу-лежачим;
● Escalate: передать обработку выше.
● Решение рекурсивно
● Есть хуки preStart, preRestart, postStop, etc.
Akka remoting/cluster
● Волшебный ActorRef: может указывать куда угодно
Akka remoting/cluster
● Волшебный ActorRef: может указывать куда угодно
● Нет никакой разницы:
o Акторы в одной JVM;
o Акторы в разных JVM;
o Акторы на разных серверах;
o Акторы в нескольких DC, континентах и галактиках.
Akka remoting/cluster
● Волшебный ActorRef: может указывать куда угодно
● Набор полезных примитивов:
o Publish-subscribe;
o Singleton;
o Cluster state feed;
o Cluster-aware routers.
● Нет никакой разницы:
o Акторы в одной JVM;
o Акторы в разных JVM;
o Акторы на разных серверах;
o Акторы в нескольких DC, континентах и галактиках.
Akka remoting/cluster
● Волшебный ActorRef: может указывать куда угодно
● Набор полезных примитивов:
o Publish-subscribe;
o Singleton;
o Cluster state feed;
o Cluster-aware routers.
● Легко отстрелить ногу
● Нет никакой разницы:
o Акторы в одной JVM;
o Акторы в разных JVM;
o Акторы на разных серверах;
o Акторы в нескольких DC, континентах и галактиках.
Akka в бою: задача
● Кейс: классический web-crawling
o Поисковик по людям (как http://people.yandex.ru, только круче).
o Все просто на первый взгляд.
o Но становится сложно, когда возрастают объемы.
Akka в бою: задача
● Кейс: классический web-crawling
o Поисковик по людям (как http://people.yandex.ru, только круче).
o Все просто на первый взгляд.
o Но становится сложно, когда возрастают объемы.
● Проблемы:
o распределенная очередь;
o ненадежная сеть;
o ненадежные сервера;
o разные сценарии сбора для разных сайтов;
o невалидный HTML;
o невозможно парсить весь рунет
на одном сервере.
Статистика
● Три машины: 32Gb RAM, Linux
● 500 запросов/с на машину, поток 50мбит
● 30Тб данных в месяц
● в очереди ~300 млн. целей
● полный пересбор раз в два месяца
0 AD
Прототип паука:
● был написан на С++ и libcurl;
● работал на одном сервере.
0 AD
Прототип паука:
● был написан на С++ и libcurl;
● работал на одном сервере.
Наступили на грабли:
● Упёрлись в один сервер
0 AD
Прототип паука:
● был написан на С++ и libcurl;
● работал на одном сервере.
Наступили на грабли:
● Упёрлись в один сервер
● Слали запросы синхронно:
o 2000 простаивающих потоков, ждущих данные из сети;
o 2k*8Mb = 16Gb памяти только на стек для потоков;
o Нельзя делать select из >1024 дескрипторов.
0 AD
Прототип паука:
● был написан на С++ и libcurl;
● работал на одном сервере.
Наступили на грабли:
● Упёрлись в один сервер
● Слали запросы синхронно:
o 2000 простаивающих потоков, ждущих данные из сети;
o 2k*8Mb = 16Gb памяти только на стек для потоков;
o Нельзя делать select из >1024 дескрипторов.
● Сегфолты: падающий поток мог вынести всё:
o Coredump на 20Гб;
o полчаса чтобы посмотреть бектрейс.
0 AD
Прототип паука:
● был написан на С++ и libcurl;
● работал на одном сервере.
Наступили на грабли:
● Упёрлись в один сервер
● Слали запросы синхронно:
o 2000 простаивающих потоков, ждущих данные из сети;
o 2k*8Mb = 16Gb памяти только на стек для потоков;
o Нельзя делать select из >1024 дескрипторов.
● Сегфолты: падающий поток мог вынести всё:
o Coredump на 20Гб;
o полчаса чтобы посмотреть бектрейс.
● Жизнь слишком коротка для С++
2013
После хождения по граблям, поняли что хотим:
● асинхронное IO;
● масштабирование из коробки;
● сказать нет shared mutable data;
● восстановление после сбоев;
● легкость отладки и тестирования.
2013
После хождения по граблям, поняли что хотим:
● асинхронное IO;
● масштабирование из коробки;
● сказать нет shared mutable data;
● восстановление после сбоев;
● легкость отладки и тестирования.
Варианты:
● Scala + Akka;
● Java + Akka;
● Erlang;
● boost: asio, phoenix, cppnetlib.
2013
После хождения по граблям, поняли что хотим:
● асинхронное IO;
● масштабирование из коробки;
● сказать нет shared mutable data;
● восстановление после сбоев;
● легкость отладки и тестирования.
Варианты:
● Scala + Akka;
● Java + Akka;
● Erlang;
● boost: asio, phoenix, cppnetlib.
Архитектура
сеть
Node
Master
Bot
Bot
Bot
Log store
Data store
Node
Bot
Bot
Dequeue
Очередь
Crawl Save
Работа с сетью
Несколько вариантов:
● spray.io
o написан на idiomatic Scala, свой DSL;
o Akka под капотом;
o немного для других вещей;
o spray-can сбоку на изоленте, многое не умеет;
o разработку штормит, в процессе слияния с akka-http.
Работа с сетью
Несколько вариантов:
● spray.io
o написан на idiomatic Scala, свой DSL;
o Akka под капотом;
o немного для других вещей;
o spray-can сбоку на изоленте, многое не умеет;
o разработку штормит, в процессе слияния с akka-http.
● Apache http-async-client
o Java;
o стабильный как мамонт;
o умеет вообще всё;
o модульный и расширяемый
(inb4 MyConnectionKeepAliveStrategyBuilderFactory);
o свои, ни с чем не совместимые Future, ThreadPool и т.д.
AHC
● Не такой уж и асинхронный:
o решили использовать общий с akka thread-pool;
o Java DNS lookup - синхронный и через UDP;
AHC
● Не такой уж и асинхронный:
o решили использовать общий с akka thread-pool;
o Java DNS lookup - синхронный и через UDP;
o UDP иногда теряется, это норма;
o потеря пакета - вечная блокировка потока в thread-pool;
o через два дня работы весь thread-pool заблокирован.
AHC
● Не такой уж и асинхронный:
o решили использовать общий с akka thread-pool;
o Java DNS lookup - синхронный и через UDP;
o UDP иногда теряется, это норма;
o потеря пакета - вечная блокировка потока в thread-pool;
o через два дня работы весь thread-pool заблокирован.
● Как жили дальше:
o раздельные thread-pool для akka и AHC;
o свой dns lookup, который умеет в таймауты;
o регулярное изучение thread dump’ов на предмет блокировок.
Одноразовые акторы
● Создать нового актора - дешево и быстро:
o ~300 байт памяти;
o можно создать хоть миллион.
Одноразовые акторы
● Создать нового актора - дешево и быстро:
o ~300 байт памяти;
o можно создать хоть миллион.
● Одна подзадача - один актор:
o получил задачу;
o сделал её, послал результат и помер.
● Чистые иммутабельные акторы
Одноразовые акторы
● Создать нового актора - дешево и быстро:
o ~300 байт памяти;
o можно создать хоть миллион.
● Одна подзадача - один актор:
o получил задачу;
o сделал её, послал результат и помер.
● Чистые иммутабельные акторы
Одноразовые акторы
● Создать нового актора - дешево и быстро:
o ~300 байт памяти;
o можно создать хоть миллион.
асинхронный
коллбек!
Future[T]
● Одна подзадача - один актор:
o получил задачу;
o сделал её, послал результат и помер.
● Чистые иммутабельные акторы
Ask pattern
● Возможность что-то асинхронно спросить у актора
● Ответ - монада Future[T]
Ask pattern
● Возможность что-то асинхронно спросить у актора
● Ответ - монада Future[T]
● Под капотом:
o создается временный актор, который ждет ответа;
o ответ заворачивается в результат Future.
Ask pattern
● Возможность что-то асинхронно спросить у актора
● Ответ - монада Future[T]
● Под капотом:
o создается временный актор, который ждет ответа;
o ответ заворачивается в результат Future.
Ask pattern
● Возможность что-то асинхронно спросить у актора
● Ответ - монада Future[T]
● Под капотом:
o создается временный актор, который ждет ответа;
o ответ заворачивается в результат Future.
Ask pattern
● Возможность что-то асинхронно спросить у актора
● Ответ - монада Future[T]
● Под капотом:
o создается временный актор, который ждет ответа;
o ответ заворачивается в результат Future.
порядок
вычисления
Akka ask puzzle
● Вылетел exception
● Что окажется в result?
Akka ask puzzle
● Вылетел exception
● Что окажется в result?
1. Failure(e:UnsupportedOperationException).
2. “”
3. Failure(e:AskTimeoutException).
4. Failure(e:ClassCastException).
Akka ask puzzle
● Вылетел exception
● Что окажется в result?
1. Failure(e:UnsupportedOperationException).
2. “”
3. Failure(e:AskTimeoutException).
4. Failure(e:ClassCastException).
Akka ask puzzle
● Вылетел exception
● Что окажется в result?
1. Failure(e:UnsupportedOperationException).
2. “”
3. Failure(e:AskTimeoutException).
4. Failure(e:ClassCastException).
Akka ask puzzle
● Вылетел exception
● Что окажется в result?
1. Failure(e:UnsupportedOperationException).
2. “”
3. Failure(e:AskTimeoutException).
4. Failure(e:ClassCastException).
Временный актор
создается вне общей
иерархии
Мы и ask pattern
● Если уметь готовить аски, то жить можно
● Используем длинные цепочки асков:
Bot ScriptAction ScriptRunner
RequestExetutorThrottlerHttpClient
Мы и ask pattern
● Если уметь готовить аски, то жить можно
● Используем длинные цепочки асков:
Bot ScriptAction ScriptRunner
RequestExetutorThrottlerHttpClient
● Легкая декомпозиция задачи на части
● Каждую часть легко тестировать
● Есть overhead на создание временного актора
FSM, Конечные автоматы
FSM, Конечные автоматы
● Можно и без них, но с ними удобнее
● Помогают в задачах, когда:
o актору нужно долго подниматься;
o есть четкие переходы между состояниями.
FSM, Конечные автоматы
● Можно и без них, но с ними удобнее
● Помогают в задачах, когда:
o актору нужно долго подниматься;
o есть четкие переходы между состояниями.
● Увлеклись:
o у бота 10 состояний;
o ~30 правил перехода;
o 500 строк лапши;
o тестировать почти невозможно.
FSM, Конечные автоматы
● Можно и без них, но с ними удобнее
● Помогают в задачах, когда:
o актору нужно долго подниматься;
o есть четкие переходы между состояниями.
● Увлеклись:
o у бота 10 состояний;
o ~30 правил перехода;
o 500 строк лапши;
o тестировать почти невозможно.
● Сейчас:
o у бота 2 состояния (просыпаюсь и активный) и 5 правил;
o вся логика вынесена в отдельные акторы;
 есть и дочерние FSM.
Тестирование
Два подхода к тестированию:
Тестирование
● Синхронное через TestActorRef
o можно руками дернуть актора за receive();
o в самый раз для простой логики.
Два подхода к тестированию:
Тестирование
● Синхронное через TestActorRef
o можно руками дернуть актора за receive();
o в самый раз для простой логики.
● Асинхронное через akka.TestKit
o полный запуск системы;
o дополнительный синтаксис для assert-ов;
o можно подсовывать mock-акторов.
Два подхода к тестированию:
Логгинг
● Есть интеграция c slf4j
● log.debug(“foo”) - отправка сообщения логгеру
● MDC - message diagnostic context
Логгинг
● Есть интеграция c slf4j
● log.debug(“foo”) - отправка сообщения логгеру
● MDC - message diagnostic context
У нас:
● Свой логгер на основе akka.event.slf4j.Slf4jLogger
● Пишем логи в кассандру:
o 5-10Гб в сутки;
o разный time-to-live для DEBUG/INFO/WARN/ERROR;
o агрегация на лету при записи;
o простой web-gui, который рисует статистику.
Производительность
● 2M сообщений в секунду - легко!
[1]: http://letitcrash.com/post/17607272336/scalability-of-fork-join-pool
Производительность
● 2M сообщений в секунду - легко!
[1]: http://letitcrash.com/post/17607272336/scalability-of-fork-join-pool
● На мощном сервере еще больше: [1]
Производительность
● 2M сообщений в секунду - легко!
[1]: http://letitcrash.com/post/17607272336/scalability-of-fork-join-pool
● У нас: ~1000 msg/s, оверхед близок к нулю
● На мощном сервере еще больше: [1]
“Динамическая” типизация
[1]: H.E. Jiansen: Typecasting actors, from Akka to TAkka
[2]: Akka 2.x Roadmap
“Динамическая” типизация
● Боль: несоответствие типов сообщений вылезает
наружу только в run-time
● Хочется строгой типизации
[1]: H.E. Jiansen: Typecasting actors, from Akka to TAkka
[2]: Akka 2.x Roadmap
“Динамическая” типизация
● Боль: несоответствие типов сообщений вылезает
наружу только в run-time
● Хочется строгой типизации
[1]: H.E. Jiansen: Typecasting actors, from Akka to TAkka
[2]: Akka 2.x Roadmap
“Динамическая” типизация
● Боль: несоответствие типов сообщений вылезает
наружу только в run-time
● Хочется строгой типизации
Старая проблема:
● TypedActor в Akka 2.0
● TAkka [1]
● “Gålbma”, Akka 3.0 [2]
[1]: H.E. Jiansen: Typecasting actors, from Akka to TAkka
[2]: Akka 2.x Roadmap
“Динамическая” типизация
● Боль: несоответствие типов сообщений вылезает
наружу только в run-time
● Хочется строгой типизации
Старая проблема:
● TypedActor в Akka 2.0
● TAkka [1]
● “Gålbma”, Akka 3.0 [2]
[1]: H.E. Jiansen: Typecasting actors, from Akka to TAkka
[2]: Akka 2.x Roadmap
У нас:
● Интеграционные тесты
● Акторы обычно умеют только
в один тип сообщений
Ошибки: Thread starvation
Что это:
● Блокировка потоков в thread-pool.
Ошибки: Thread starvation
Что это:
● Блокировка потоков в thread-pool.
Откуда берутся:
● Thread.sleep(), Await.result() внутри актора;
● долгие вычисления;
● интеграция с легаси-кодом.
Ошибки: Thread starvation
Методы борьбы:
● ломать пальцы за Thread.sleep() внутри актора;
● отдельные dispatcher’ы;
● мониторинг стека вызовов и загруженности
потоков.
Что это:
● Блокировка потоков в thread-pool.
Откуда берутся:
● Thread.sleep(), Await.result() внутри актора;
● долгие вычисления;
● интеграция с легаси-кодом.
Ошибки: OutOfMemoryException
Причины:
● переполнение почтового ящика;
● слишком много акторов.
Ошибки: OutOfMemoryException
Причины:
● переполнение почтового ящика;
● слишком много акторов.
Что делать:
● мониторить загруженность почтового ящика;
● прореживать очередь сообщений;
● периодически изучать heap-dump и GC logs на
предмет утилизации памяти;
● следить за логическими утечками (замыкания).
В итоге
● прошли путь от akka 2.0 до 2.3.x
● один год в production
В итоге
● прошли путь от akka 2.0 до 2.3.x
● один год в production
● в начале приходится тяжело:
В итоге
● прошли путь от akka 2.0 до 2.3.x
● один год в production
● много скрытых граблей, но жить можно
● исключительно простой и выразительный
формализм
● удобно разрабатывать и тестировать
● в начале приходится тяжело:
Ссылки
● Typesafe activator [1]
● Coursera: Principles of reactive programming [2]
● Книги:
o Jamie Allen: Effective Akka, 2013;
o Derek Wyatt: Akka concurrency, 2013.
● Блоги:
o letitcrash.com [4]
[1]: https://typesafe.com/activator
[2]: https://www.coursera.org/course/reactive
[3]: https://letitcrash.com
Q&A

More Related Content

PDF
Scala performance под капотом
PPTX
Введение в Akka
PDF
DUMP-2015: «Распределенная обработка миллионов документов на Scala и Akka» Ст...
PDF
Работа с Akka Сluster, @afiskon, scalaby#14
PDF
Алексей Федоров
PDF
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...
PPTX
Опыт эксплуатации большого проекта на Ruby
PPTX
Андрей Акиньшин
Scala performance под капотом
Введение в Akka
DUMP-2015: «Распределенная обработка миллионов документов на Scala и Akka» Ст...
Работа с Akka Сluster, @afiskon, scalaby#14
Алексей Федоров
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...
Опыт эксплуатации большого проекта на Ruby
Андрей Акиньшин

What's hot (20)

PDF
"Модель акторов и параллелизм с использованием Akka" Зубов Максим, Naumen
ODP
Top10 доводов против языка Ruby
PDF
Константин Осипов
PDF
Как сделать ваш JavaScript быстрее / Роман Дворнов (Авито)
PDF
Язык Lua — секреты производительности / Ник Заварицкий (Mail.ru)
PDF
Павел Довгалюк, Обратная отладка
PDF
Производительность WebGL-приложений / Дмитренко Кирилл (Яндекс)
PDF
Aviasales: миграция поискового движка в docker / Дмитрий Кузьменков (Aviasales)
PDF
Олег Бартунов и Иван Панченко
PDF
Golang в действии: Как нам удается писать highload приложение на (не?)подходя...
PDF
Actor model. Futures & Promises. Reactive Streams.
PPTX
Пайплайн машинного обучения на Apache Spark / Павел Клеменков (Rambler&Co)
PDF
Артём Ерошенко «Рецепт приготовления облачных тестингов»
PDF
Отладка производительности приложения на Erlang / Максим Лапшин (Erlyvideo)
PDF
My talk at YouCon Saratov 2016
PDF
Actor model. Futures and Promises. Reactive Streams.
PDF
Actor model
PPTX
неприятная правда про язык go
PDF
Фреймворк Akka и его использование в Яндексе
PPTX
JVM: краткий курс общей анатомии, JPoint 2016 Conference Edition
"Модель акторов и параллелизм с использованием Akka" Зубов Максим, Naumen
Top10 доводов против языка Ruby
Константин Осипов
Как сделать ваш JavaScript быстрее / Роман Дворнов (Авито)
Язык Lua — секреты производительности / Ник Заварицкий (Mail.ru)
Павел Довгалюк, Обратная отладка
Производительность WebGL-приложений / Дмитренко Кирилл (Яндекс)
Aviasales: миграция поискового движка в docker / Дмитрий Кузьменков (Aviasales)
Олег Бартунов и Иван Панченко
Golang в действии: Как нам удается писать highload приложение на (не?)подходя...
Actor model. Futures & Promises. Reactive Streams.
Пайплайн машинного обучения на Apache Spark / Павел Клеменков (Rambler&Co)
Артём Ерошенко «Рецепт приготовления облачных тестингов»
Отладка производительности приложения на Erlang / Максим Лапшин (Erlyvideo)
My talk at YouCon Saratov 2016
Actor model. Futures and Promises. Reactive Streams.
Actor model
неприятная правда про язык go
Фреймворк Akka и его использование в Яндексе
JVM: краткий курс общей анатомии, JPoint 2016 Conference Edition
Ad

Viewers also liked (20)

PDF
Работа с Akka Cluster - Александр Алексеев
PDF
Путь от монолита на PHP к микросервисам на Scala / Денис Иванов (2GIS)
PDF
"Посмотрим на Акку-Джаву" Дмитрий Мантула
PPTX
How to run Real Time processing on Big Data / Ron Zavner (GigaSpaces)
PPTX
Expert Java Day: Java concurrency
PDF
Akka Cluster in Production
PDF
Никита Цуканов "Параллелизм и распределённые вычисления на акторах с Akka.net"
PPTX
Multithreading in java past and actual
PDF
Under the hood of scala implicits (kl10tch 10.03.2015)
PDF
Backend: Пишем на Scala для браузера
PDF
Under the hood of scala implicits (Scala eXchange 2014)
PDF
Scala lecture #4
PDF
Scala training
PDF
PDF
PDF
Feature suggester
PDF
Работа с Akka Cluster - Александр Алексеев
Путь от монолита на PHP к микросервисам на Scala / Денис Иванов (2GIS)
"Посмотрим на Акку-Джаву" Дмитрий Мантула
How to run Real Time processing on Big Data / Ron Zavner (GigaSpaces)
Expert Java Day: Java concurrency
Akka Cluster in Production
Никита Цуканов "Параллелизм и распределённые вычисления на акторах с Akka.net"
Multithreading in java past and actual
Under the hood of scala implicits (kl10tch 10.03.2015)
Backend: Пишем на Scala для браузера
Under the hood of scala implicits (Scala eXchange 2014)
Scala lecture #4
Scala training
Feature suggester
Ad

Similar to Akka: как я перестал бояться и полюбил асинхронный код (20)

PDF
Actor model
PDF
Actor Model
PDF
Akka.NET
PDF
Модель акторов и C++ что, зачем и как?
PPTX
Akka: Введение
PDF
модель акторов и C++ что, зачем и как ?
PDF
Курсы актерского мастерства
PDF
Take a Look at Akka-Java
PDF
"Посмотрим на Акку-Джаву" Дмитрий Мантула
PDF
Let's Take a Look at Akka-Java
PPTX
Платформа SmartActors
POTX
Как жить в согласии с SOLID?
PDF
Actors for fun and profit
PDF
Cocaine: сценарии использования (Дмитрий Унковский, Яндекс)
PDF
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
PDF
Akka и реактивное программирование на JVM
PDF
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
PDF
Общество Мертвых Потоков
PDF
Антон Нехаев - Многопоточное и распределенное программирование
PDF
To be reactive...RxJava
Actor model
Actor Model
Akka.NET
Модель акторов и C++ что, зачем и как?
Akka: Введение
модель акторов и C++ что, зачем и как ?
Курсы актерского мастерства
Take a Look at Akka-Java
"Посмотрим на Акку-Джаву" Дмитрий Мантула
Let's Take a Look at Akka-Java
Платформа SmartActors
Как жить в согласии с SOLID?
Actors for fun and profit
Cocaine: сценарии использования (Дмитрий Унковский, Яндекс)
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Akka и реактивное программирование на JVM
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
Общество Мертвых Потоков
Антон Нехаев - Многопоточное и распределенное программирование
To be reactive...RxJava

Akka: как я перестал бояться и полюбил асинхронный код

  • 1. Как я перестал бояться и полюбил асинхронный код JUG@VRN, 2014 Гребенников Роман, Sociohub
  • 2. Содержание ● Модель акторов: o зачем она нужна; o что это такое; o Akka 2 и Scala; o какие возможности даёт. ● Пример системы: o система сбора и парсинга данных. ● Личный опыт: o типичные ошибки; o подводные камни; o производительность; o перспективы.
  • 3. Free lunch is over Одно ядро, один поток - путь в никуда: [1]: http://www.gotw.ca/publications/concurrency-ddj.htm [2]: PassMark, http://www.cpubenchmark.net
  • 4. Free lunch is over Одно ядро, один поток - путь в никуда: [1]: http://www.gotw.ca/publications/concurrency-ddj.htm [2]: PassMark, http://www.cpubenchmark.net
  • 5. Concurrency vs Parallelism [1]: Rob Pike: Concurrency is not Parallelism (it's better!), http://concur.rspace.googlecode.com/hg/talk/concur.html
  • 6. Concurrency vs Parallelism Parallel programming строго одновременное исполнение нескольких задач [1]: Rob Pike: Concurrency is not Parallelism (it's better!), http://concur.rspace.googlecode.com/hg/talk/concur.html
  • 7. Concurrency vs Parallelism Concurrent programming композиция независимо выполняющихся задач (не обязательно параллельно) Parallel programming строго одновременное исполнение нескольких задач [1]: Rob Pike: Concurrency is not Parallelism (it's better!), http://concur.rspace.googlecode.com/hg/talk/concur.html
  • 8. Concurrency vs Parallelism Concurrent programming композиция независимо выполняющихся задач (не обязательно параллельно) Parallel programming строго одновременное исполнение нескольких задач [1]: Rob Pike: Concurrency is not Parallelism (it's better!), http://concur.rspace.googlecode.com/hg/talk/concur.html Всё это сложно
  • 11. Корень проблемы Shared mutable state и его друзья
  • 12. Корень проблемы Shared mutable state и его друзья
  • 14. Зачем нужны акторы? ● Чтобы перестать думать о плохом: o блокировки, race conditions, дедлоки; o shared state, state visibility; o потоки, concurrent collections и т.д.
  • 15. Зачем нужны акторы? ● Чтобы перестать думать о плохом: o блокировки, race conditions, дедлоки; o shared state, state visibility; o потоки, concurrent collections и т.д. ● И начать думать о хорошем: o single execution flow: актор работает последовательно; o слабая связанность всех компонентов: легко тестировать; o асинхронность: больше никакого Await; o нет никакого shared mutable state.
  • 16. Зачем нужны акторы? ● Чтобы перестать думать о плохом: o блокировки, race conditions, дедлоки; o shared state, state visibility; o потоки, concurrent collections и т.д. ● Легкость масштабирования: o часть платформы, не надо ничего изобретать; o есть восстановление после сбоев: “let it crash”. ● И начать думать о хорошем: o single execution flow: актор работает последовательно; o слабая связанность всех компонентов: легко тестировать; o асинхронность: больше никакого Await; o нет никакого shared mutable state.
  • 17. Модель акторов ● Придумана в 1972 году, до сих пор актуальна [1] ● Стала популярной благодаря Erlang ● Всё - актор, даже небо, даже звезды [1]: http://letitcrash.com/post/20964174345/carl-hewitt-explains-the-essence-of-the-actor
  • 18. Модель акторов ● Придумана в 1972 году, до сих пор актуальна [1] ● Стала популярной благодаря Erlang ● Всё - актор, даже небо, даже звезды [1]: http://letitcrash.com/post/20964174345/carl-hewitt-explains-the-essence-of-the-actor ● Акторы: o функционируют параллельно; o асинхронно обмениваются сообщениями; o имеют персональный адрес и почтовый ящик. ● при получении сообщения можно: o отправить новое сообщение другим акторам; o создать новых акторов; o изменить свое поведение для следующего сообщения. ● Напоминает Email
  • 19. Akka ● Jonas Bonér o Java champion; o Terracotta JVM clustering, JRockit JVM, AspectWerkz AOP, Eclipse AspectJ. ● Ресурсы o http://akka.io/docs/ o http://letitcrash.com/ ● Код o http://github.com/akka/akka o Apache 2.0 License o Scala API, Java API Áhkká (Lule Sami: "old woman")
  • 20. Actor внутри ActorRef Actor Почтовый ящик Указывает на актора. Умеет класть сообщения в ящик. Ваш код тут
  • 21. Actor внутри ActorRef Actor Почтовый ящик Указывает на актора. Умеет класть сообщения в ящик. Ваш код тут Берет сообщения по-одному. Что-то с ними делает. Единственный способ взаимодействия - отправка сообщения. Во внутренности актора доступа нет ни у кого.
  • 23. Почтовые ящики Пути как в файловой системе: ● akka://system/user/foo/bar ● akka.tcp://system@srv.example.com/user/foo/bar
  • 24. Почтовые ящики Пути как в файловой системе: ● akka://system/user/foo/bar ● akka.tcp://system@srv.example.com/user/foo/bar Выбор актора: ● каждый актор знает себя, родителя и детей; ● акторов можно выбирать по пути из ActorRegistry:
  • 25. Почтовые ящики Пути как в файловой системе: ● akka://system/user/foo/bar ● akka.tcp://system@srv.example.com/user/foo/bar Выбор актора: ● каждый актор знает себя, родителя и детей; ● акторов можно выбирать по пути из ActorRegistry: Типы: ● UnboundedMailbox; ● BoundedMailbox; ● UnboundedPriorityMailbox; ● BoundedPriorityMailbox.
  • 26. Диспетчеры ● Актор != поток поток 1 поток 2 A1 A2 A4 A1 A1 A2 A4 A4A1 A3
  • 27. Диспетчеры ● Актор != поток поток 1 поток 2 A1 A2 A4 A1 A1 A2 A4 A4A1 A3 ● Каждый актор жив, только когда работает ● В остальное время он освобождает поток
  • 28. Диспетчеры ● Актор != поток поток 1 поток 2 A1 A2 A4 A1 A1 A2 A4 A4A1 A3 ● Каждый актор жив, только когда работает ● В остальное время он освобождает поток ● Диспетчер занимается раскладыванием акторов по потокам: o Dispatcher; o PinnedDispatcher; o BalancingDispatcher; o CallingThreadDispatcher.
  • 29. Диспетчеры ● Актор != поток поток 1 поток 2 A1 A2 A4 A1 A1 A2 A4 A4A1 A3 ● Каждый актор жив, только когда работает ● В остальное время он освобождает поток ● Диспетчер занимается раскладыванием акторов по потокам: o Dispatcher; o PinnedDispatcher; o BalancingDispatcher; o CallingThreadDispatcher. ● Для непосредственного исполнения: o fork-join-executor; o thread-pool-executor.
  • 30. Падший актор ● Код иногда ломается ● Как жить дальше и что делать? ActorRef Parent Actor MessageBox
  • 31. Падший актор ● Код иногда ломается ● Как жить дальше и что делать? ActorRef Parent Actor MessageBox
  • 32. Падший актор ● Код иногда ломается ● Как жить дальше и что делать? ActorRef Parent
  • 33. Падший актор ● Код иногда ломается ● Как жить дальше и что делать? ActorRef Parent deadLetters Могильник для потерянных сообщений
  • 34. Падший актор ● Код иногда ломается ● Как жить дальше и что делать? ActorRef Parent deadLetters Могильник для потерянных сообщений ● И что?
  • 35. Supervision ● Можно делать иерархии акторов ● Каждый актор в ответе за своих детей ● Упавшего ребенка можно:
  • 36. Supervision ● Можно делать иерархии акторов ● Каждый актор в ответе за своих детей ● Упавшего ребенка можно: ● Stop: остановить; ● Restart: перезапустить; ● Continue: оставить полу-лежачим; ● Escalate: передать обработку выше.
  • 37. Supervision ● Можно делать иерархии акторов ● Каждый актор в ответе за своих детей ● Упавшего ребенка можно: ● Stop: остановить; ● Restart: перезапустить; ● Continue: оставить полу-лежачим; ● Escalate: передать обработку выше. ● Решение рекурсивно ● Есть хуки preStart, preRestart, postStop, etc.
  • 38. Supervision ● Можно делать иерархии акторов ● Каждый актор в ответе за своих детей ● Упавшего ребенка можно: ● Stop: остановить; ● Restart: перезапустить; ● Continue: оставить полу-лежачим; ● Escalate: передать обработку выше. ● Решение рекурсивно ● Есть хуки preStart, preRestart, postStop, etc.
  • 39. Akka remoting/cluster ● Волшебный ActorRef: может указывать куда угодно
  • 40. Akka remoting/cluster ● Волшебный ActorRef: может указывать куда угодно ● Нет никакой разницы: o Акторы в одной JVM; o Акторы в разных JVM; o Акторы на разных серверах; o Акторы в нескольких DC, континентах и галактиках.
  • 41. Akka remoting/cluster ● Волшебный ActorRef: может указывать куда угодно ● Набор полезных примитивов: o Publish-subscribe; o Singleton; o Cluster state feed; o Cluster-aware routers. ● Нет никакой разницы: o Акторы в одной JVM; o Акторы в разных JVM; o Акторы на разных серверах; o Акторы в нескольких DC, континентах и галактиках.
  • 42. Akka remoting/cluster ● Волшебный ActorRef: может указывать куда угодно ● Набор полезных примитивов: o Publish-subscribe; o Singleton; o Cluster state feed; o Cluster-aware routers. ● Легко отстрелить ногу ● Нет никакой разницы: o Акторы в одной JVM; o Акторы в разных JVM; o Акторы на разных серверах; o Акторы в нескольких DC, континентах и галактиках.
  • 43. Akka в бою: задача ● Кейс: классический web-crawling o Поисковик по людям (как http://people.yandex.ru, только круче). o Все просто на первый взгляд. o Но становится сложно, когда возрастают объемы.
  • 44. Akka в бою: задача ● Кейс: классический web-crawling o Поисковик по людям (как http://people.yandex.ru, только круче). o Все просто на первый взгляд. o Но становится сложно, когда возрастают объемы. ● Проблемы: o распределенная очередь; o ненадежная сеть; o ненадежные сервера; o разные сценарии сбора для разных сайтов; o невалидный HTML; o невозможно парсить весь рунет на одном сервере.
  • 45. Статистика ● Три машины: 32Gb RAM, Linux ● 500 запросов/с на машину, поток 50мбит ● 30Тб данных в месяц ● в очереди ~300 млн. целей ● полный пересбор раз в два месяца
  • 46. 0 AD Прототип паука: ● был написан на С++ и libcurl; ● работал на одном сервере.
  • 47. 0 AD Прототип паука: ● был написан на С++ и libcurl; ● работал на одном сервере. Наступили на грабли: ● Упёрлись в один сервер
  • 48. 0 AD Прототип паука: ● был написан на С++ и libcurl; ● работал на одном сервере. Наступили на грабли: ● Упёрлись в один сервер ● Слали запросы синхронно: o 2000 простаивающих потоков, ждущих данные из сети; o 2k*8Mb = 16Gb памяти только на стек для потоков; o Нельзя делать select из >1024 дескрипторов.
  • 49. 0 AD Прототип паука: ● был написан на С++ и libcurl; ● работал на одном сервере. Наступили на грабли: ● Упёрлись в один сервер ● Слали запросы синхронно: o 2000 простаивающих потоков, ждущих данные из сети; o 2k*8Mb = 16Gb памяти только на стек для потоков; o Нельзя делать select из >1024 дескрипторов. ● Сегфолты: падающий поток мог вынести всё: o Coredump на 20Гб; o полчаса чтобы посмотреть бектрейс.
  • 50. 0 AD Прототип паука: ● был написан на С++ и libcurl; ● работал на одном сервере. Наступили на грабли: ● Упёрлись в один сервер ● Слали запросы синхронно: o 2000 простаивающих потоков, ждущих данные из сети; o 2k*8Mb = 16Gb памяти только на стек для потоков; o Нельзя делать select из >1024 дескрипторов. ● Сегфолты: падающий поток мог вынести всё: o Coredump на 20Гб; o полчаса чтобы посмотреть бектрейс. ● Жизнь слишком коротка для С++
  • 51. 2013 После хождения по граблям, поняли что хотим: ● асинхронное IO; ● масштабирование из коробки; ● сказать нет shared mutable data; ● восстановление после сбоев; ● легкость отладки и тестирования.
  • 52. 2013 После хождения по граблям, поняли что хотим: ● асинхронное IO; ● масштабирование из коробки; ● сказать нет shared mutable data; ● восстановление после сбоев; ● легкость отладки и тестирования. Варианты: ● Scala + Akka; ● Java + Akka; ● Erlang; ● boost: asio, phoenix, cppnetlib.
  • 53. 2013 После хождения по граблям, поняли что хотим: ● асинхронное IO; ● масштабирование из коробки; ● сказать нет shared mutable data; ● восстановление после сбоев; ● легкость отладки и тестирования. Варианты: ● Scala + Akka; ● Java + Akka; ● Erlang; ● boost: asio, phoenix, cppnetlib.
  • 55. Работа с сетью Несколько вариантов: ● spray.io o написан на idiomatic Scala, свой DSL; o Akka под капотом; o немного для других вещей; o spray-can сбоку на изоленте, многое не умеет; o разработку штормит, в процессе слияния с akka-http.
  • 56. Работа с сетью Несколько вариантов: ● spray.io o написан на idiomatic Scala, свой DSL; o Akka под капотом; o немного для других вещей; o spray-can сбоку на изоленте, многое не умеет; o разработку штормит, в процессе слияния с akka-http. ● Apache http-async-client o Java; o стабильный как мамонт; o умеет вообще всё; o модульный и расширяемый (inb4 MyConnectionKeepAliveStrategyBuilderFactory); o свои, ни с чем не совместимые Future, ThreadPool и т.д.
  • 57. AHC ● Не такой уж и асинхронный: o решили использовать общий с akka thread-pool; o Java DNS lookup - синхронный и через UDP;
  • 58. AHC ● Не такой уж и асинхронный: o решили использовать общий с akka thread-pool; o Java DNS lookup - синхронный и через UDP; o UDP иногда теряется, это норма; o потеря пакета - вечная блокировка потока в thread-pool; o через два дня работы весь thread-pool заблокирован.
  • 59. AHC ● Не такой уж и асинхронный: o решили использовать общий с akka thread-pool; o Java DNS lookup - синхронный и через UDP; o UDP иногда теряется, это норма; o потеря пакета - вечная блокировка потока в thread-pool; o через два дня работы весь thread-pool заблокирован. ● Как жили дальше: o раздельные thread-pool для akka и AHC; o свой dns lookup, который умеет в таймауты; o регулярное изучение thread dump’ов на предмет блокировок.
  • 60. Одноразовые акторы ● Создать нового актора - дешево и быстро: o ~300 байт памяти; o можно создать хоть миллион.
  • 61. Одноразовые акторы ● Создать нового актора - дешево и быстро: o ~300 байт памяти; o можно создать хоть миллион. ● Одна подзадача - один актор: o получил задачу; o сделал её, послал результат и помер. ● Чистые иммутабельные акторы
  • 62. Одноразовые акторы ● Создать нового актора - дешево и быстро: o ~300 байт памяти; o можно создать хоть миллион. ● Одна подзадача - один актор: o получил задачу; o сделал её, послал результат и помер. ● Чистые иммутабельные акторы
  • 63. Одноразовые акторы ● Создать нового актора - дешево и быстро: o ~300 байт памяти; o можно создать хоть миллион. асинхронный коллбек! Future[T] ● Одна подзадача - один актор: o получил задачу; o сделал её, послал результат и помер. ● Чистые иммутабельные акторы
  • 64. Ask pattern ● Возможность что-то асинхронно спросить у актора ● Ответ - монада Future[T]
  • 65. Ask pattern ● Возможность что-то асинхронно спросить у актора ● Ответ - монада Future[T] ● Под капотом: o создается временный актор, который ждет ответа; o ответ заворачивается в результат Future.
  • 66. Ask pattern ● Возможность что-то асинхронно спросить у актора ● Ответ - монада Future[T] ● Под капотом: o создается временный актор, который ждет ответа; o ответ заворачивается в результат Future.
  • 67. Ask pattern ● Возможность что-то асинхронно спросить у актора ● Ответ - монада Future[T] ● Под капотом: o создается временный актор, который ждет ответа; o ответ заворачивается в результат Future.
  • 68. Ask pattern ● Возможность что-то асинхронно спросить у актора ● Ответ - монада Future[T] ● Под капотом: o создается временный актор, который ждет ответа; o ответ заворачивается в результат Future. порядок вычисления
  • 69. Akka ask puzzle ● Вылетел exception ● Что окажется в result?
  • 70. Akka ask puzzle ● Вылетел exception ● Что окажется в result? 1. Failure(e:UnsupportedOperationException). 2. “” 3. Failure(e:AskTimeoutException). 4. Failure(e:ClassCastException).
  • 71. Akka ask puzzle ● Вылетел exception ● Что окажется в result? 1. Failure(e:UnsupportedOperationException). 2. “” 3. Failure(e:AskTimeoutException). 4. Failure(e:ClassCastException).
  • 72. Akka ask puzzle ● Вылетел exception ● Что окажется в result? 1. Failure(e:UnsupportedOperationException). 2. “” 3. Failure(e:AskTimeoutException). 4. Failure(e:ClassCastException).
  • 73. Akka ask puzzle ● Вылетел exception ● Что окажется в result? 1. Failure(e:UnsupportedOperationException). 2. “” 3. Failure(e:AskTimeoutException). 4. Failure(e:ClassCastException). Временный актор создается вне общей иерархии
  • 74. Мы и ask pattern ● Если уметь готовить аски, то жить можно ● Используем длинные цепочки асков: Bot ScriptAction ScriptRunner RequestExetutorThrottlerHttpClient
  • 75. Мы и ask pattern ● Если уметь готовить аски, то жить можно ● Используем длинные цепочки асков: Bot ScriptAction ScriptRunner RequestExetutorThrottlerHttpClient ● Легкая декомпозиция задачи на части ● Каждую часть легко тестировать ● Есть overhead на создание временного актора
  • 77. FSM, Конечные автоматы ● Можно и без них, но с ними удобнее ● Помогают в задачах, когда: o актору нужно долго подниматься; o есть четкие переходы между состояниями.
  • 78. FSM, Конечные автоматы ● Можно и без них, но с ними удобнее ● Помогают в задачах, когда: o актору нужно долго подниматься; o есть четкие переходы между состояниями. ● Увлеклись: o у бота 10 состояний; o ~30 правил перехода; o 500 строк лапши; o тестировать почти невозможно.
  • 79. FSM, Конечные автоматы ● Можно и без них, но с ними удобнее ● Помогают в задачах, когда: o актору нужно долго подниматься; o есть четкие переходы между состояниями. ● Увлеклись: o у бота 10 состояний; o ~30 правил перехода; o 500 строк лапши; o тестировать почти невозможно. ● Сейчас: o у бота 2 состояния (просыпаюсь и активный) и 5 правил; o вся логика вынесена в отдельные акторы;  есть и дочерние FSM.
  • 81. Тестирование ● Синхронное через TestActorRef o можно руками дернуть актора за receive(); o в самый раз для простой логики. Два подхода к тестированию:
  • 82. Тестирование ● Синхронное через TestActorRef o можно руками дернуть актора за receive(); o в самый раз для простой логики. ● Асинхронное через akka.TestKit o полный запуск системы; o дополнительный синтаксис для assert-ов; o можно подсовывать mock-акторов. Два подхода к тестированию:
  • 83. Логгинг ● Есть интеграция c slf4j ● log.debug(“foo”) - отправка сообщения логгеру ● MDC - message diagnostic context
  • 84. Логгинг ● Есть интеграция c slf4j ● log.debug(“foo”) - отправка сообщения логгеру ● MDC - message diagnostic context У нас: ● Свой логгер на основе akka.event.slf4j.Slf4jLogger ● Пишем логи в кассандру: o 5-10Гб в сутки; o разный time-to-live для DEBUG/INFO/WARN/ERROR; o агрегация на лету при записи; o простой web-gui, который рисует статистику.
  • 85. Производительность ● 2M сообщений в секунду - легко! [1]: http://letitcrash.com/post/17607272336/scalability-of-fork-join-pool
  • 86. Производительность ● 2M сообщений в секунду - легко! [1]: http://letitcrash.com/post/17607272336/scalability-of-fork-join-pool ● На мощном сервере еще больше: [1]
  • 87. Производительность ● 2M сообщений в секунду - легко! [1]: http://letitcrash.com/post/17607272336/scalability-of-fork-join-pool ● У нас: ~1000 msg/s, оверхед близок к нулю ● На мощном сервере еще больше: [1]
  • 88. “Динамическая” типизация [1]: H.E. Jiansen: Typecasting actors, from Akka to TAkka [2]: Akka 2.x Roadmap
  • 89. “Динамическая” типизация ● Боль: несоответствие типов сообщений вылезает наружу только в run-time ● Хочется строгой типизации [1]: H.E. Jiansen: Typecasting actors, from Akka to TAkka [2]: Akka 2.x Roadmap
  • 90. “Динамическая” типизация ● Боль: несоответствие типов сообщений вылезает наружу только в run-time ● Хочется строгой типизации [1]: H.E. Jiansen: Typecasting actors, from Akka to TAkka [2]: Akka 2.x Roadmap
  • 91. “Динамическая” типизация ● Боль: несоответствие типов сообщений вылезает наружу только в run-time ● Хочется строгой типизации Старая проблема: ● TypedActor в Akka 2.0 ● TAkka [1] ● “Gålbma”, Akka 3.0 [2] [1]: H.E. Jiansen: Typecasting actors, from Akka to TAkka [2]: Akka 2.x Roadmap
  • 92. “Динамическая” типизация ● Боль: несоответствие типов сообщений вылезает наружу только в run-time ● Хочется строгой типизации Старая проблема: ● TypedActor в Akka 2.0 ● TAkka [1] ● “Gålbma”, Akka 3.0 [2] [1]: H.E. Jiansen: Typecasting actors, from Akka to TAkka [2]: Akka 2.x Roadmap У нас: ● Интеграционные тесты ● Акторы обычно умеют только в один тип сообщений
  • 93. Ошибки: Thread starvation Что это: ● Блокировка потоков в thread-pool.
  • 94. Ошибки: Thread starvation Что это: ● Блокировка потоков в thread-pool. Откуда берутся: ● Thread.sleep(), Await.result() внутри актора; ● долгие вычисления; ● интеграция с легаси-кодом.
  • 95. Ошибки: Thread starvation Методы борьбы: ● ломать пальцы за Thread.sleep() внутри актора; ● отдельные dispatcher’ы; ● мониторинг стека вызовов и загруженности потоков. Что это: ● Блокировка потоков в thread-pool. Откуда берутся: ● Thread.sleep(), Await.result() внутри актора; ● долгие вычисления; ● интеграция с легаси-кодом.
  • 96. Ошибки: OutOfMemoryException Причины: ● переполнение почтового ящика; ● слишком много акторов.
  • 97. Ошибки: OutOfMemoryException Причины: ● переполнение почтового ящика; ● слишком много акторов. Что делать: ● мониторить загруженность почтового ящика; ● прореживать очередь сообщений; ● периодически изучать heap-dump и GC logs на предмет утилизации памяти; ● следить за логическими утечками (замыкания).
  • 98. В итоге ● прошли путь от akka 2.0 до 2.3.x ● один год в production
  • 99. В итоге ● прошли путь от akka 2.0 до 2.3.x ● один год в production ● в начале приходится тяжело:
  • 100. В итоге ● прошли путь от akka 2.0 до 2.3.x ● один год в production ● много скрытых граблей, но жить можно ● исключительно простой и выразительный формализм ● удобно разрабатывать и тестировать ● в начале приходится тяжело:
  • 101. Ссылки ● Typesafe activator [1] ● Coursera: Principles of reactive programming [2] ● Книги: o Jamie Allen: Effective Akka, 2013; o Derek Wyatt: Akka concurrency, 2013. ● Блоги: o letitcrash.com [4] [1]: https://typesafe.com/activator [2]: https://www.coursera.org/course/reactive [3]: https://letitcrash.com
  • 102. Q&A