问题描述
问题:
如何配置 ring-jetty-adapter 来限制并发工作线程的数量?我在这里使用嵌入式码头,而不是创建 WAR 文件或类似的东西。
上下文
我的数据库连接池只有20个连接,所有请求都需要做数据库查询。目前,当服务器负载变高时,比如连续 40 个并发请求,其中 20 个将被阻塞等待 DB。然后队列会不断增加,等待就会失控(线程饥饿)。
:max-threads
参数不能做我想要的,因为它只限制了jettys 内部线程池的大小,用于接受和选择器线程,而不仅仅是工作线程。
经过一些研究,我认为我需要使用的是 jetty QoS filter,但我不知道如何将 web.xml 配置转换为我的 clojure ring 应用程序。
解决方法
首先,您无法通过调整线程配置来控制或限制行为。
每个请求 1 个线程的老派模型在现代容器上无效,尤其是在内部 100% 异步的 Jetty 上。
单个请求可以在该请求的整个生命周期中使用 1...n 个线程。 Jetty 中线程的行为受您的技术选择(例如:os、jvm、网络协议等)和 API 选择的影响,甚至您的服务器的压力有多大。
除此之外,您想要的解决方案应该专注于限制特定服务器资源端点可以同时使用的请求数量。
这样做的方法是限制可以并发访问服务器资源端点的活动请求的数量。
这是通过跟踪对特定资源端点的请求数量,然后挂起超过配置的最大值的请求,在活动计数低于配置的最大值时恢复挂起的请求,以及超时位于挂起的请求中来实现的状态太久了。
此功能集是在 Jetty QoSFilter
中为您提供的。
您可以将 Jetty QoSFilter
用于 Jetty 中基于 Jetty ServletContextHandler
(包括 WebAppContext
)的任何内容。
见:https://www.eclipse.org/jetty/documentation/jetty-9/index.html#qos-filter
FilterHolder qosConfig = servletContextHandler.addFilter(QoSFilter.class,"/api/backend/*",EnumSet.of(DispatcherType.REQUEST));
qosConfig.setInitParameter("maxRequests","10");
qosConfig.setInitParameter("waitMs","50");
qosConfig.setInitParameter("suspendMs","-1");