首页 > 解决方案 > 第一次调用时播放框架很慢

问题描述

我有一个问题,启动后播放框架。

我有这个简单的控制器:

@Singleton
class BomberManController @Inject()(cc: ControllerComponents) extends AbstractController(cc) {

  def index() = Action { implicit request: Request[AnyContent] =>
    Ok("test")
  }
}

在第一次调用时,在 prod env 上,请求需要 400 毫秒,第二次请求需要 2 毫秒。

我不明白为什么以及如何优化它。在我的项目中,请求必须少于 300 毫秒。

你有什么想法吗?

播放版本:2.6

标签: scalaplayframework

解决方案


一种选择是创建一个虚拟对象Request并将其直接应用到控制器的构造函数中index.apply(request)。考虑下面方法的定义和调用点warmUp

@Singleton 
class BomberManController @Inject()(cc: ControllerComponents) extends AbstractController(cc) {

  warmUp()

  def index() = Action { implicit request: Request[AnyContent] =>
    Ok("test")   
  }

  private def warmUp() = {
    val requestFactory = new DefaultRequestFactory(HttpConfiguration())
    val request =
      requestFactory.createRequest(
        RemoteConnection("127.0.0.1", false, None),
        "GET",
        RequestTarget("/", "/", Map.empty),
        "HTTP/1.1",
        Headers(),
        TypedMap.empty,
        AnyContentAsEmpty
      )
    index.apply(request)   
  } 
}

在生产BomberManController中是在应用程序启动时实例化的,因此warmUp将被调用,进而到达index端点。

play.http.secret.key要在本地测试此生产行为,请设置application.conf并启动应用程序

 sbt clean runProd

如果您不希望使用warmUp实用程序方法污染您的控制器,您可以将此关注点分离为实用程序单例,例如WarmUpUtility,并使用急切的单例绑定。例如:

@Singleton 
class WarmUpUtility @Inject()(bomberManController: BomberManController)() {

  warmUp()

  private def warmUp() = {
    val requestFactory = new DefaultRequestFactory(HttpConfiguration())
    val request =
      requestFactory.createRequest(
        RemoteConnection("127.0.0.1", false, None),
        "GET",
        RequestTarget("/", "/", Map.empty),
        "HTTP/1.1",
        Headers(),
        TypedMap.empty,
        AnyContentAsEmpty
      )
    bomberManController.index.apply(request)
  }

}

// Module should be in the root package 
class Module extends AbstractModule {
  override def configure() = {
    bind(classOf[WarmUpUtility]).asEagerSingleton()
  }
}

推荐阅读