5

这是一个由两部分组成的问题,首先是设计问题而不是如何实现它,其次是 Akka 的一些实现问题。

我正在使用 Scalatra 构建一个 REST 服务端点,调用该端点时将从多个源中提取图像,对其进行操作并返回它们。这可能是一个相当长的运行过程,并且可能比单个 http 请求/响应周期可以接受的时间更长。

我对此的想法是,当进行调用时,我将启动一堆 akka Actor 来提取图像资源,并让他们将结果交给图像处理 Actor 以进行缩放等。初始请求本身会立即返回某种处理 ID,可用于对另一个端点进行后续轮询调用,该端点将在处理结果时返回结果,并带有一个标志以确定是否有更多结果可让客户端知道停止轮询。

我的问题如下:

  1. 从设计的角度来看,这有意义吗?
  2. 如果我使用这种方法,那么每个后续请求以检索已处理的图像都必须具有某种状态意识才能知道客户端已经收到了哪些图像。你将如何管理这种状态?
  3. 我从来没有看过这个,但是在这种情况下,长时间运行的彗星式 HTTP 请求会比轮询更有意义吗?

实施部分

假设我最终得到了类似于上面的设计,我对 Scalatra 和 Akka(或任何 Actor 范例)非常陌生,我有几个问题。

好的,第一个是我认为的 Scala/Scalatra 特定问题。好的,我查看了 akka http://www.scalatra.org/guides/async/akka.html上的 Scalatra 文档,在此示例中,他们设置应用程序引导程序如下:

 // Get a handle to an ActorSystem and a reference to one of your actors
  val system = ActorSystem()
  val myActor = system.actorOf(Props[MyActor])

  // In the init method, mount your servlets with references to the system
  // and/or ActorRefs, as necessary.
  override def init(context: ServletContext) {
    context.mount(new PageRetriever(system), "/*")
    context.mount(new MyActorApp(system, myActor), "/actors/*")
  }

我假设 scalatra 的引导在应用程序启动时发生一次,那么 system.actorOf(Props[MyActor]) 是创建一个实例还是每个请求一个实例?

其次,假设我的 MyActor 类(或更合理的名称)做了以下事情:

class MyActor extends Actor {
  def receive = {
    //Find the [ImageSearchingActor] actor in akka registry and send search message
    case initiateSearchRequest: InitiateSearchRequestMessage => TODO

    //Find free [ImageProcessingActors] in akka registry and send each Image url to process  
    case imageInformationFound : ImageInformationFoundMessage => TODO

    //Persist the result to a cache, or data store with the ProcessingId that all message will pass  
    case imageProcessed : ImageProcessedMessage =>  TODO
  }
}

现在,在这种情况下,我将在多个地方检索图像,因此多个 Actor 将获取这些数据。当他们找到合适的图像时,将使用几个 Actor 来处理图像。如果我采用我的设计,那么我需要在某个地方标记对于给定的 ProcessingId 没有更多可用的处理图像。这意味着我需要知道给定 ProcessingId 的所有图像搜索和图像处理参与者何时完成。我该怎么做呢?

所以这是一个很多问题,我希望它是有道理的消费信息。

干杯。克里斯。

4

1 回答 1

3

这里有很多问题。快速回答:

  1. 是的,我想是这样。

  2. 您可能希望将一个 Actor 类用作聚合器、主控器或协调器,从而启动图像检索和图像处理 Actor 类。然后,聚合器包含您的整体计算何时可以被视为完成的逻辑。互联网上有很多此类事情的示例,如果您想要具体示例与您正在做的事情相匹配,请确保查看 Akka 2.1.x 示例,因为这可能是您需要的重新使用当前的 Scalatra 代码库。

  3. 这可能是个好主意。Scalatra 与 Atmosphere 框架集成,这使得进行 websocket/comet 长轮询非常容易。您可以在 docs中阅读。它是否对您的应用程序有意义取决于很多因素,但值得一看。以我的经验,套接字编程有时会令人惊叹,有时比它的价值更麻烦 - 例如,如果您要通过大量代理,除非使用 SSL,否则 websockets 会出现问题。不过,看到信息一旦可用就被推送到客户端是一件很美好的事情。

对于另一个问题,关于 ActorSystem 创建:

在 Scalatra 中,您的控制器是根据每个请求实例化的;您的示例代码中的 ActorSystem 只会被初始化一次。每当有请求进来时,就会创建一个新的控制器实例,并引用 ActorSystem。

ActorSystem 创建是一个重量级操作,应该尽可能少地发生。

于 2013-04-13T10:45:41.803 回答