Scala+Akka Typed应用无日志输出问题排查求助
聊天应用无日志输出的问题排查与修复
问题描述
开发了由UserActor、Main、RoomActor组成的聊天应用,运行后无任何日志输出。已尝试添加Thread.sleep(5000)、调整logback.xml将root级别设为DEBUG/INFO、用Await.result(system.whenTerminated, Duration.Inf)替换Thread.sleep,问题依旧。
核心错误点与修复方案
1. Main类的ActorSystem初始化错误
错误原因:
- 错误创建了空行为的
ActorSystem(ActorSystem(Behaviors.empty, "ChatSystem")),该系统无法驱动Actor生命周期、处理消息。 - 使用
system.systemActorOf创建子Actor不符合Typed Actor规范,且提前调用system.terminate()导致Actor未处理消息就被终止。 - Main的Behavior定义后未被执行,代码流程直接走到终止逻辑。
修复后的Main代码:
package Chat import akka.actor.typed.{ActorRef, ActorSystem, Behavior} import akka.actor.typed.scaladsl.Behaviors import scala.concurrent.Await import scala.concurrent.duration.Duration object Main extends App { sealed trait MainCommand def apply(): Behavior[MainCommand] = Behaviors.setup { context => // 用context.spawn正确创建子Actor val userActor = context.spawn(UserActor(), "userActor") val roomActor = context.spawn(RoomActor(), "roomActor") // 传递正确的userActor引用,替代deadLetters userActor ! UserActor.CreateUser("John", "Doe", 25, userActor) val roomName = "General" roomActor ! RoomActor.CreateRoom(userActor, roomName) userActor ! UserActor.SendMessageToRoom(roomActor, "Hello, everyone!", "John") Behaviors.receiveMessage { case _ => context.log.info("Unknown message for MainActor") Behaviors.same } } // 启动Main作为ActorSystem的根行为,等待系统终止 val system = ActorSystem(Main(), "ChatSystem") Await.result(system.whenTerminated, Duration.Inf) }
2. UserActor的状态更新失效
错误原因:CreateUser分支中,创建新用户后仅生成了新的用户Map,但未返回携带新状态的userBehavior,导致用户状态无法持久化。后续SendMessageToRoom会因找不到用户抛出异常,Actor重启后日志被吞。
修复后的UserActor关键分支:
case CreateUser(name, surname, age, userActor) => val userId = UUID.randomUUID().toString val newUser = User(name, surname, age, userId, userActor) context.log.info(s"User $newUser added in user list") context.log.info(s"Created user: $userId") // 返回携带新状态的Behavior,更新用户列表 userBehavior(users + (userId -> newUser))
3. UserActor中CreateUser的参数错误
错误原因:
发送CreateUser时传递的userActor是system.deadLetters,导致后续用户消息被发送到死信邮箱,无法触发日志输出。
修复:
在Main中发送消息时,将参数替换为实际的userActor引用:
userActor ! UserActor.CreateUser("John", "Doe", 25, userActor)
4. RoomActor的LeaveRoom逻辑错误
错误原因:
- 使用
rooms.get(roomName).foreach处理房间时,内部返回的roomBehavior会被忽略,导致房间状态无法更新。 - 分支末尾重复输出日志,逻辑混乱导致状态不一致。
修复后的RoomActor LeaveRoom分支:
case LeaveRoom(user, roomName) => rooms.get(roomName) match { case Some(room) => room.users -= user if(user == room.owner) { if(room.users.isEmpty) { context.log.info(s"$user was the owner and the last user in room: $roomName. Removing the room.") roomBehavior(rooms - roomName) } else { val newOwner = room.users.head context.log.info(s"$user was the owner. Assigning the new owner: $newOwner") val updatedRoom = room.copy(owner = newOwner) roomBehavior(rooms + (roomName -> updatedRoom)) } } else { context.log.info(s"$user left the room: $roomName") room.users.foreach { elem => elem ! UserActor.LeftRoomNotification(user, roomName) } roomBehavior(rooms + (roomName -> room)) } case None => context.log.warn(s"Room $roomName does not exist") Behaviors.same }
补充配置说明
确保logback.xml放在src/main/resources下,示例配置:
<configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <root level="INFO"> <appender-ref ref="STDOUT" /> </root> </configuration>
内容的提问来源于stack exchange,提问作者Ch1rae
相关产品推荐
相关产品推荐

