我们有一个Play 2.6.x应用程序,目前正在进行压力测试(使用Gatling)。在负载很重的情况下,如果应用程序快速响应(即在100毫秒内),我们不会介意请求失败。该操作会执行一些CPU工作和一些IO - 所有异步(但使用存根禁用IO会产生相同的结果)
我们注意到,当应用程序处于负载状态时,设置akka.http.server.request-timeout=100ms
没有任何区别 - 第99个百分点仍然会爆炸到几秒钟,有些请求需要超过60秒(这是Gatling给出的点) Request Timeout
例外)。
在某种程度上重现,在一个更加孤立的环境中,我使用了https://github.com/playframework/play-scala-starter-example并添加了一些操作,这些操作使不同的线程以不同的方式进入睡眠状态(在线程池和方法之间切换)。以下是我定义的行动:
package controllers
import javax.inject._
import akka.actor.ActorSystem
import play.api.Configuration
import play.api.mvc._
import scala.concurrent.duration._
import scala.concurrent.{ExecutionContext, Future, Promise, blocking}
@Singleton
class AsyncController @Inject()(
cc: ControllerComponents,
actorSystem: ActorSystem,
configuration: Configuration
)(implicit exec: ExecutionContext) extends AbstractController(cc) {
def message_delay = Action.async {
getFutureMessage(1.second).map { msg => Ok("hello") }
}
def message_delay_bg = Action.async {
getFutureMessage(1.second)(ExecutionContext.global).map { msg => Ok("hello") }
}
def message_sleep = Action.async {
Future {
Thread.sleep(1000)
Ok("hello")
}
}
def message_sleep_bg = Action.async {
Future {
Thread.sleep(1000)
Ok("hello")
}(ExecutionContext.global)
}
def message_block_sleep = Action.async {
Future {
blocking {
Thread.sleep(1000)
Ok("hello")
}
}
}
def message_block_sleep_bg = Action.async {
Future {
blocking {
Thread.sleep(1000)
Ok("hello")
}
}(ExecutionContext.global)
}
private def getFutureMessage(delayTime: FiniteDuration)(implicit ec: ExecutionContext): Future[String] = {
val promise: Promise[String] = Promise[String]()
actorSystem.scheduler.scheduleOnce(delayTime) {
promise.success("Hi!")
}(ec) // run scheduled tasks using the actor system's dispatcher
promise.future
}
}
在进行一些负载测试后,我得到的结果是:
如果忽略连接超时并且"无法打开套接字"错误(可能是我的笔记本电脑的限制),还有超过60秒的大量请求(以及返回的503s)。
最后,问题