第4章:Actor模型与Akka基础 — 生命周期、消息传递、监督策略
Actor模型是Akka的核心抽象,面试常从三个维度考察:生命周期管理(状态转换时机与钩子方法)、消息传递(异步、不可变、邮箱机制)、监督策略(容错恢复与父子关系)。本章聚焦高频考点,结合真实项目经验教你结构化应答。
面试问答卡片
🎯 面试问题1:简述Akka Actor的生命周期,并说明preStart和postStop的作用时机。
考察点:是否理解Actor的状态机模型(创建→启动→接收消息→停止→销毁),以及钩子方法的实际用途。
回答框架:先说5个阶段 → 点出preStart在初始化资源(DB连接、定时器),postStop用于清理 → 强调不可逆,stop后不再接收消息。
示例回答:Actor生命周期:new → preStart → 正常接收消息 → postStop → Terminated。preStart在start()后执行,用于初始化;postStop在stop()后、死亡前执行,释放资源。若重启,会重新走preStart而非再次new。
可能追问:重启时preStart和postStop的执行顺序?答:先postStop清理旧资源,再new+preStart。如何手动停止Actor?答:context.stop(self)或发送PoisonPill。
🎯 面试问题2:Akka中消息传递是异步的吗?如何保证消息顺序和处理结果返回?
考察点:对Actor模型“tell”与“ask”的理解,邮箱机制,以及Future/pipeTo的使用。
回答框架:默认tell无返回值;ask返回Future → 利用pipeTo避免阻塞 → 保证同一个Actor消息顺序按发送顺序处理(FIFO邮箱)。
示例回答:tell是异步fire-and-forget,无保证顺序?实际上同一Actor的邮箱保证FIFO。若需结果用ask,返回Future,调用方可通过pipeTo将结果发送给另一个Actor,避免阻塞。
可能追问:邮箱类型有哪些?答:默认无界邮箱,还有PriorityMailbox、BoundedMailbox。如何自定义邮箱?答:实现MessageQueue接口并配置。
🎯 面试问题3:Akka监督策略中OneForOne和AllForOne的区别?什么场景选后者?
考察点:监督树概念,容错策略选择依据,以及实际项目中的权衡。
回答框架:OneForOne只重启出错的子Actor;AllForOne重启所有子Actor → 适用于子Actor强依赖或共享状态场景 → 自定义策略可混合Restart/Resume/Stop/Escalate。
示例回答:OneForOne隔离影响最小,适合独立子Actor(如HTTP请求)。AllForOne适合子Actor共同维护可变状态(如分区缓存),一个失败可能导致全局不一致,必须全部重启。默认OneForOne。
可能追问:监督策略的默认恢复指令?答:默认Restart。如何定义最大重启次数?答:在BackoffSupervisor或自定义策略中设置maxNrOfRetries与withinTimeRange。
项目案例:高并发实时消息推送系统
| 项目名称 | Akka-WebSocket 高并发实时推送平台(内部代号:PushX) |
| 业务背景 | 服务于千万级用户的消息通知系统(订单状态、系统告警),要求毫秒级推送,高可用且能自动恢复Actor故障。 |
| 规模指标 | 100万+ WebSocket长连接,单机撑2万并发Actor,日均推送1.2亿条消息。 |
| 技术栈 | Akka 2.6 + Akka HTTP + Scala 2.13 + Redis + Kafka(解耦生产者) |
| 核心难点 | 1) 百万连接下Actor内存与邮箱压力;2) 部分连接异常断开导致父Actor崩溃,需AllForOne监督恢复;3) 消息乱序问题通过自定义Stash邮箱解决。 |
| 面试高频追问 | ① 你用的监督策略是什么?为什么不用OneForOne?② 如何防止Actor重启时丢失未处理消息?③ 邮箱溢出怎么处理? |
| 可迁移回答话术 | “在WebSocket连接组中,每个用户Actor拥有独立状态,但父Actor维护路由表。一旦某个子Actor因网络失败,AllForOne确保整个组感知拓扑变更,统一重新建立连接,避免部分孤儿连接。我们结合BackoffSupervisor和最大重启次数控制,避免雪崩。” |