Jetty8.1.16
于 2014 年 9 月发布,现在是EOL(生命终止),请考虑使用最新、稳定且受支持的 Jetty 版本。(如码头9.4.12.20180830
)
你得到尖叫的事实是你java.util.concurrent.RejectedExecutionException
没有足够的线程池配置。
您拥有的线程池配置非常小。
这仅适用于单核、单 CPU、单线程硬件配置。为什么?好吧,那是因为您的 cpu/core/thread 硬件配置决定了您的 NIO 行为,并规定了对线程池的最低要求。
在 2009 年(近 10 年前!)的 MacOS 笔记本电脑上,您至少需要 9 个线程才能支持在该硬件上发出单个阻塞 REST 请求的单个连接。
在现代 Ryzen Threadripper 系统上,您通常需要至少 69 个线程来支持在此硬件上发出单个阻塞 REST 请求的单个连接。
另一方面,您的配置非常适合 Raspberry Pi Zero,并且可以支持大约 3 个连接,每个连接有 1 个请求处于活动状态。
使用该配置,您将只能处理简单的串行请求,并且您的应用程序不使用任何异步处理或异步 I/O 行为。为什么?这是因为即使是典型的现代网页也需要至少 40 个左右的线程数,这取决于浏览器如何利用您的服务器。
对于您的情况,这ExecutorThreadPool
也是一个糟糕的选择(仅适用于高并发环境,考虑 24+ cpu/cores,并且最小线程配置高于 500,通常为数千)。
您最好使用该标准QueuedThreadPool
,它在低端性能更高,并且能够增长以处理需求(并随着时间的推移缩减资源利用率以降低资源利用率)。
(QueuedThreadPool
在 Jetty 9.4.x 中)还具有针对错误配置的保护,如果配置不足以满足您的硬件配置、您在 Jetty 中选择的一组功能或您在 Jetty 中的特定配置,则会向您发出警告。
如果您想在资源不足时拒绝连接,请考虑使用DoSFilter
(或者如果您想更温和,请考虑QoSFilter
)。
试图通过 ThreadPool 限制使用永远不会奏效,因为为了拒绝一个连接,需要一个线程来接受它(接受者线程,每个服务器连接器一个),另一个来处理 NIO 事件(选择器线程,共享资源,处理多个连接),另一个处理请求(返回http状态码503)。
如果您想在自己的代码(而不是 Jetty)中实现,您可能只需要编写一个Filter
计算活动交换(请求和响应)并在计数高于某个可配置数字时强制 503 响应状态。
但是,如果您这样做,您可能应该强制关闭所有响应。又名Connection: close
响应头,不允许持久连接。