在akka-http服务中,每个客户端会话如何缓存一些信息?这在文档中并不十分明显。我想为每个连接创建一个actor。
我应该在哪里创建演员,如何从舞台内部引用它?
我的服务受到以下约束:
val serverSource: Source[Http.IncomingConnection, Future[Http.ServerBinding]] =
Http().bind(interface = bindAddress, port = bindPort)
val bindingFuture: Future[Http.ServerBinding] =
serverSource
.to(Sink.foreach { connection =>
connection.handleWithSyncHandler (requestHandler)
// seems like I should set up some session state storage here,
// such as my actor
})
.run()
...
以及后来:
val packetProcessor: Flow[A, B, Unit] = Flow[A]
.map {
case Something =>
// can i use the actor here, or access my session state?
}
我怀疑我可能误解了整个范例,试图使其合适。我无法判断是否有任何内置或需要手动实施的内容。
答案 0 :(得分:1)
我发现Agent
是一种非常方便的并发缓存机制。
例如,假设您希望保持已连接的所有远程地址的运行Set
。您可以设置代理来存储值,并设置Flow
来写入缓存:
import scala.concurrent.ExecutionContext.Implicits.global
import akka.agent.Agent
import scala.collection.immutable
val addressCache = Agent(immutable.Set.empty[java.net.InetSocketAddress])
import akka.stream.scaladsl.Flow
val cacheAddressFlow = Flow[IncomingConnection] map { conn =>
addressCache send (_ + conn.remoteAddress) //updates the cache
conn //forwards the connection to the rest of the stream
}
此流程可以成为您的Stream的一部分:
val bindingFuture: Future[Http.ServerBinding] =
serverSource.via(cacheAddressFlow)
.to(Sink.foreach { connection =>
connection.handleWithSyncHandler (requestHandler)
})
.run()
然后,您可以在绑定逻辑之外完全“查询”缓存:
def somewhereElseInTheCode = {
val currentAddressSet = addressCache.get
println(s"address count so far: ${currentAddressSet.size}")
}
如果您的目标是将所有IncomingConnection
值发送到Actor
进行处理,则可以使用Sink.actorRef
完成此操作:
object ConnectionStreamTerminated
class ConnectionActor extends Actor {
override def receive = {
case conn : IncomingConnection => ???
case ConnectionStreamTerminated => ???
}
}
val actorRef = actorSystem actorOf Props[ConnectionActor]
val actorSink =
Sink.actorRef[IncomingConnection](actorRef, ConnectionStreamTerminated)
val bindingFuture: Future[Http.ServerBinding] =
serverSource.runWith(actorSink)
答案 1 :(得分:1)
由于建议的代理商已被弃用。我建议使用akka-http-session
。它确保会话数据安全且不会被篡改。