我正在尝试在Akka的actor模型之上实现Event Bus(Pub-Sub)模式。
“Native”EventBus实现不符合我的一些要求(例如,在主题中仅保留最后一条消息的可能性,它特定于MQTT协议,我正在为它实现消息代理{{3} })。
我的EventBus的当前界面如下:
object Bus {
case class Subscribe(topic: String, actor: ActorRef)
case class Unsubscribe(topic: String, actor: ActorRef)
case class Publish(topic: String, payload: Any, retain: Boolean = false)
}
用法如下:
val system = ActorSystem("System")
val bus = system.actorOf(Props[MqttEventBus], name = "bus")
val device1 = system.actorOf(Props(new DeviceActor(bus)))
val device2 = system.actorOf(Props(new DeviceActor(bus)))
所有设备都引用了一个总线actor。总线参与者负责存储所有订阅状态和主题(例如保留消息)。
内部的设备角色可以决定发布,订阅或取消订阅主题。
经过一些性能基准后,我意识到我当前的设计会影响发布和订阅之间的处理时间,原因如下:
如何为我的事件总线实施分发(并行化)工作负载? 目前的解决方案是否适合akka-cluster?
目前,我正在考虑通过以下几种Bus实例https://github.com/butaji/JetMQ:
val paths = (1 to 5).map(x => {
system.actorOf(Props[EventBusActor], name = "event-bus-" + x).path.toString
})
val bus_publisher = system.actorOf(RoundRobinGroup(paths).props())
val bus_manager = system.actorOf(BroadcastGroup(paths).props())
其中:
如下所示,它将在所有总线上复制状态,并通过负载分配减少每个actor的队列。
答案 0 :(得分:1)
您可以在单身公交车内部而不是在外面行驶。您的总线可能负责路由消息和建立主题,而子Actors可能负责分发消息。一个基本示例,演示了我所描述的内容,但没有取消订阅功能,重复订阅检查或监督:
import scala.collection.mutable
import akka.actor.{Actor, ActorRef}
class HashBus() extends Actor {
val topicActors = mutable.Map.empty[String, ActorRef]
def createDistributionActor = {
context.actorOf(Props[DistributionActor])
}
override def receive = {
case subscribe : Subscribe =>
topicActors.getOrElseUpdate(subscribe.topic, createDistributionActor) ! subscribe
case publish : Publish =>
topicActors.get(topic).foreach(_ ! publish)
}
}
class DistributionActor extends Actor {
val recipients = mutable.List.empty[ActorRef]
override def receive = {
case Subscribe(topic: String, actorRef: ActorRef) =>
recipients +: actorRef
case publish : Publish =>
recipients.map(_ ! publish)
}
}
这将确保您的总线Actor邮箱不会饱和,因为总线的工作只是进行哈希查找。 DistributionActors将负责映射收件人并分发有效负载。同样,DistributionActor可以保留主题的任何状态。