gpt4 book ai didi

scala - 基于Actor的Web服务-如何正确执行?

转载 作者:行者123 更新时间:2023-12-03 11:43:34 25 4
gpt4 key购买 nike

在过去的几个月中,我和我的同事们成功地构建了一个服务器端系统,用于向iPhone设备发送推送通知。基本上,用户通过RESTful Web服务(Spray-Server,最近更新为使用Spray-can作为HTTP层)注册这些通知,并且该逻辑使用Akka的调度程序调度一条或多条消息以供将来调度。

这个系统在我们构建时就可以正常工作:它每秒可以处理数百个,甚至数千个HTTP请求,并且可以每秒23,000个的速度发送通知-如果我们减少日志输出,添加多个通知,则可能更多发送方参与者(从而与Apple有更多联系),并且在我们使用的Java库(java-apns)中可能需要进行一些优化。

这个问题是关于如何做Right(tm)。我的同事通常对Scala和基于actor的系统了解更多,他指出该应用程序不是基于“纯” actor的系统-他是对的。我现在想知道的是正确的做法。

目前,我们只有一个不带子类的Spray HttpService actor,它使用一组概述HTTP服务逻辑的指令进行初始化。当前,已经非常简化了,我们有这样的指令:

post {
content(as[SomeBusinessObject]) { businessObject => request =>
// store the business object in a MongoDB back-end and wait for the ID to be
// returned; we want to send this back to the user.
val businessObjectId = persister !! new PersistSchedule(businessObject)
request.complete("/businessObject/%s".format(businessObjectId))
}
}

现在,如果我做对了,在基于actor的编程中,来自actor的“等待响应”是不可以的(不建议使用!!!)。我认为,这样做的“正确”方法是将 request对象传递给消息中的 persister actor,并在从后端收到生成的ID后立即调用 request.complete

我已经在我的应用程序中重写了其中一条路线来完成此操作;在发送给参与者的消息中,还发送了请求对象/引用。这似乎可以正常工作:
  content(as[SomeBusinessObject]) { businessObject => request =>
persister ! new PersistSchedule(request, businessObject)
}

我主要的担心是,我们似乎将 request对象传递给了“业务逻辑”,在这种情况下是持久性。持久性现在将承担额外的责任,即调用 request.complete,并了解其在哪个系统中运行,即它是Web服务的一部分。

解决这种情况的正确方法是什么,以使持久性参与者不知道它是http服务的一部分,并且不需要知道如何输出生成的ID?

我认为请求仍应传递给持久性参与者,而不是持久性参与者调用request.complete,而是将消息发送回HttpService参与者( SchedulePersisted(request, businessObjectId)消息),后者仅调用 request.complete("/businessObject/%s".format(businessObjectId))。基本上:
def receive = {
case SchedulePersisted(request, businessObjectId) =>
request.complete("/businessObject/%s".format(businessObjectId))
}

val directives = post {
content(as[SomeBusinessObject]) { businessObject => request =>
persister ! new PersistSchedule(request, businessObject)
}
}

我采用这种方法走的正确吗?

一个较小的特定于 spray-server的辅助问题,可以将 HttpService子类化并覆盖receive方法,还是可以这样破坏事情? (我不知道将 Actor 归类,也不知道如何将无法识别的消息传递给“ parent ” Actor )

最后一个问题,是在可能贯穿整个应用程序传递的actor消息中传递 request对象/引用,这是一种好的方法,还是有一种更好的方法来“记住”在将请求流经应用程序后应向哪个请求发送响应?

最佳答案

关于第一个问题,是的,您的方向正确。 (尽管我也希望看到一些替代方法来处理此类问题)。

我的一个建议是使persister参与者完全不了解请求。您可以将请求作为Any类型传递。服务代码中的匹配器可以自动将cookie转换回Request

case class SchedulePersisted(businessObjectId: String, cookie: Any)

// in your actor
override def receive = super.receive orElse {
case SchedulePersisted(businessObjectId, request: Request) =>
request.complete("/businessObject/%s".format(businessObjectId))
}

关于第二个问题, Actor 课与普通课没有什么不同。但是您确实需要确保调用父类(super class)的 receive方法,以便它可以处理自己的消息。我还有其他方法可以做到这一点 in my original answer,但我想我更喜欢 chaining partial functions like this:
class SpecialHttpService extends HttpService {
override def receive = super.receive orElse {
case SpecialMessage(x) =>
// handle special message
}
}

关于scala - 基于Actor的Web服务-如何正确执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9226568/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com