我们有一个API在裸骨Scala Akka HTTP中实现 - 两个路由面向大量计算(CPU和内存密集型)。没有集群 - 全部运行在一台结实的机器上。计算是适当的 - 可以花费超过60秒来完成一个孤立的请求。我们并不关心速度。没有阻塞IO,只是很多CPU处理。Akka HTTP和长时间运行的请求
当我开始进行性能测试时,一个有趣的模式显示:请求A1,A2,...,A10通过。他们使用的资源相当繁重,事实证明,Akka会针对超出的请求A5-A10返回HTTP 503。问题在于,即使没有人拿起结果,计算仍在运行。
并从那里我们看到级联性能崩溃:请求A11-A20到达服务器仍然在请求A5-A10。很显然,这些新的请求也有可能超时 - 即使服务器更忙,甚至更高。因此,当Akka触发超时时,它们中的一些会运行,使得服务器更加繁忙和更慢,然后新的一批请求就会通过......所以在系统运行一段时间后,您几乎看到所有请求超时开始失败。在停止加载后,您会看到日志中仍有一些请求正在处理。我试过在单独的ExecutionContext以及系统调度程序中运行计算,尝试使它完全异步(通过未来组合),但结果仍然相同。滞留作业使得服务器如此繁忙,以至于几乎每个请求都会失败。
在https://github.com/zcox/spray-blocking-test中描述了一个类似的情况,但重点转移到那里 - /ping
对于处理长时间运行的请求的端点上的或多或少的稳定责任并不重要。
问题:如何设计我的应用程序以更好地中断挂起的请求?我可以忍受重负载下一小部分失败的请求,但几秒钟后让整个系统停止工作是不可接受的。
非常宽泛的问题。简而言之,您应该在重负载情况下立即拒绝某些请求(只需说抱歉或追踪运行过多计算的用户或维护队列)。你也应该为你的计算,数据库,喷雾使用单独的上下文......所以你的http前端层总会有响应。 – ipoteka