我目前正在尝试使用自动发现服务实现群集播放+ akka实现。但是,我似乎遇到了包含在游戏中的Guice DI加载器的问题。从他们的文档的摘录指出:带有播放框架的Akka群集设置
https://www.playframework.com/documentation/2.5.x/ScalaAkka#Integrating-with-Akka
虽然我们建议您使用内置的演员系统,因为它设置了一切,如正确的类加载器,生命周期挂钩,等等,没有什么能阻止你从使用你自己的演员系统。但重要的是确保您执行以下操作:
当播放关闭时,注册一个停止挂钩以关闭演员系统 从播放环境传递正确的类加载器,否则Akka将无法找到您的应用程序类
请确保您更改Play使用play.akka.config读取其akka配置的位置,或者您未从缺省akka配置中读取您的akka配置,因为这会导致出现问题,例如何时系统尝试绑定到相同的远程端口
我有d一个以上配置然而,他们建议我似乎无法避开Play仍会结合它从BuiltInModule内部ActorSystemProvider:
class BuiltinModule extends Module {
def bindings(env: Environment, configuration: Configuration): Seq[Binding[_]] =
{
def dynamicBindings(factories: ((Environment, Configuration) => Seq[Binding[_]])*) = {
factories.flatMap(_(env, configuration))
}
Seq(
bind[Environment] to env,
bind[ConfigurationProvider].to(new ConfigurationProvider(configuration)),
bind[Configuration].toProvider[ConfigurationProvider],
bind[HttpConfiguration].toProvider[HttpConfiguration.HttpConfigurationProvider],
// Application lifecycle, bound both to the interface, and its implementation, so that Application can access it
// to shut it down.
bind[DefaultApplicationLifecycle].toSelf,
bind[ApplicationLifecycle].to(bind[DefaultApplicationLifecycle]),
bind[Application].to[DefaultApplication],
bind[play.Application].to[play.DefaultApplication],
bind[Router].toProvider[RoutesProvider],
bind[play.routing.Router].to[JavaRouterAdapter],
bind[ActorSystem].toProvider[ActorSystemProvider],
bind[Materializer].toProvider[MaterializerProvider],
bind[ExecutionContextExecutor].toProvider[ExecutionContextProvider],
bind[ExecutionContext].to[ExecutionContextExecutor],
bind[Executor].to[ExecutionContextExecutor],
bind[HttpExecutionContext].toSelf,
bind[CryptoConfig].toProvider[CryptoConfigParser],
bind[CookieSigner].toProvider[CookieSignerProvider],
bind[CSRFTokenSigner].toProvider[CSRFTokenSignerProvider],
bind[AESCrypter].toProvider[AESCrypterProvider],
bind[play.api.libs.Crypto].toSelf,
bind[TemporaryFileCreator].to[DefaultTemporaryFileCreator]
) ++ dynamicBindings(
HttpErrorHandler.bindingsFromConfiguration,
HttpFilters.bindingsFromConfiguration,
HttpRequestHandler.bindingsFromConfiguration,
ActionCreator.bindingsFromConfiguration
)
}
}
我曾尝试创建我自己的GuiceApplicationBuilder不过,为了绕过这个,现在它只是相反,移动重复绑定异常来自BuiltInModule。
这里就是我想:
AkkaConfigModule:
package module.akka
import com.google.inject.{AbstractModule, Inject, Provider, Singleton}
import com.typesafe.config.Config
import module.akka.AkkaConfigModule.AkkaConfigProvider
import net.codingwell.scalaguice.ScalaModule
import play.api.Application
/**
* Created by dmcquill on 8/15/16.
*/
object AkkaConfigModule {
@Singleton
class AkkaConfigProvider @Inject() (application: Application) extends Provider[Config] {
override def get() = {
val classLoader = application.classloader
NodeConfigurator.loadConfig(classLoader)
}
}
}
/**
* Binds the application configuration to the [[Config]] interface.
*
* The config is bound as an eager singleton so that errors in the config are detected
* as early as possible.
*/
class AkkaConfigModule extends AbstractModule with ScalaModule {
override def configure() {
bind[Config].toProvider[AkkaConfigProvider].asEagerSingleton()
}
}
ActorSystemModule:
package module.akka
import actor.cluster.ClusterMonitor
import akka.actor.ActorSystem
import com.google.inject._
import com.typesafe.config.Config
import net.codingwell.scalaguice.ScalaModule
import play.api.inject.ApplicationLifecycle
import scala.collection.JavaConversions._
/**
* Created by dmcquill on 7/27/16.
*/
object ActorSystemModule {
@Singleton
class ActorSystemProvider @Inject() (val lifecycle: ApplicationLifecycle, val config: Config, val injector: Injector) extends Provider[ActorSystem] {
override def get() = {
val system = ActorSystem(config.getString(NodeConfigurator.CLUSTER_NAME_PROP), config.getConfig("fitnessApp"))
// add the GuiceAkkaExtension to the system, and initialize it with the Guice injector
GuiceAkkaExtension(system).initialize(injector)
system.log.info("Configured seed nodes: " + config.getStringList("fitnessApp.akka.cluster.seed-nodes").mkString(", "))
system.actorOf(GuiceAkkaExtension(system).props(ClusterMonitor.name))
lifecycle.addStopHook {() =>
system.terminate()
}
system
}
}
}
/**
* A module providing an Akka ActorSystem.
*/
class ActorSystemModule extends AbstractModule with ScalaModule {
import module.akka.ActorSystemModule.ActorSystemProvider
override def configure() {
bind[ActorSystem].toProvider[ActorSystemProvider].asEagerSingleton()
}
}
加载应用程序:
class CustomApplicationLoader extends GuiceApplicationLoader {
override def builder(context: ApplicationLoader.Context): GuiceApplicationBuilder = {
initialBuilder
.overrides(overrides(context): _*)
.bindings(new AkkaConfigModule, new ActorSystemModule)
}
}
主要的事情,我的东东要完成的是配置ActorSystem,以便我可以以编程方式加载Akka集群的种子节点。
上述方法是正确的方法还是有更好的方法来实现这一目标?如果这是正确的方法,有什么我从根本上不理解与DI设置玩/吉斯?
更新
对于这种架构,播放+阿卡位于同一节点上。
当我最初以此为例进行构建时,我查看了该模板。但是,我正在尝试的架构是在同一个节点上播放+ akka,这样每个播放节点中都有一个actor系统。 – dmcqu314