深入探索Akka与AkkaTyped:构建响应式应用的新途径
立即解锁
发布时间: 2025-08-19 00:05:40 阅读量: 7 订阅数: 16 


Scala 2.13编程实战与进阶
### 深入探索 Akka 与 Akka Typed:构建响应式应用的新途径
#### 1. Akka 与 Actor 模型基础
传统方法难以满足当前的扩展需求,而 Actor 模型以其无共享范式为这一问题提供了解决方案。Akka 是一个用于在 JVM 上构建基于 Actor 应用程序的库。
Actor 通过发送和接收消息进行通信,并相应地改变其内部状态和产生副作用。每个 Actor 都有一个以 ActorRef 形式存在的地址,它还封装了 Actor 的邮箱和调度器。Actor 被组织成层次结构,父 Actor 负责监督其子 Actor。
Actor 有明确的生命周期,并实现了许多方法,这些方法会在其生命周期的适当时候被调用。Akka 还提供了额外的模块,进一步扩展了其功能。
#### 2. 应用测试与运行
在测试方面,我们构建测试类的方式与之前类似,但有一个细微的差别。Seller Actor 是匿名定义的,因此它只是整个 Actor 系统的一部分。我们在默认构造函数中实例化 Store,并使用通过 store 字段可访问的底层 Actor 系统作为 TestKit 实例的构造函数参数。
以下是测试代码示例:
```scala
store.seller ! 'UnexpectedMessage
expectNoMessage()
}
"return groceries if given a shopping list" in {
store.seller.tell(ShoppingList(1, 1, 1, 1), testActor)
expectMsg(Groceries(1,1,1,1))
}
```
运行应用时,若尚未安装 Java 和 SBT,请进行安装。可以在终端中使用两个单独的终端会话分别运行 Shop 和 Bakery。运行命令如下:
- `sbt "runMain ch11.Store"`
- `sbt "runMain ch11.Bakery"`
由于代码中未处理 Shopping/ShoppingList 状态的 StateTimeout,因此必须先启动商店会话,待其加载并开始接受连接后,再启动面包店会话。
#### 3. Akka Typed 简介
Akka Typed 是 Akka 的一个模块,它以与未类型化的 Akka 略有不同的方式实现了 Actor 模型。与传统的未类型化 Akka 相比,Akka Typed 减少了开发者的选择,但增加了类型安全性,并简化了在维护阶段对基于 Actor 的程序的推理。
##### 3.1 与未类型化 Akka 的差异
在未类型化的 Akka 中,Actor 是抽象 Actor 类的任何子类,并重写 `def receive: PartialFunction[Any, Unit]` 方法。这使得开发者在实现中可以做任何事情,除了返回有意义的结果,这使得代码难以推理,并且无法组合 Actor 逻辑。
而 Akka Typed 声明任何定义了静态类型 Behavior 的实体都可以被视为 Actor。Behavior 的类型限制 Actor 只能接收特定类型的消息,并且 Actor 行为的返回类型必须是相同类型的下一个 Behavior。这样可以在编译时确保 Actor 只接收它声明要处理的消息类型。
此外,Actor 地址也需要类型化,并且地址类型需要在编译时已知。因此,未类型化 Akka 的一些特性,如隐式访问当前消息的发送者和通用 Actor 查找,在类型化 Akka 中不可用。
另一个显著的变化是引入了 Signal 消息类型,它代表 Actor 生命周期中的事件,取代了未类型化 Akka 中 Actor 类暴露的专用回调方法。
##### 3.2 示例:构建饼干面包店 Actor 系统
为了说明 Akka Typed 的特性,我们将重新实现一个小饼干面包店的 Actor 系统,该系统包含多个 Actor,每个 Actor 都有自己的职责:
- **Manager**:驱动整个过程,并将材料从一个工人传递到另一个工人。
- **Boy**:获取购物清单,并从商店返回相应的杂货给 Manager。
- **Chef**:将杂货制成面团,使用多个搅拌器,搅拌器的数量取决于要混合的材料量。
- **Cook**:将面团制成生饼干。
- **Baker**:使用有限容量的单个烤箱分批烘焙生饼干。
以下是构建该系统的一些步骤和代码示例:
首先,在 `build.sbt` 中添加依赖:
```scala
lazy val akkaVersion = "2.5.13"
libraryDependencies += "com.typesafe.akka" %% "akka-actor-typed" % akkaVersion
```
假设每个代码片段中都存在以下导入:
```scala
import akka.actor.typed._
import akka.actor.typed.scaladsl._
```
以烤箱 Actor 为例,定义其协议:
```scala
final case class Groceries(eggs: Int, flour: Int, sugar: Int, chocolate: Int)
final case class Dough(weight: Int)
final case class RawCookies(count: Int)
final case class ReadyCookies(count: Int)
sealed trait Command
case class Put(rawCookies: Int, sender: ActorRef[Baker.Command]) extends Command
case class Extract(sender: ActorRef[Baker.Command]) extends Command
```
定义烤箱 Actor 的行为:
```scala
def empty: Behaviors.Receive[Command] = Behaviors.receiveMessage[Command] {
case Put(rawCookies, sender) =>
val (inside, overflow:
```
0
0
复制全文
相关推荐









