0

我正在使用 kairosdb 最新版本。我尝试启用码头线程池。我的期望是,如果队列大小被请求填充,那么所有后续请求都会立即被拒绝。但是尽管我看到了,但请求会在某个时间后送达

 java.util.concurrent.RejectedExecutionException

如果队列已满,则应拒绝客户端请求。如何达到同样的效果?

为了测试,我添加了这些参数。

kairosdb.jetty.threads.queue_size=2 #queue
kairosdb.jetty.threads.min=2 # minThread
kairosdb.jetty.threads.max=4 #maxThread
kairosdb.jetty.threads.keep_alive_ms=1000

对应的jetty线程池代码

new ExecutorThreadPool(minThreads, maxThreads, keepAliveMs, TimeUnit.MILLISECONDS, queue);

kairosdb 中使用的 jetty 版本是8.1.16

4

1 回答 1

0

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响应头,不允许持久连接。

于 2018-11-11T20:00:24.267 回答