当前位置: 首页 > 知识库问答 >
问题:

具有HTTP接口的Akka actor系统

司徒寒
2023-03-14

我正在尝试创建一个Akka系统,它将响应HTTP请求。我创造了几个可以很好地交换信息的演员。我还可以使用akka-http来响应HTTP请求。问题在于如何将这两部分连接起来。

TL;DR:如何在akka-http请求处理过程中与Akka参与者对话?

我创建了一个单独的参与者来负责启动HTTP系统:

class HttpActor extends Actor with ActorLogging  {
  /* implicits elided */

  private def initHttp() = {
    val route: Route =  path("status") { get { complete { "OK" } } }
    Http()(context.system).bindAndHandle(route, "localhost", 8080)
  }
  private var bound: Option[Future[Http.ServerBinding]] = None

  override def receive = {
    case HttpActor.Init =>
      bound match {
        case Some(x) => log.warning("Http already bootstrapping")
        case None =>
          bound = Some(initHttp(watcher))
      }

  }
}

object HttpActor {
  case object Init
}

正如您可能看到的,执行元在它接收到的第一条消息上创建akka-http服务(没有理由,实际上,它也可以在构造函数中这样做)。

  private def initInteractiveHttp() = {
    val route: Route =  path("status") { 
      get { complete { "OK" } } 
    } ~ path("ask") {
      get { complete {
        // Here are the interesting two lines:
        val otherActorResponse = someOtherActor ? SomeMessage
        otherActorResponse.mapTo[String]
    } }
    Http()(context.system).bindAndHandle(route, "localhost", 8080)
  }

这将向SomeMessage发送SomeOtherActor并在完成请求-响应循环之前等待响应。然而,据我所知,消息将从根httpactor发送,这是不好的,在可伸缩性方面没有任何意义。理想情况下,我将为每个请求创建一个不同的专用actor实例,但由于akka-http类型,这将失败。请考虑以下示例:

class DisposableActor(httpContext: HttpContext) {
    override def preStart() = {
       // ... send some questions to other actors
    }
    override def receive = {
      case GotAllData(x) => httpContext.complete(x)
    }
}

class HttpActorWithDisposables {
  // there is a `context` value in scope - we're an actor, after all
  private def initHttpWithDisposableActors() = {
    val route: Route =  path("status") { 
      get { complete { "OK" } } 
    } ~ path("ask") {
      get { httpContext =>
        val props = Props(new DisposableActor(httpContext))
        val disposableActor = context.actorOf(props, "disposable-actor-name")
        // I have nothing to return here
      }
    }
    Http()(context.system).bindAndHandle(route, "localhost", 8080)
  }

通过这种方法,我可以强制DisposableActor在某个时间点调用HttpContext.Complete。这应该正确地结束请求-响应处理周期。然而,路由DSL要求在get块内返回有效的响应(或Future),因此这种方法不起作用。

共有1个答案

商燕七
2023-03-14

实际上,你的第一种方法是很好的。ask模式为您创建了一个轻量级的、一次性的actor,它等待结果(非阻塞地)来完成将来的任务。它基本上完成了您想要用DisposableActor复制的所有事情,您的主HttpActor不会因此而受到压力。

如果仍要使用其他执行元,则有completeWith:

completeWith(instanceOf[String]) { complete =>
  // complete is of type String => Unit
  val props = Props(new DisposableActor(complete))
  val disposableActor = context.actorOf(props, "disposable-actor-name")

  // completeWith expects you to return unit
}

在您的actor中,当您得到结果时调用complete函数

class DisposableActor(complete: String => Unit) {
  override def receive = {
    case GotAllData(x) => 
      complete(x)
      context stop self // don't for get to stop the actor
  }
}
 类似资料:
  • 问题内容: 根据Hibernate文档的这一部分,我应该能够查询HQL中的任何Java类。 http://docs.jboss.org/hibernate/core/3.3/reference/en/html/queryhql.html#queryhql- polymorphism 不幸的是,当我运行此查询时… 我收到消息“未映射事务[[从事务trans,其中trans.envelopeId =:

  • HTTP接口 创建直播间 通过该接口可以创建直播间,接口请求地址为: https://api.csslcloud.net/api/room/create 需要传递以下参数: 参数 说明 备注 userid CC账户ID name 直播间名称,最大字符40 标题头尾的空格字符会自动删除 desc 直播间描述,最大字符5000 templatetype 直播模板类型,请求模板信息接口可获得模板类型的

  • 问题内容: 我需要用c 编写一个库,客户端可以使用它在远程服务器上执行一些操作。我唯一还没有做的事情是:C 库需要一个C接口。让我更好地解释一下:从使用此lib的客户端中,我需要调用以下内容:int operation(void * addr); 如果int <0错误,等等。但是该库是c 中的类。所以我的答案是..是否需要一个全局变量在库中保存类的实例?开发C 类的C接口有更好的选择吗? 谢谢建议

  • 使用方式:import core "github.com/lengzhao/govm/app/chain1/ae4a05b2b8a4de21d9e6f26e9d7992f7f33e89689f3015f3fc8a3a3278815e28c" 接口中所有的user都需要使用合约的私有结构体作为参数。如第二章中的样例Event接口 接口的具体实现可以查看源码:govm/app/chain1/ae4a0

  • 问题内容: 我正在学习如何使用JavaScript进行OOP。它具有接口概念(例如Java的接口)吗? 这样我就可以创建一个侦听器… 问题答案: 没有“此类必须具有这些功能”的概念(也就是说,本身没有接口),因为: JavaScript继承基于对象,而不是类。除非您意识到:这不是什么大不了的事情 JavaScript是一种 非常 动态的类型化语言-您可以使用适当的方法创建对象,这将使其符合接口,

  • 我有这些实体: 用户 角色 权限 一个用户有很多角色,一个角色有很多权限。 null