Что такое Akka Typed и как она отличается от классической Akka?

Akka Typed — это новая, типобезопасная версия акторной модели Akka, представленная как официальная альтернатива классическому (untyped) API. Основная цель Akka Typed — обеспечить строгую типизацию сообщений и поведения акторов, минимизируя ошибки во время компиляции и улучшая масштабируемость кода.

Отличие от классической Akka

1. Статическая типизация сообщений

В классической Akka (akka.actor.Actor) метод receive принимает любые типы сообщений (Any), и программист должен вручную проверять типы:

def receive = {
case s: String => println(s"Got a string: $s")
case n: Int => println(s"Got a number: $n")
}

В Akka Typed сообщения строго типизированы через параметр:

Behavior\[String\]

Актор, принимающий только строки, не сможет принять Int, Boolean и прочие типы — компилятор это отследит.

2. Никаких классов-наследников

В классической Akka акторы реализуются как классы, унаследованные от akka.actor.Actor.

class MyActor extends Actor {
def receive = {
...
}
}

В Akka Typed акторами управляет функция, возвращающая Behavior[T]:

val myBehavior: Behavior\[String\] = Behaviors.receive { (ctx, msg) =>
...
}

Это делает поведение более функциональным, легче читаемым и поддающимся рефакторингу.

3. Поведение как значение

В классической Akka поведение — это receive метод. В Akka Typed поведение — это значение типа Behavior[T], которое можно возвращать, передавать, сохранять.

def counter(n: Int): Behavior\[String\] =
Behaviors.receiveMessage {
case "inc" => counter(n + 1)
case "print" =>
println(n)
Behaviors.same
}

Каждое сообщение может возвращать новое поведение, и эта возможность естественным образом реализует конечные автоматы.

4. Строгая типизация контекста и акторных ссылок

Контекст (ActorContext) и акторные ссылки (ActorRef) тоже типизированы. Это гарантирует, что нельзя отправить неправильное сообщение.

def apply(): Behavior\[Command\] =
Behaviors.receive { (ctx: ActorContext\[Command\], msg: Command) =>
...
}

В классической Akka ActorRef может принимать Any.

5. Явное создание акторов через Behaviors

Вместо system.actorOf(Props(...)), в Akka Typed создаётся Behavior:

val greeter: Behavior\[Hello\] = Behaviors.receive { (ctx, msg) =>
...
}
val system: ActorSystem\[Hello\] = ActorSystem(greeter, "HelloSystem")

Тип ActorSystem[Hello] указывает, что система ожидает акторов, обрабатывающих сообщения типа Hello.

Пример: классическая Akka

case class Greet(name: String)
class Greeter extends Actor {
def receive = {
case Greet(name) => println(s"Hello, $name")
}
}
val system = ActorSystem("ClassicSystem")
val greeter = system.actorOf(Props\[Greeter\])
greeter ! Greet("Alice")

Пример: Akka Typed

case class Greet(name: String)
val greeter: Behavior\[Greet\] = Behaviors.receive { (ctx, msg) =>
println(s"Hello, ${msg.name}")
Behaviors.same
}
val system = ActorSystem(greeter, "TypedSystem")
system ! Greet("Alice")

Преимущества Akka Typed

  1. Безопасность на этапе компиляции — уменьшает runtime-ошибки.

  2. Явное определение контрактов акторов — легче читать и сопровождать.

  3. Функциональный стиль — легче писать композиции, менять поведение.

  4. Простота тестирования — поведение как чистая функция.

  5. Лучшая поддержка IDE и автодополнения.

Поддержка Akka Typed и миграция

Akka Typed является предпочтительной моделью с версии Akka 2.6. Старое untyped API не удалено, но считается устаревающим. Также можно интегрировать untyped и typed акторы в одном проекте через akka.actor.typed.adapter._, но лучше придерживаться typed-подхода при разработке новых компонентов.

Поведение акторов в Akka Typed

Akka Typed предоставляет множество функций для управления поведением:

  • Behaviors.same — оставить текущее поведение.

  • Behaviors.ignore — игнорировать все сообщения.

  • Behaviors.stopped — завершить актор.

  • Behaviors.receiveMessage — упростить поведение без контекста.

  • Behaviors.setup — задать инициализацию.

Иерархия акторов и супервизия

Akka Typed поддерживает те же механизмы надзора:

Behaviors.supervise(childBehavior).onFailure\[Exception\](SupervisorStrategy.restart)

Поведение оборачивается в супервизор, который определяет, что делать в случае ошибки.

Резюме отличий (без выделения)

Особенность Classic Akka Akka Typed
Типизация сообщений Нет (Any) Есть (Behavior[T])
--- --- ---
Акторы Класс Actor Функция Behavior[T]
--- --- ---
Контекст и ActorRef Нетипизированный Типизированный
--- --- ---
Смена поведения context.become Behavior[T]
--- --- ---
Безопасность Runtime-ошибки Компиляция ловит ошибки
--- --- ---
Интеграция с typed supervision Сложно Встроено
--- --- ---

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