在负载下快速失败(通过设置请求超时)

时间:2017-10-24 13:52:07

标签: scala playframework akka-http

我们有一个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
  }

}

在进行一些负载测试后,我得到的结果是:

Gatling results

如果忽略连接超时并且"无法打开套接字"错误(可能是我的笔记本电脑的限制),还有超过60秒的大量请求(以及返回的503s)。

最后,问题

  1. 是否可以实现此故障快速方案?
  2. 预计这对重负荷是否敏感?
  3. 如果我的设置出现问题,我该如何解决?

0 个答案:

没有答案