Akka Typed Actor如何获取UDP发送方?无sender()方法的解决方案
Akka Typed中获取UDP发送方Actor Ref的方案
问题背景
在Akka Classic Actor中,存在sender()方法用于获取消息发送方。我使用akka.io.Udp实现向多个Actor进行UDP多播,以下是我的Akka Classic版本代码:
override def preStart(): Unit = { super.preStart() val manager = Udp(context.system).manager println(s"Sending req to bind to ${localInet}") manager ! Udp.Bind(self, localInet) } override def receive: Receive = { case Udp.Bound(localAddress) => { println(s"UdpConn Actor: ${sender()}") println(s"Bound to ${localAddress}") timers.startTimerWithFixedDelay("DISCOVERY", SendDiscovery, 1.seconds) context.become(ready(sender())) } }
由于Akka Typed版本没有sender()方法,请问是否有办法获取UDP发送方的Actor Ref?我曾在Akka文档中搜索IO和UDP的Typed版本相关内容,但未找到相关信息。
解决方案
目前Akka官方并未为UDP IO提供原生的Typed封装,需要通过Classic-Typed适配工具实现需求,具体方案如下:
1. 导入适配工具包
引入Akka的Classic-Typed适配依赖后,导入相关适配包:
import akka.actor.typed.scaladsl.adapter._
2. 在Typed Actor中与Classic UDP Manager交互
- 获取Classic的UDP Manager ActorRef:
val classicManager = context.system.classicSystem.actorOf(Udp.props()) - 发送
Udp.Bind请求时,将Typed Actor自身转换为Classic ActorRef:classicManager ! Udp.Bind(self.toClassic, localInet)
3. 获取UDP发送方的ActorRef
通过context.messageAdapter将Classic的UDP事件转换为Typed消息,同时借助适配后的context.sender()获取发送方:
// 创建消息适配器,转换UDP事件 val udpAdapter = context.messageAdapter[Udp.Event] { case bound: Udp.Bound => // 将Classic发送方ActorRef转换为Typed ActorRef val senderTypedRef = context.sender().toTyped[Udp.Command] // 自定义Typed消息,携带发送方信息 BoundCompleted(bound.localAddress, senderTypedRef) } // 向UDP Manager注册适配器 classicManager ! Udp.Register(udpAdapter.toClassic)
4. 备选方案:通过Classic代理Actor中转
如果直接适配不够直观,可以在Typed Actor中创建一个Classic代理Actor,由它处理UDP IO交互,再将发送方信息传递给Typed Actor:
// 在Typed Actor中创建Classic代理 val udpProxy = context.spawnClassicActor(Props(new Actor { override def receive: Receive = { case Udp.Bound(localAddress) => // 获取发送方并转发给Typed Actor context.parent ! BoundResult(localAddress, sender()) case other => context.parent ! other } }), "udp-proxy") // 向代理发送Bind请求 classicManager ! Udp.Bind(udpProxy, localInet)
通过上述方案,即可在Akka Typed中获取UDP发送方的ActorRef,完成多播相关操作。
内容的提问来源于stack exchange,提问作者tmm
相关产品推荐
相关产品推荐

