3

我有一个 Play 2.x 应用程序,并在 Heroku 上运行,只有一个网络测功机。

在启动时,会触发一个 Akka actor,它自己会安排未来的作业(例如发送推送通知)。

object Global extends GlobalSettings {

  override def onStart(app:Application) {
    val actor = Akka.system.actorOf(Props[SomeActor])
    Akka.system.scheduler.scheduleOnce(0 seconds, actor, None)
  }
}

这适用于一个网络测功机,但我很想知道如果我增加网络测功机的数量会发生什么。onStart 会用两个网络测功机执行两次吗?

如果Global真的在全球范围内工作并且onStart只执行一次,与网络测功机的数量无关,那就太好了。如果没有,多个测功机必须以某种方式就一个负责完成这项工作的测功机达成一致。

有没有人遇到过类似的问题?

4

2 回答 2

5

如果您运行两个网络测功机,您的全局将执行两次。全局对于流程来说是全局的。当您扩展您的 Web 进程时,您正在运行两个进程。你有几个选择:

  • 使用不同的进程(又名单例进程)来运行你的全局。Play 的好处是你可以有多个GlobalSettings实现。当你开始你的过程时,你指定你想要使用的全局-Dapplication.global=YourSecondGlobal。那么,在您的 procfile 中,您将拥有singleton: target/start -Dhttp.port=${PORT} ${JAVA_OPTS} -Dapplication.global=YourSecondGlobal. 启动您的 Web 进程和singleton进程,并确保singleton缩放到 1。
  • 使用分布式信号量获取锁。然后每个进程将竞相获得锁——获胜的进程将继续执行,其他进程将失败。如果您正在使用 Postgres(正如许多人在 Heroku 上所做的那样),建议锁是一个不错的选择。
于 2013-03-07T19:27:39.707 回答
2

您还可以在运行时获取测功机名称:

String dyno = System.getenv("DYNO");

所以做这样的检查也可能有效:

if(dyno.equals("web.1")) {

}
于 2014-03-05T22:27:35.373 回答