102
Как я перестал бояться и полюбил асинхронный код JUG@VRN, 2014 Гребенников Роман, Sociohub

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

Embed Size (px)

Citation preview

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

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

JUG@VRN, 2014

Гребенников Роман,Sociohub

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

Содержание

● Модель акторов:o зачем она нужна;o что это такое;o Akka 2 и Scala;o какие возможности даёт.

● Пример системы:o система сбора и парсинга данных.

● Личный опыт:o типичные ошибки;o подводные камни;o производительность;o перспективы.

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

Free lunch is over

Одно ядро, один поток - путь в никуда:

[1]: http://www.gotw.ca/publications/concurrency-ddj.htm[2]: PassMark, http://www.cpubenchmark.net

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

Free lunch is over

Одно ядро, один поток - путь в никуда:

[1]: http://www.gotw.ca/publications/concurrency-ddj.htm[2]: PassMark, http://www.cpubenchmark.net

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

Concurrency vs Parallelism

[1]: Rob Pike: Concurrency is not Parallelism (it's better!), http://concur.rspace.googlecode.com/hg/talk/concur.html

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

Concurrency vs Parallelism

Parallel programmingстрого одновременное исполнение нескольких задач

[1]: Rob Pike: Concurrency is not Parallelism (it's better!), http://concur.rspace.googlecode.com/hg/talk/concur.html

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

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

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

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

Всё это сложно

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

Корень проблемы

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

Корень проблемы

Shared mutable state

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

Корень проблемы

Shared mutable stateи его друзья

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

Корень проблемы

Shared mutable stateи его друзья

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

Зачем нужны акторы?

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

Зачем нужны акторы?

● Чтобы перестать думать о плохом:o блокировки, race conditions, дедлоки;o shared state, state visibility;o потоки, concurrent collections и т.д.

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

Зачем нужны акторы?

● Чтобы перестать думать о плохом:o блокировки, race conditions, дедлоки;o shared state, state visibility;o потоки, concurrent collections и т.д.

● И начать думать о хорошем:o single execution flow:

актор работает последовательно;o слабая связанность всех компонентов:

легко тестировать;o асинхронность:

больше никакого Await;o нет никакого shared mutable state.

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

Зачем нужны акторы?

● Чтобы перестать думать о плохом: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.

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

Модель акторов

● Придумана в 1972 году, до сих пор актуальна [1]

● Стала популярной благодаря Erlang● Всё - актор, даже небо, даже звезды

[1]: http://letitcrash.com/post/20964174345/carl-hewitt-explains-the-essence-of-the-actor

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

Модель акторов

● Придумана в 1972 году, до сих пор актуальна [1]

● Стала популярной благодаря Erlang● Всё - актор, даже небо, даже звезды

[1]: http://letitcrash.com/post/20964174345/carl-hewitt-explains-the-essence-of-the-actor

● Акторы:o функционируют параллельно;o асинхронно обмениваются сообщениями;o имеют персональный адрес и почтовый ящик.

● при получении сообщения можно:o отправить новое сообщение другим акторам;o создать новых акторов;o изменить свое поведение для следующего сообщения.

● Напоминает Email

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

Akka

● Jonas Bonéro 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/akkao Apache 2.0 Licenseo Scala API, Java API

Áhkká (Lule Sami: "old woman")

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

Actor внутри

ActorRef

Actor

Почтовый ящик

Указывает на актора.Умеет класть сообщения в ящик.

Ваш код тут

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

Actor внутри

ActorRef

Actor

Почтовый ящик

Указывает на актора.Умеет класть сообщения в ящик.

Ваш код тут

Берет сообщения по-одному.Что-то с ними делает.

Единственный способ взаимодействия - отправка сообщения. Во внутренности

актора доступа нет ни у кого.

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

Создание актора

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

Почтовые ящики

Пути как в файловой системе:● akka://system/user/foo/bar● akka.tcp://[email protected]/user/foo/bar

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

Почтовые ящики

Пути как в файловой системе:● akka://system/user/foo/bar● akka.tcp://[email protected]/user/foo/bar

Выбор актора:● каждый актор знает себя, родителя и детей;● акторов можно выбирать по пути из ActorRegistry:

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

Почтовые ящики

Пути как в файловой системе:● akka://system/user/foo/bar● akka.tcp://[email protected]/user/foo/bar

Выбор актора:● каждый актор знает себя, родителя и детей;● акторов можно выбирать по пути из ActorRegistry:

Типы:● UnboundedMailbox;● BoundedMailbox;● UnboundedPriorityMailbox;● BoundedPriorityMailbox.

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

Диспетчеры

● Актор != поток

поток 1

поток 2

A1

A2

A4 A1

A1 A2

A4 A4A1

A3

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

Диспетчеры

● Актор != поток

поток 1

поток 2

A1

A2

A4 A1

A1 A2

A4 A4A1

A3

● Каждый актор жив, только когда работает● В остальное время он освобождает поток

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

Диспетчеры

● Актор != поток

поток 1

поток 2

A1

A2

A4 A1

A1 A2

A4 A4A1

A3

● Каждый актор жив, только когда работает● В остальное время он освобождает поток● Диспетчер занимается раскладыванием акторов

по потокам:o Dispatcher;o PinnedDispatcher;o BalancingDispatcher;o CallingThreadDispatcher.

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

Диспетчеры

● Актор != поток

поток 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.

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

Падший актор

● Код иногда ломается● Как жить дальше и что делать?

ActorRef

Parent

Actor

MessageBox

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

Падший актор

● Код иногда ломается● Как жить дальше и что делать?

ActorRef

Parent

Actor

MessageBox

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

Падший актор

● Код иногда ломается● Как жить дальше и что делать?

ActorRef

Parent

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

Падший актор

● Код иногда ломается● Как жить дальше и что делать?

ActorRef

Parent

deadLetters Могильник для потерянных сообщений

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

Падший актор

● Код иногда ломается● Как жить дальше и что делать?

ActorRef

Parent

deadLetters Могильник для потерянных сообщений

● И что?

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

Supervision

● Можно делать иерархии акторов● Каждый актор в ответе за своих детей● Упавшего ребенка можно:

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

Supervision

● Можно делать иерархии акторов● Каждый актор в ответе за своих детей● Упавшего ребенка можно:

● Stop: остановить;● Restart: перезапустить;● Continue: оставить полу-лежачим;● Escalate: передать обработку выше.

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

Supervision

● Можно делать иерархии акторов● Каждый актор в ответе за своих детей● Упавшего ребенка можно:

● Stop: остановить;● Restart: перезапустить;● Continue: оставить полу-лежачим;● Escalate: передать обработку выше.

● Решение рекурсивно● Есть хуки preStart, preRestart, postStop, etc.

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

Supervision

● Можно делать иерархии акторов● Каждый актор в ответе за своих детей● Упавшего ребенка можно:

● Stop: остановить;● Restart: перезапустить;● Continue: оставить полу-лежачим;● Escalate: передать обработку выше.

● Решение рекурсивно● Есть хуки preStart, preRestart, postStop, etc.

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

Akka remoting/cluster

● Волшебный ActorRef: может указывать куда угодно

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

Akka remoting/cluster

● Волшебный ActorRef: может указывать куда угодно

● Нет никакой разницы:o Акторы в одной JVM;o Акторы в разных JVM;o Акторы на разных серверах;o Акторы в нескольких DC, континентах и галактиках.

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

Akka remoting/cluster

● Волшебный ActorRef: может указывать куда угодно

● Набор полезных примитивов:o Publish-subscribe;o Singleton;o Cluster state feed;o Cluster-aware routers.

● Нет никакой разницы:o Акторы в одной JVM;o Акторы в разных JVM;o Акторы на разных серверах;o Акторы в нескольких DC, континентах и галактиках.

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

Akka remoting/cluster

● Волшебный ActorRef: может указывать куда угодно

● Набор полезных примитивов:o Publish-subscribe;o Singleton;o Cluster state feed;o Cluster-aware routers.

● Легко отстрелить ногу

● Нет никакой разницы:o Акторы в одной JVM;o Акторы в разных JVM;o Акторы на разных серверах;o Акторы в нескольких DC, континентах и галактиках.

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

Akka в бою: задача

● Кейс: классический web-crawlingo Поисковик по людям (как http://people.yandex.ru, только круче).o Все просто на первый взгляд.o Но становится сложно, когда возрастают объемы.

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

Akka в бою: задача

● Кейс: классический web-crawlingo Поисковик по людям (как http://people.yandex.ru, только круче).o Все просто на первый взгляд.o Но становится сложно, когда возрастают объемы.

● Проблемы:o распределенная очередь;o ненадежная сеть;o ненадежные сервера;o разные сценарии сбора для разных сайтов;o невалидный HTML;o невозможно парсить весь рунет

на одном сервере.

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

Статистика

● Три машины: 32Gb RAM, Linux● 500 запросов/с на машину, поток 50мбит● 30Тб данных в месяц ● в очереди ~300 млн. целей● полный пересбор раз в два месяца

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

0 AD

Прототип паука:● был написан на С++ и libcurl;● работал на одном сервере.

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

0 AD

Прототип паука:● был написан на С++ и libcurl;● работал на одном сервере.

Наступили на грабли:● Упёрлись в один сервер

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

0 AD

Прототип паука:● был написан на С++ и libcurl;● работал на одном сервере.

Наступили на грабли:● Упёрлись в один сервер

● Слали запросы синхронно:o 2000 простаивающих потоков, ждущих данные из сети;o 2k*8Mb = 16Gb памяти только на стек для потоков;o Нельзя делать select из >1024 дескрипторов.

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

0 AD

Прототип паука:● был написан на С++ и libcurl;● работал на одном сервере.

Наступили на грабли:● Упёрлись в один сервер

● Слали запросы синхронно:o 2000 простаивающих потоков, ждущих данные из сети;o 2k*8Mb = 16Gb памяти только на стек для потоков;o Нельзя делать select из >1024 дескрипторов.

● Сегфолты: падающий поток мог вынести всё:o Coredump на 20Гб;o полчаса чтобы посмотреть бектрейс.

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

0 AD

Прототип паука:● был написан на С++ и libcurl;● работал на одном сервере.

Наступили на грабли:● Упёрлись в один сервер

● Слали запросы синхронно:o 2000 простаивающих потоков, ждущих данные из сети;o 2k*8Mb = 16Gb памяти только на стек для потоков;o Нельзя делать select из >1024 дескрипторов.

● Сегфолты: падающий поток мог вынести всё:o Coredump на 20Гб;o полчаса чтобы посмотреть бектрейс.

● Жизнь слишком коротка для С++

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

2013

После хождения по граблям, поняли что хотим:● асинхронное IO;● масштабирование из коробки;● сказать нет shared mutable data;● восстановление после сбоев;● легкость отладки и тестирования.

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

2013

После хождения по граблям, поняли что хотим:● асинхронное IO;● масштабирование из коробки;● сказать нет shared mutable data;● восстановление после сбоев;● легкость отладки и тестирования.

Варианты:● Scala + Akka;● Java + Akka;● Erlang;● boost: asio, phoenix, cppnetlib.

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

2013

После хождения по граблям, поняли что хотим:● асинхронное IO;● масштабирование из коробки;● сказать нет shared mutable data;● восстановление после сбоев;● легкость отладки и тестирования.

Варианты:● Scala + Akka;● Java + Akka;● Erlang;● boost: asio, phoenix, cppnetlib.

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

Архитектура

сеть

Node

Master

Bot

Bot

Bot

Log store

Data store

NodeBot

Bot

Dequeue

Очередь

Crawl Save

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

Работа с сетью

Несколько вариантов:● spray.io

o написан на idiomatic Scala, свой DSL;o Akka под капотом;o немного для других вещей;o spray-can сбоку на изоленте, многое не умеет;o разработку штормит, в процессе слияния с akka-http.

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

Работа с сетью

Несколько вариантов:● spray.io

o написан на idiomatic Scala, свой DSL;o Akka под капотом;o немного для других вещей;o spray-can сбоку на изоленте, многое не умеет;o разработку штормит, в процессе слияния с akka-http.

● Apache http-async-cliento Java;o стабильный как мамонт;o умеет вообще всё;o модульный и расширяемый

(inb4 MyConnectionKeepAliveStrategyBuilderFactory);o свои, ни с чем не совместимые Future, ThreadPool и т.д.

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

AHC

● Не такой уж и асинхронный:o решили использовать общий с akka thread-pool;o Java DNS lookup - синхронный и через UDP;

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

AHC

● Не такой уж и асинхронный:o решили использовать общий с akka thread-pool;o Java DNS lookup - синхронный и через UDP;

o UDP иногда теряется, это норма;o потеря пакета - вечная блокировка потока в thread-pool;o через два дня работы весь thread-pool заблокирован.

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

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’ов на предмет блокировок.

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

Одноразовые акторы

● Создать нового актора - дешево и быстро:o ~300 байт памяти;o можно создать хоть миллион.

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

Одноразовые акторы

● Создать нового актора - дешево и быстро:o ~300 байт памяти;o можно создать хоть миллион.

● Одна подзадача - один актор:o получил задачу;o сделал её, послал результат и помер.

● Чистые иммутабельные акторы

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

Одноразовые акторы

● Создать нового актора - дешево и быстро:o ~300 байт памяти;o можно создать хоть миллион.

● Одна подзадача - один актор:o получил задачу;o сделал её, послал результат и помер.

● Чистые иммутабельные акторы

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

Одноразовые акторы

● Создать нового актора - дешево и быстро:o ~300 байт памяти;o можно создать хоть миллион.

асинхронный коллбек!

Future[T]

● Одна подзадача - один актор:o получил задачу;o сделал её, послал результат и помер.

● Чистые иммутабельные акторы

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

Ask pattern● Возможность что-то асинхронно спросить у актора● Ответ - монада Future[T]

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

Ask pattern● Возможность что-то асинхронно спросить у актора● Ответ - монада Future[T]● Под капотом:

o создается временный актор, который ждет ответа;o ответ заворачивается в результат Future.

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

Ask pattern● Возможность что-то асинхронно спросить у актора● Ответ - монада Future[T]● Под капотом:

o создается временный актор, который ждет ответа;o ответ заворачивается в результат Future.

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

Ask pattern● Возможность что-то асинхронно спросить у актора● Ответ - монада Future[T]● Под капотом:

o создается временный актор, который ждет ответа;o ответ заворачивается в результат Future.

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

Ask pattern● Возможность что-то асинхронно спросить у актора● Ответ - монада Future[T]● Под капотом:

o создается временный актор, который ждет ответа;o ответ заворачивается в результат Future.

порядок вычисления

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

Akka ask puzzle

● Вылетел exception● Что окажется в result?

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

Akka ask puzzle

● Вылетел exception● Что окажется в result?

1. Failure(e:UnsupportedOperationException).2. “”3. Failure(e:AskTimeoutException).4. Failure(e:ClassCastException).

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

Akka ask puzzle

● Вылетел exception● Что окажется в result?

1. Failure(e:UnsupportedOperationException).2. “”3. Failure(e:AskTimeoutException).4. Failure(e:ClassCastException).

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

Akka ask puzzle

● Вылетел exception● Что окажется в result?

1. Failure(e:UnsupportedOperationException).2. “”3. Failure(e:AskTimeoutException).4. Failure(e:ClassCastException).

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

Akka ask puzzle

● Вылетел exception● Что окажется в result?

1. Failure(e:UnsupportedOperationException).2. “”3. Failure(e:AskTimeoutException).4. Failure(e:ClassCastException).

Временный актор создается вне общей

иерархии

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

Мы и ask pattern

● Если уметь готовить аски, то жить можно● Используем длинные цепочки асков:

Bot ScriptAction ScriptRunner

RequestExetutorThrottlerHttpClient

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

Мы и ask pattern

● Если уметь готовить аски, то жить можно● Используем длинные цепочки асков:

Bot ScriptAction ScriptRunner

RequestExetutorThrottlerHttpClient

● Легкая декомпозиция задачи на части● Каждую часть легко тестировать● Есть overhead на создание временного актора

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

FSM, Конечные автоматы

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

FSM, Конечные автоматы

● Можно и без них, но с ними удобнее● Помогают в задачах, когда:

o актору нужно долго подниматься;o есть четкие переходы между состояниями.

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

FSM, Конечные автоматы

● Можно и без них, но с ними удобнее● Помогают в задачах, когда:

o актору нужно долго подниматься;o есть четкие переходы между состояниями.

● Увлеклись: o у бота 10 состояний;o ~30 правил перехода;o 500 строк лапши;o тестировать почти невозможно.

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

FSM, Конечные автоматы

● Можно и без них, но с ними удобнее● Помогают в задачах, когда:

o актору нужно долго подниматься;o есть четкие переходы между состояниями.

● Увлеклись: o у бота 10 состояний;o ~30 правил перехода;o 500 строк лапши;o тестировать почти невозможно.

● Сейчас: o у бота 2 состояния (просыпаюсь и активный) и 5 правил;o вся логика вынесена в отдельные акторы;

есть и дочерние FSM.

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

Тестирование

Два подхода к тестированию:

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

Тестирование

● Синхронное через TestActorRefo можно руками дернуть актора за receive();o в самый раз для простой логики.

Два подхода к тестированию:

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

Тестирование

● Синхронное через TestActorRefo можно руками дернуть актора за receive();o в самый раз для простой логики.

● Асинхронное через akka.TestKito полный запуск системы;o дополнительный синтаксис для assert-ов;o можно подсовывать mock-акторов.

Два подхода к тестированию:

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

Логгинг

● Есть интеграция c slf4j● log.debug(“foo”) - отправка сообщения логгеру● MDC - message diagnostic context

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

Логгинг

● Есть интеграция 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, который рисует статистику.

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

Производительность

● 2M сообщений в секунду - легко!

[1]: http://letitcrash.com/post/17607272336/scalability-of-fork-join-pool

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

Производительность

● 2M сообщений в секунду - легко!

[1]: http://letitcrash.com/post/17607272336/scalability-of-fork-join-pool

● На мощном сервере еще больше: [1]

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

Производительность

● 2M сообщений в секунду - легко!

[1]: http://letitcrash.com/post/17607272336/scalability-of-fork-join-pool

● У нас: ~1000 msg/s, оверхед близок к нулю

● На мощном сервере еще больше: [1]

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

“Динамическая” типизация

[1]: H.E. Jiansen: Typecasting actors, from Akka to TAkka[2]: Akka 2.x Roadmap

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

“Динамическая” типизация

● Боль: несоответствие типов сообщений вылезает наружу только в run-time

● Хочется строгой типизации

[1]: H.E. Jiansen: Typecasting actors, from Akka to TAkka[2]: Akka 2.x Roadmap

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

“Динамическая” типизация

● Боль: несоответствие типов сообщений вылезает наружу только в run-time

● Хочется строгой типизации

[1]: H.E. Jiansen: Typecasting actors, from Akka to TAkka[2]: Akka 2.x Roadmap

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

“Динамическая” типизация

● Боль: несоответствие типов сообщений вылезает наружу только в 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

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

“Динамическая” типизация

● Боль: несоответствие типов сообщений вылезает наружу только в 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

У нас:● Интеграционные тесты● Акторы обычно умеют только

в один тип сообщений

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

Ошибки: Thread starvation

Что это:

● Блокировка потоков в thread-pool.

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

Ошибки: Thread starvation

Что это:

● Блокировка потоков в thread-pool.

Откуда берутся:● Thread.sleep(), Await.result() внутри актора;● долгие вычисления;● интеграция с легаси-кодом.

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

Ошибки: Thread starvation

Методы борьбы:● ломать пальцы за Thread.sleep() внутри актора;● отдельные dispatcher’ы;● мониторинг стека вызовов и загруженности

потоков.

Что это:

● Блокировка потоков в thread-pool.

Откуда берутся:● Thread.sleep(), Await.result() внутри актора;● долгие вычисления;● интеграция с легаси-кодом.

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

Ошибки: OutOfMemoryException

Причины:● переполнение почтового ящика;● слишком много акторов.

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

Ошибки: OutOfMemoryException

Причины:● переполнение почтового ящика;● слишком много акторов.

Что делать:● мониторить загруженность почтового ящика;● прореживать очередь сообщений;● периодически изучать heap-dump и GC logs на

предмет утилизации памяти;● следить за логическими утечками (замыкания).

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

В итоге● прошли путь от akka 2.0 до 2.3.x● один год в production

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

В итоге● прошли путь от akka 2.0 до 2.3.x● один год в production● в начале приходится тяжело:

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

В итоге● прошли путь от akka 2.0 до 2.3.x● один год в production

● много скрытых граблей, но жить можно● исключительно простой и выразительный

формализм● удобно разрабатывать и тестировать

● в начале приходится тяжело:

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

Ссылки

● 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

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

Q&A