Статьи

Основы Акки

Как объяснялось в предыдущем посте, наша система основана на Akka . Прежде чем перейти к более подробным сведениям о нашем решении, я хотел бы объяснить, что такое Akka и почему это так здорово.

Akka — это инструментарий, а не фреймворк, вы можете просто использовать биты, которые вам нужны для вашего сервиса. В этой серии мы сосредоточимся на основных функциях и не будем рассматривать Akka Streams , Akka-Http или Akka Cluster (поскольку они не входят в сферу применения, а не потому, что они не фантастические).

Акка предлагает другую абстракцию для работы с параллелизмом, паралеллизмом и отказоустойчивостью. Эта абстракция называется Actor Model. Если у вас есть опыт работы со старой экосистемой Java, вы поймете, как трудно писать безопасный и правильный многопоточный код . Предоставление удобных для человека абстракций, таких как Actors, является революцией, сравнимой с управлением памятью в Java на момент появления. Новые проблемы, связанные с масштабированием Интернета и облачными вычислениями, требуют реактивного подхода к программированию. Akka согласуется с этой философией и позволяет вам внедрять управляемые событиями архитектуры .

Актеры полностью

Потоки являются дорогим ресурсом, поэтому мы должны использовать их разумно. Блокировка потоков, пока мы ожидаем ответа от какой-либо операции ввода-вывода, действительно неэффективна. Актеры используют потоки по-разному, в результате чего они довольно легкие ( несколько миллионов актеров на ГБ кучи памяти )

Актеры — хорошее сочетание принципов объектно-ориентированного и функционального программирования. ООП в основном о сообщениях, как заявил Алан Кей, один из пионеров ООП

Мне очень жаль, что я давно придумал термин «объекты» для этой темы, потому что это заставляет многих людей сосредоточиться на меньшей идее. Основная идея — «обмен сообщениями».

Актер обменивается неизменными сообщениями и сохраняет свое собственное инкапсулированное состояние: каждое взаимодействие должно осуществляться через сообщения.

Отказоустойчивость

В Java нет четкой и общей модели обработки ошибок, и вы можете понять это после работы в нескольких проектах. Происхождение этого — запутанная абстракция, называемая Исключением и его подтипами Проверенные и Не проверенные Исключения. Единственное реальное отличие состоит в том, что проверенные исключения заставляют нас решать проблему в прямой вызывающей стороне, за исключением того, что они не намекают на стратегию, которую мы должны применять.

Я настоятельно рекомендую этот пост об этом. Одна из таких сильных идей в посте заключается в том, что ошибки не являются исправляемыми ошибками. Эта цитата содержится в этом посте, первоисточник :

Я принимал участие в разработке библиотеки, написанной на C ++. Один из разработчиков сказал мне, что разработчики делятся на тех, кто любит исключения, и тех, кто предпочитает коды возврата. Как мне кажется, друзья с кодами возврата победили. Однако у меня сложилось впечатление, что они обсуждали не ту тему: исключения и коды возврата одинаково выразительны, однако их не следует использовать для описания ошибок. На самом деле коды возврата содержали такие определения, как ARRAY_INDEX_OUT_OF_RANGE . Но я задавался вопросом: как отреагирует моя функция, когда она получит этот код возврата из подпрограммы? Должен ли он отправить письмо своему программисту? Он может вернуть этот код вызывающей стороне по очереди, но также не знает, как с этим справиться. Хуже того, поскольку я не могу делать предположения о реализации функции, я должен ожидать ARRAY_INDEX_OUT_OF_RANGE от каждой подпрограммы. Мой вывод заключается в том, что ARRAY_INDEX_OUT_OF_RANGE является ARRAY_INDEX_OUT_OF_RANGE (программирования). Он не может быть обработан или исправлен во время выполнения, он может быть исправлен только разработчиком. Таким образом, не должно быть соответствующего кода возврата, но вместо этого должны быть утверждения.

Akka предоставляет отличный способ для устранения сбоев / ошибок на основе следующих принципов:

  • Принцип единой ответственности: управление отказами делегируется руководителям, создавая целенаправленные субъекты бизнеса. Некоторое время назад мы договорились, что управление жизненным циклом, например создание объектов, следует перенести на фабрики, поэтому объект не несет ответственности за создание самого себя. Возобновление или перезапуск объекта после некоторого сбоя является частью управления жизненным циклом, и Akka заставляет вас передать эту ответственность супервизорам. Полученный код будет слабосвязанным и очень связным.
  • Стратегии восстановления по умолчанию: важно понимать, какие у нас есть варианты после того, как система находится в состоянии сбоя. БД временно не работает? Имеет ли какой-либо ввод в сочетании с существующими данными нежелательное состояние? Это ошибка? Нужно ли нам отказываться от этого конкретного запроса, или эта часть системы будет испорчена, пока не будет применено какое-либо исправление? Эти вопросы будут определять наш ответ на этот инцидент, и Akka предлагает несколько встроенных стратегий .
1
2
3
4
5
6
7
override val supervisorStrategy =
  OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
    case _: ArithmeticException      => Resume
    case _: NullPointerException     => Restart
    case _: IllegalArgumentException => Stop
    case _: Exception                => Escalate
  }
  • Отказ как первоклассного гражданина: некоторые библиотеки или экосистемы скрывают сбои через непонятные API. Akka обычно развертывается в распределенных средах, поэтому использует ненадежные ресурсы, такие как сети. Это заставляет нас выводить неудачи на фронт. Даже в «более безопасных» средах, таких как монолиты, повсеместно возникают сбои, поэтому использование таких инструментов, как Akka, крайне важно для создания надежного и надежного программного обеспечения.

Параллелизм и параллелизм

С Akka мы не собираемся иметь дело непосредственно с потоками, они скрыты под слоем абстракции. Основой приложения Akka является система Actor :

Система акторов — это иерархическая группа акторов, которые имеют общую конфигурацию, например, диспетчеры, развертывания, удаленные возможности и адреса. Это также точка входа для создания или поиска актеров.

Диспетчер также является контекстом выполнения, поэтому, в конце концов, именно там находится пул потоков. Предположим, что ваше приложение использует один диспетчер с 4 выделенными потоками. Как вы можете видеть, потоки являются дефицитным ресурсом, если мы будем блокировать ввод-вывод или интенсивную работу ЦП в некоторых акторах, мы будем использовать исключительно один из потоков, и вы увидите, насколько быстро в вашем сервисе закончатся потоки.

Решение заключается в том, чтобы обернуть эти операции такими конструкциями, как Scala Futures, а затем предоставить другой контекст выполнения для этих задач.

Резюме

Akka — фантастический инструментарий, полный хорошо подходящих абстракций для современных задач. В следующем посте мы увидим с помощью некоторого кода, как координировать и контролировать акторов с ограничениями нашего примера приложения.

Ссылка: Основы Akka от нашего партнера JCG Фелипе Фернандеса в блоге Crafted Software .