当我收集Spray.io的经验时,我发现有更多方法可以解决这个问题。我发现了一些有时相互矛盾的意见。所以我想请更有经验的用户分享他们的观点。 基本上有一个REST api和分离的服务层都通过蛋糕模式组装如下:
object Main extends App with BootedCore with ServiceActors with RestApi with Web
ServiceActors将ActorRefs保存到各种服务,RestApi保存Spray路由。服务参与者回复案例类。
问题是如何连接这两层?
**可能性1 - 使用akka ask pattern **
import scala.concurrent.ExecutionContext.Implicits.global
//TODO: Excecution context - this is not scalable
val adServiceRoute: Route = {
path("service" / "import" / "status") {
get {
respondWithMediaType(`text/plain`) {
complete {
adImporterService.ask(GetImportStatus)(1 second).mapTo[StatusOfImport]
}
}
}
}
}
implicit val importStatusMarshaller: Marshaller[StatusOfImport] =
Marshaller.of[StatusOfImport](ContentTypes.`text/plain`) { (value, contentType, ctx) =>
val string = "Hello marshalled status"
ctx.marshalTo(HttpEntity(contentType, string))
}
我找到了这个解决方案的一些缺点,我想澄清一下。 - 各种博客蛤蜊问问模式最好避免,如果可能,一些例子推理:例如它隐藏了潜在的错误等。 - 不确定要运行哪个ExcecutionContext。 Import global绝对是正确的。我有的是ActorSystem。为此目的配置分离的调度程序是否常见?
可能性2 - 使用告诉 我试图重写前一个,但无法使其正常工作
val adServiceRoute: Route = {
path("service" / "ad" / "import" / "status") {
get {
respondWithMediaType(`text/plain`) (getServiceStatus)
}
}
}
implicit val importStatusMarshaller: Marshaller[StatusOfImport] =
Marshaller.of[StatusOfImport](ContentTypes.`text/plain`) { (value, contentType, ctx) =>
val string = "Hello marshalled status"
ctx.marshalTo(HttpEntity(contentType, string))
}
def getServiceStatus(ctx: RequestContext): Unit = {
adImporterService.tell(GetImportStatus , ctx.responder)
}
这里的问题是adImporterService的响应是StatusOfImport,响应者不知道如何处理。为了将响应转换为HttpResponse而创建一个每个请求的actor,只是为了处理响应,在我看来是过度的。
我显然遗漏了一些重要的事情。 有人可以更有经验澄清吗?
答案 0 :(得分:0)
我认为你可以使用spray的onComplete
指令。例如:
onComplete(adImporterService.ask(GetImportStatus).mapTo[StatusOfImport]) {
case Success(v) => complete(v)
case Failure(e) => ...
}