加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 基于演员的网络服务 – 如何正确执行?

发布时间:2020-12-16 09:44:11 所属栏目:安全 来源:网络整理
导读:在过去的几个月里,我和我的同事已经成功地建立了一个服务器端系统,用于向iPhone设备发送推送通知。基本上,用户通过RESTful Web服务注册这些通知( Spray-Server,最近更新为使用 Spray-can作为HTTP层),并且使用Akka的调度程序,将来使用逻辑调度一个或多
在过去的几个月里,我和我的同事已经成功地建立了一个服务器端系统,用于向iPhone设备发送推送通知。基本上,用户通过RESTful Web服务注册这些通知( Spray-Server,最近更新为使用 Spray-can作为HTTP层),并且使用Akka的调度程序,将来使用逻辑调度一个或多个消息以进行调度。

这个系统,正如我们构建的一样,它的工作原理是:它可以处理数百个甚至数千个HTTP请求,并且可以以每秒23,000的速度发送通知 – 如果我们减少日志输出,可以增加多个通知发件人演员(以及与苹果更多的连接),并且可能会在我们使用的Java库中进行一些优化(java-apns)。

这个问题是关于如何做到Right(tm)。我的同事对Scala和基于演员的系统总体了解更多,指出应用程序不是一个“纯粹的”基于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))
  }
}

现在,如果我得到这个权利,一个演员的“等待响应”是基于演员的编程中的一个no-no(加上不被弃用的)。我认为“正确”的方法是将请求对象传递给消息中的持久性actor,并在后端收到生成的ID后立即调用request.complete。

我已经在我的应用程序中重写了一条路线,做到这一点;在发送给演员的消息中,请求对象/引用也被发送。这似乎像这样应该是:

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

我主要关心的是,我们似乎将请求对象传递给“业务逻辑”,在这种情况下是持久化。持有者现在得到额外的责任,即呼叫请求完整,以及关于它运行什么系统的知识,即它是Web服务的一部分。

处理这样的情况的正确方法是什么,以便持久性的演员不知道它是http服务的一部分,并且不需要知道如何输出生成的ID?

我认为这个请求应该仍然被传递给持久性的演员,而不是调用request.complete的Persister actor,而是发送一个消息给HttpService actor(一个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)
  }
}

我用这种方式在正确的轨道上吗?

一个较小的二次喷雾服务器的具体问题,是否可以继承HttpService并覆盖接收方法,否则我会以这种方式破解? (我没有关于子类化演员的线索,或者如何将无法识别的消息传递给“父”演员)

最后的问题是,在可能通过整个应用程序的一个可行方法的actor消息中传递请求对象/引用,或者是否有更好的方式“记住”在通过应用程序流动请求之后应该发送响应的请求?

解决方法

对于你的第一个问题,是的,你是在正确的轨道上。 (虽然我也想看一些替代方法来处理这种问题)。

我有一个建议是让持续演员绝对不了解请求。您可以将请求作为任何类型传递。您的服务代码中的匹配器可以将Cookie自动转换为请求。

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))
}

关于你的第二个问题,演员班真的没有什么不同于普通班。但是您确实需要确保调用超类的接收方法,以便它可以处理自己的消息。我还有其他一些方法来做这个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
  }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读