作为参考,这个问题源于Scala method performance (collect or foreach or other) looping through sockets?
我在actor中存储了对websocket的引用,然后将该actor订阅到Akka EventStream:
val socketActor = system.actorOf(Props(new Actor {
val socket = WebSocketConnection
def receive = {
case d: AppMessage ⇒ socket.send(d)
}
}))
system.eventStream.subscribe(socketActor, classOf[AppMessage])
我错误的是,我可以使用EventStream创建的唯一分类器是类类型。因此,如果您想将消息路由到不同的actor,比如基于userId,您是否需要创建多个EventStream并手动构建一个EventBus,或者这里有什么我缺少的东西?
如果我能做一些简单的事情会很好:
system.eventStream.subscribe(socketActor, Map("userId" -> userId, "teamId" -> teamId) )
这可能仅仅是一个概念性问题,因为我不太确定EventStream代表什么。
答案 0 :(得分:3)
这是我的解决方案,基于ActorEventBus
基于此要点:https://gist.github.com/3757237
我发现这比处理EventStreams更具可维护性。未来可能需要多个EventStream,但此时它很容易支持当前的基础架构。
首先,MessageBus根据PubSub频道处理包含在actor中的套接字的传出消息:
case class MessageEvent(val channel:String, val message:String)
/**
* message bus to route messages to their appropriate contexts
*/
class MessageBus extends ActorEventBus with LookupClassification {
type Event = MessageEvent
type Classifier = String
protected def mapSize(): Int = {
10
}
protected def classify(event: Event): Classifier = {
event.channel
}
protected def publish(event: Event, subscriber: Subscriber): Unit = {
subscriber ! event
}
}
object MessageBus {
val actorSystem = ActorSystem("contexts")
val Bus = new MessageBus
/**
* create an actor that stores a browser socket
*/
def browserSocketContext(s: WebSocketConnection, userId: Long, teamId: Long) = {
val subscriber = actorSystem.actorOf(Props(new BrowserSocket(s,userId,teamId)))
Bus.subscribe( subscriber, "/app/socket/%s" format s.toString)
Bus.subscribe( subscriber, "/app/browser/u/%s" format userId )
Bus.subscribe( subscriber, "/app/browser/t/%s" format teamId )
Bus.subscribe( subscriber, "/app/browser" )
}
}
这是实际包含套接字的actor:
/**
* actor wrapping access for browser socket
*/
class BrowserSocket(
val s: WebSocketConnection,
val userId: Long,
val teamId: Long
) extends Actor {
def receive = {
case payload:MessageEvent =>
s.send(payload.message)
case ping:MessagePing =>
s.ping(ping.data)
}
}
答案 1 :(得分:1)
据我所知,EventStreams和Event Bus用于记录和监控。您通常使用Actors构建所需的功能并在它们之间传递消息。
因此,您将AppMessage
发送给自定义路由器角色,该角色将分拣要发送给哪个后备角色。也许路由器可以在它认为合适时产生后台演员,或者演员可以在路由器上订阅(通过传递适当的消息)。这主要取决于您需要实施的逻辑。