这是一个由两部分组成的问题,首先是设计问题而不是如何实现它,其次是 Akka 的一些实现问题。
我正在使用 Scalatra 构建一个 REST 服务端点,调用该端点时将从多个源中提取图像,对其进行操作并返回它们。这可能是一个相当长的运行过程,并且可能比单个 http 请求/响应周期可以接受的时间更长。
我对此的想法是,当进行调用时,我将启动一堆 akka Actor 来提取图像资源,并让他们将结果交给图像处理 Actor 以进行缩放等。初始请求本身会立即返回某种处理 ID,可用于对另一个端点进行后续轮询调用,该端点将在处理结果时返回结果,并带有一个标志以确定是否有更多结果可让客户端知道停止轮询。
我的问题如下:
- 从设计的角度来看,这有意义吗?
- 如果我使用这种方法,那么每个后续请求以检索已处理的图像都必须具有某种状态意识才能知道客户端已经收到了哪些图像。你将如何管理这种状态?
- 我从来没有看过这个,但是在这种情况下,长时间运行的彗星式 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 的所有图像搜索和图像处理参与者何时完成。我该怎么做呢?
所以这是一个很多问题,我希望它是有道理的消费信息。
干杯。克里斯。