客户端会话存储在akka-http服务器中

时间:2016-01-26 02:24:11

标签: akka-stream akka-http

在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?
    }

我怀疑我可能误解了整个范例,试图使其合适。我无法判断是否有任何内置或需要手动实施的内容。

2 个答案:

答案 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。它确保会话数据安全且不会被篡改。