当前位置: 首页 > 知识库问答 >
问题:

Akka HTTP和长时间运行请求

岳华灿
2023-03-14

我们有一个应用程序html" target="_blank">接口实现在裸骨Scala Akka HTTP中--一对路由前面的大量计算(CPU和内存密集)。没有集群-所有运行在一个强壮的机器上。计算量相当大--一个独立请求可能需要60多秒才能完成。我们并不那么在意速度。没有阻塞IO,只是大量的CPU处理。

当我开始对它进行性能测试时,出现了一个有趣的模式:假设请求A1、A2、...、A10通过。它们会大量使用资源,结果Akka会为溢出的请求A5-A10返回HTTP503。问题是,即使没有人来取结果,计算仍然在运行。

从那里我们看到了一个级联的性能崩溃:请求A11-A20到达仍在处理请求A5-A10的服务器。显然,这些新的请求也有可能超负荷--考虑到服务器更忙,超负荷的几率甚至更高。因此,当Akka触发超时时,它们中的一些将会运行,这使得服务器变得更加繁忙和缓慢,然后新的一批请求通过...因此,在运行系统一段时间后,您会看到几乎所有的请求在某个点之后都开始以超时方式失败。并且在停止加载之后,您可以在日志中看到一些仍在处理的请求。

我尝试在单独的ExecutionContext和系统调度程序中运行计算,试图使其完全异步(通过将来的组合),但结果仍然是一样的。延迟的作业使服务器非常繁忙,最终几乎每个请求都失败。

在https://github.com/zcox/spray-blocking-test中描述了一个类似的情况,但重点转移到了那里-/ping对我们来说并不重要,因为它对处理长时间运行请求的endpoint承担或多或少的稳定责任。

问题是:如何设计应用程序以更好地中断挂起请求?我可以容忍一些很小百分比的失败请求在重载下,但磨整个系统停顿数秒后是不可接受的。

共有1个答案

闾丘德宇
2023-03-14

Akka HTTP不会自动终止对超时请求的处理。通常,需要做的额外记账是不会有回报的,所以默认情况下是不开启的。我认为这是一个疏忽,TBH,我自己也遇到过类似的Akka HTTP问题。

我认为您需要在请求超时时手动中止处理,否则服务器在超载时将无法恢复,正如您所看到的。

没有一个标准的机制可以用来实现这一点(请参见“如何在Scala中取消Future?”)。如果线程在没有I/O的情况下执行CPU工作,那么thread.interrupt()将不会有用。相反,您应该创建一个deadlypromise或类似的文件,以显示请求是否仍处于打开状态,并在计算过程中定期检查超时情况:deadlypromise

// in the HTTP server class:
val responseTimeout: Duration = 30.seconds

val routes = 
  path("slowComputation") {
    complete {
      val responseTimeoutDeadline: Deadline = responseTimeout.fromNow
      computeSlowResult(responseTimeoutDeadline)
    }
  }

// in the processing code:
def computeSlowResult(responseDeadline: Deadline): Future[HttpResponse] = Future {
  val gatherInputs: List[_] = ???
  gatherInputs.fold(0) { (acc, next) =>

    // check if the response has timed out
    if (responseDeadline.isOverdue())
      throw new TimeoutException()

    acc + next // proceed with the calculation a little
  }
}

(检查promise是否已完成要比检查deadly是否已过期便宜得多。我已经将后者的代码放在上面,因为它更容易编写。)

 类似资料:
  • 经过长时间的调查,问题似乎是长时间运行的请求超时,并且在NodeJS中再次调用endpoint。没有来自浏览器的新网络请求。我做了一些测试,2分钟后再次调用endpoint。我读到NodeJS中http请求的默认超时时间为2分钟。 https://nodejs.org/docs/latest-v12.x/api/http.html#http_server_timeout 我使用的是NestJS(有

  • 每个人在最新的更新之后,Studio在运行应用程序之前已经运行了很长时间(3-40分钟)“运行Gradle Build”。如何治疗?当前Studio版本:1.3。2.

  • 我有一个Spring Boot应用程序,我想实现的是,当我的Rest控制器需要更长的时间来处理请求时,只需发送错误而不继续处理请求。这可能吗?我如何以某种方式实现它,而无需在控制器级别进行修改,而是在应用程序级别进行修改。这是在最新的Spring启动

  • 我有一个在Tomcat7上运行的Spring3.0WebMVC应用程序。在应用程序启动时,我启动一个后台线程来加载内存缓存,其中包含来自数据库的记录。该线程从数据库加载所有数据通常需要一个多小时。在同一个应用程序中,我有一个@Controller注释类,它公开了一个REST接口,客户端可以通过该接口从加载的缓存中获取对象。 我们的要求之一是,在数据加载完成之前发出的任何REST请求都将立即向客户端

  • 我已经在Ubuntu14.04中安装了Android studio。我试图清理这个项目,但它花了太长时间,已经1小时了,因为gradle正在运行。在我的Gradle控制台中,我得到了如下错误: 线程“png-cruncher_8”java.lang.runtimeException:在等待从aapt进程时超时,请确保在/home/files/android/sdk/build-tools/23.0

  • 我使用前端Spring云应用程序(微服务)作为Zuul代理()将请求从外部源路由到使用Spring云编写的其他内部微服务(Spring boot) Zuul服务器直接来自示例部分中的应用程序 我在本地运行了这组服务,这一切似乎都工作正常,但如果我在网络上运行它有一些负载,或通过VPN,然后我开始看到Zuul转发错误,我在日志中看到客户端超时。 有没有办法改变Zuul转发的超时时间,这样我就可以从眼