如何创建一个带有延迟的虚拟 akka Httpresponse?

问题描述

因为我们可以使用 HttpResponse

创建一个虚拟的 httpresponse

但它不会在响应中产生任何延迟,有没有办法在其中添加延迟?

解决方法

是的,您可以,也可以不使用 Thread.sleep。因为它会阻塞线程,如果您需要模拟一个有大量请求的服务,这不是一个好的选择。检查这个旧的实现,也许它可以帮助:https://github.com/EmiCareOfCell44/http-retarder

,

在本例中,我使用 Thread.sleep(value) 模拟延迟。但请注意,当您从浏览器请求 http GET|POST localhost:8081/home?timeout=5000 此方法被阻塞时,即使 HttpResponseFuture 内,它也会延迟您作为参数传递的时间。

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.Http.IncomingConnection
import akka.http.scaladsl.model._
import akka.http.scaladsl.model.headers.Location
import akka.stream.scaladsl.{Flow,Sink}

import scala.concurrent.Future

object BasicServerLowLevel {
  def main(args: Array[String]): Unit = {
    implicit val system = ActorSystem("BasicServerLowLevel")
    import system.dispatcher

    def getHtmlFuture(value: Int) = {
      Thread.sleep(value) // SIMULATING A LONG COMPUTATION HERE
      Future(HttpResponse(
        StatusCodes.OK,// HTTP 200
        entity = HttpEntity(
          ContentTypes.`text/html(UTF-8)`,s"""
             |<html>
             | <body>
             |  Async Hello Akka HTTP timeout: $value milliseconds
             | </body>
             |</html>
             |""".stripMargin)
      ))
    }

    /** serve back HTTP response ASYNCHRONOUSLY */
    val asyncRequestHandler: HttpRequest => Future[HttpResponse] = {
      case HttpRequest(HttpMethods.GET | HttpMethods.POST,uri@Uri.Path("/home"),headers,entity,protocol) =>
        val timeout = uri.query().get("timeout").map(_.toInt)
        println(s"timeout: $timeout milliseconds")
        timeout match {
          case None =>
            getHtmlFuture(0)
          case Some(value: Int) =>
            getHtmlFuture(value)
        }
      case request: HttpRequest =>
        request.discardEntityBytes()
        Future(HttpResponse(
          StatusCodes.NotFound,// HTTP 404
          entity = HttpEntity(
            ContentTypes.`text/html(UTF-8)`,"""
              |<html>
              | <body>
              |  OOPS! async page not found =(<br>try http://localhost:8081/home
              | </body>
              |</html>
              |""".stripMargin)
        ))
    }
    val httpAsyncConnectionHandler = Sink.foreach[IncomingConnection] { connection =>
      connection.handleWithAsyncHandler(asyncRequestHandler)
    }
    println(s"call on the console: 'http GET localhost:8081/home'")
    println(s"call on the console: 'http GET localhost:8081/home?timeout=5000'")
    // manual version >>>
    // Http().newServerAt("localhost",8081).connectionSource().runWith(httpAsyncConnectionHandler)
    // short version >>>
    Http().newServerAt("localhost",8081).bind(asyncRequestHandler)

  }
}
,

梅比有这样的想法吗?基于akka.pattern.after。 测试延迟 10 秒 -> http://localhost:9000/example?delay=10000

object Main extends App with Directives {

  implicit val system: ActorSystem = ActorSystem()

  val routes: Route = {
    (get & path("example")) {
      parameter("delay".as[Int]) { delay =>
        complete {
          akka.pattern.after(delay.millis) {
            Future.successful(response(delay))
          }
        }
      }
    }
  }

  def response(delay: Int): HttpResponse = {
    HttpResponse(
      StatusCodes.OK,entity = HttpEntity(
    ContentTypes.`text/html(UTF-8)`,s"""
       |<html>
       | <body>
       |  Example request with delay $delay
       | </body>
       |</html>
       |""".stripMargin
      )
    )
  }

  val (host,port) = ("localhost",9000)

  Http().newServerAt(host,port).bind(routes)
}