如何使用 kairosdb 中的 Jetty 配置拒绝来自客户端的请求
How to reject request from client using Jetty config in kairosdb
我正在使用最新版本的 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
Jetty 8.1.16
于 2014 年 9 月发布,现在 EOL (End of Life),请考虑使用最新、稳定且受支持的 Jetty 版本。 (比如Jetty9.4.12.20180830
)
您得到 java.util.concurrent.RejectedExecutionException
的事实表明您的线程池配置不足。
您的线程池配置非常小。
那只适合单核、单cpu、单线程的硬件配置。为什么?好吧,那是因为您的 cpu/core/thread 硬件配置决定了您的 NIO 行为,并规定了对线程池的最低要求。
在 2009 年(将近 10 年前!)的 MacOS 笔记本电脑上,您至少需要 9 个线程才能支持在该硬件上发出单个阻塞 REST 请求的单个连接。
在现代 Ryzen Threadripper 系统上,您通常需要至少 69 个线程的线程数才能支持在该硬件上发出单个阻塞 REST 请求的单个连接。
另一方面,您的配置非常适合 Raspberry Pi 零,并且可以支持大约 3 个连接,每个连接有 1 个活动请求。
使用该配置,您将只能串行处理简单请求,并且您的应用程序不使用任何异步处理或异步 I/O 行为。为什么?这是因为即使是典型的现代网页也需要至少 40 个左右的线程数,这取决于浏览器如何利用您的服务器。
ExecutorThreadPool
对你的情况来说也是一个糟糕的选择(这只适用于高度并发的环境,想想 24+ cpu/cores,并且最小线程配置在 500 以上,通常是数千) .
你最好使用标准 QueuedThreadPool
它在低端的性能要好得多,并且能够增长以满足需求(并随着时间的推移缩减以随着需求消退而降低资源利用率) .
QueuedThreadPool
(在 Jetty 9 中。4.x)也有针对错误配置的保护,如果配置不适合您的硬件配置、您在 Jetty 中选择的一组功能,则会发出警告,或您在 Jetty 中的特定配置。
如果您想在资源不足时拒绝连接,请考虑使用 DoSFilter
(or if you want to be more gentle, consider QoSFilter
)。
尝试通过 ThreadPool 限制使用永远不会奏效,因为为了拒绝连接,需要一个线程来接受它(接受器线程,每个服务器连接器一个),另一个来处理 NIO 事件(选择器线程,共享资源,处理多个连接),另一个处理请求(到 return http 状态代码 503)。
如果你想在你自己的代码(而不是 Jetty)中实现,你可能只需要写一个 Filter
来计算活跃的交换(请求和响应)并在计数高于 503 时强制响应状态一些可配置的数字。
但如果您这样做,您可能应该强制关闭所有响应。又名 Connection: close
响应 header 并且不允许持久连接。
我正在使用最新版本的 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
Jetty 8.1.16
于 2014 年 9 月发布,现在 EOL (End of Life),请考虑使用最新、稳定且受支持的 Jetty 版本。 (比如Jetty9.4.12.20180830
)
您得到 java.util.concurrent.RejectedExecutionException
的事实表明您的线程池配置不足。
您的线程池配置非常小。
那只适合单核、单cpu、单线程的硬件配置。为什么?好吧,那是因为您的 cpu/core/thread 硬件配置决定了您的 NIO 行为,并规定了对线程池的最低要求。
在 2009 年(将近 10 年前!)的 MacOS 笔记本电脑上,您至少需要 9 个线程才能支持在该硬件上发出单个阻塞 REST 请求的单个连接。
在现代 Ryzen Threadripper 系统上,您通常需要至少 69 个线程的线程数才能支持在该硬件上发出单个阻塞 REST 请求的单个连接。
另一方面,您的配置非常适合 Raspberry Pi 零,并且可以支持大约 3 个连接,每个连接有 1 个活动请求。
使用该配置,您将只能串行处理简单请求,并且您的应用程序不使用任何异步处理或异步 I/O 行为。为什么?这是因为即使是典型的现代网页也需要至少 40 个左右的线程数,这取决于浏览器如何利用您的服务器。
ExecutorThreadPool
对你的情况来说也是一个糟糕的选择(这只适用于高度并发的环境,想想 24+ cpu/cores,并且最小线程配置在 500 以上,通常是数千) .
你最好使用标准 QueuedThreadPool
它在低端的性能要好得多,并且能够增长以满足需求(并随着时间的推移缩减以随着需求消退而降低资源利用率) .
QueuedThreadPool
(在 Jetty 9 中。4.x)也有针对错误配置的保护,如果配置不适合您的硬件配置、您在 Jetty 中选择的一组功能,则会发出警告,或您在 Jetty 中的特定配置。
如果您想在资源不足时拒绝连接,请考虑使用 DoSFilter
(or if you want to be more gentle, consider QoSFilter
)。
尝试通过 ThreadPool 限制使用永远不会奏效,因为为了拒绝连接,需要一个线程来接受它(接受器线程,每个服务器连接器一个),另一个来处理 NIO 事件(选择器线程,共享资源,处理多个连接),另一个处理请求(到 return http 状态代码 503)。
如果你想在你自己的代码(而不是 Jetty)中实现,你可能只需要写一个 Filter
来计算活跃的交换(请求和响应)并在计数高于 503 时强制响应状态一些可配置的数字。
但如果您这样做,您可能应该强制关闭所有响应。又名 Connection: close
响应 header 并且不允许持久连接。