第4章 并发编程与Akka Actor
📌 面试问答卡片
第一问:请介绍 Actor 模型及 Akka 中的实现。
考察点:并发模型理解、与共享内存差异、消息传递语义、Akka 关键概念(ActorRef、Mailbox)。
回答框架:
① 定义:Actor 是并发原语,封装状态+行为,通过异步消息通信;
② 核心:每个 Actor 有邮箱(Mailbox),串行处理消息,无共享状态;
③ Akka 实现:ActorRef 作为引用,ActorSystem 管理生命周期;
④ 优势:错误隔离、位置透明、易扩展;
⑤ 注意:消息不可变性,避免阻塞。
示例回答:
“Actor 模型通过消息传递实现并行,每个 Actor 拥有独立邮箱与行为。Akka 借助 ActorRef 提供位置透明通信,保证消息顺序处理。相比于共享内存锁,它避免了竞态条件并提升了容错性。例如在聊天系统中,每个用户对应一个 Actor 管理会话。”
可能追问:
① Actor 内如何保证只处理一个消息?
② 如果消息处理抛出异常会怎样?
③ 如何跨 JVM 发送消息?
避坑提醒:不要只说“像对象”,要强调无共享、异步、容错;避免将 Actor 与普通线程混为一谈。
第二问:Akka 的监督策略(Supervision Strategy)有哪些?如何选择?
考察点:容错设计思维、错误恢复机制、OneForOne 与 AllForOne 区别、自定义指令。
回答框架:
① 监督者:父 Actor 监督子 Actor,处理失败;
② 策略类型:OneForOne(仅重启失败子 Actor)、AllForOne(重启所有同级);
③ 指令:Resume(忽略错误继续)、Restart(重新初始化)、Stop(终止)、Escalate(向上报告);
④ 选择依据:错误类型、依赖关系、业务原子性;
⑤ 例子:文件处理中文件缺失可用 Resume,网络超时用 Restart。
示例回答:
“Akka 监督策略有两种:OneForOne 只影响出错的子 Actor,适合独立任务;AllForOne 重启全部子 Actor,适合强依赖阶段。默认指令是 Restart,但根据业务可改为 Resume(如临时读取失败)或 Stop(如认证失败后无需重试)。我曾在支付服务中使用 OneForOne 配合 Restart,避免影响正常订单。”
可能追问:
① 如何自定义监督策略?
② 监督策略与 Actor 生命周期关系?
③ 什么场景用 Escalate?
避坑提醒:不要只列举指令不解释场景;注意区分监督策略与 Actor 重启机制。
第三问:Future 与 Promise 的区别?在 Akka 中如何使用?
考察点:异步编程理解、回调组合、Promise 与 Future 的关系、与 Actor 协作。
回答框架:
① Future 是异步结果的只读占位符,用于消费;Promise 是可写的 Future 生产者;
② 区别:Future 由计算产生,Promise 可手动完成;
③ 在 Akka 中:通过 ask 模式获得 Future,用 pipeTo 回传给 Actor;
④ 组合:map/flatMap/onComplete;
⑤ 注意:Actor 内部避免同步等待 Future,应用 pipeTo。
示例回答:
“Future 代表未来值,Promise 提供成功/失败方法填充 Future。在 Akka 中常用 ask 模式获取 Actor 回复得到 Future,再用 pipeTo 将结果发回另一个 Actor,避免阻塞。例如在用户注册中异步校验邮箱,使用 flatMap 组合两个验证 Future 并统一返回。”
可能追问:
① Future 的线程执行机制?
② 如何处理 Future 超时?
③ 与 Actor 的 tell/ask 选择?
避坑提醒:不要混淆 Future 与 Promise 的角色;避免在 Actor 内长期阻塞 Future 导致邮箱堆积。
📁 真实项目案例模板
项目名称:实时风控分析服务(FPG Engine)
业务背景:监控电商交易,实时识别异常行为(刷单、盗号),触发规则引擎与人工审核。
规模指标:日均事件量 5 亿条;QPS 峰值 80K;50+ 个规则 Actor;集群节点 20 台 32C64G。
技术栈:Scala 2.13, Akka 2.8 (Typed), Kafka, Redis, Prometheus, Kubernetes。
核心难点:
① 事件流中部分消息处理慢导致背压;
② Actor 间复杂依赖需要动态监督策略;
③ 规则变更需热更新而不中断服务。
面试高频追问:
① 你们如何实现动态加载规则而不重启 Actor?→ 通过消息分发规则代码,或使用带版本号的配置 Actor 定时更新。
② 高峰时消息丢失风险?→ 使用 Kafka 持久化+最多一次语义,配合监督策略的 Resume 避免重试风暴。
③ 为什么选择 Akka Typed 而非 Classic?→ 类型安全,编译期避免死信,适合多人协作。
可迁移回答话术:
“我们在实时风控场景下使用 Akka Actor 处理高并发事件。每个规则封装为独立 Actor,监督策略采用 OneForOne + Resume 应对瞬态网络错误,防止重试导致负载上升。对于规则热更新,通过配置 Actor 广播版本号,各 Actor 异步拉取新规则,保证零停机。Future 结合 pipeTo 用于异步查询外部黑名单库,避免阻塞 Actor 邮箱。最终系统在 80K QPS 下 p99 延迟低于 50ms。”