gpt4 book ai didi

java - 避免tomcat/spring-boot中慢客户端导致的线程饥饿

转载 作者:搜寻专家 更新时间:2023-11-01 00:56:13 25 4
gpt4 key购买 nike

我有一个简单的 spring-boot 应用程序。它有一个端点,从请求体中获取一个对象,什么也不做:

@Controller
class FooController {
@RequestMapping(method=RequestMethod.POST, value="/foo")
public void postFoo(@RequestBody Foo foo) {
}
}

非常简单的东西。

然后我通过 telnet 连接并通过适当的 header 发送,就好像我要发送一个 json 编码的对象一样,但从不发送请求正文 - 我只是让连接挂起。

运行jstack,我可以看到tomcat已经将请求发送给了spring。 Spring 已将其发送给 jackson。 jackson 在等待更多数据输入的 NIO 上被阻止。

Thread 12128: (state = BLOCKED)
- sun.misc.Unsafe.park(boolean, long) @bci=0 (Compiled frame; information may be imprecise)
- java.util.concurrent.locks.LockSupport.parkNanos(java.lang.Object, long) @bci=20, line=226 (Compiled frame)
...
- org.apache.tomcat.util.net.NioEndpoint$KeyAttachment.awaitLatch(java.util.concurrent.CountDownLatch, long, java.util.concurrent.TimeUnit) @bci=18, line=1582 (Compiled frame)
...
- org.apache.tomcat.util.net.NioSelectorPool.read(java.nio.ByteBuffer, org.apache.tomcat.util.net.NioChannel, java.nio.channels.Selector, long) @bci=7, line=227 (Compiled frame)
- org.apache.coyote.http11.InternalNioInputBuffer.readSocket(boolean, boolean) @bci=103, line=427 (Compiled frame)
...
- org.apache.catalina.connector.CoyoteInputStream.read(byte[], int, int) @bci=76, line=200 (Compiled frame)
- com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper.ensureLoaded(int) @bci=49, line=503 (Compiled frame)
...
- com.fasterxml.jackson.databind.ObjectMapper.readValue(java.io.InputStream, com.fasterxml.jackson.databind.JavaType) @bci=6, line=2158 (Compiled frame)
- org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readJavaType(com.fasterxml.jackson.databind.JavaType, org.springframework.http.HttpInputMessage) @bci=11, line=225 (Compiled frame)
...
- org.springframework.web.servlet.FrameworkServlet.doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) @bci=3, line=863 (Compiled frame)
- javax.servlet.http.HttpServlet.service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) @bci=149, line=646 (Compiled frame)
- org.springframework.web.servlet.FrameworkServlet.service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) @bci=32, line=837 (Compiled frame)
- javax.servlet.http.HttpServlet.service(javax.servlet.ServletRequest, javax.servlet.ServletResponse) @bci=30, line=727 (Compiled frame)
- org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse) @bci=446, line=303 (Compiled frame)
...
- org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(java.nio.channels.SelectionKey, org.apache.tomcat.util.net.NioEndpoint$KeyAttachment) @bci=140, line=1736 (Interpreted frame)
- org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run() @bci=94, line=1695 (Compiled frame)
- java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) @bci=95, line=1145 (Compiled frame)
- java.util.concurrent.ThreadPoolExecutor$Worker.run() @bci=5, line=615 (Interpreted frame)
- org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run() @bci=4, line=61 (Interpreted frame)
- java.lang.Thread.run() @bci=11, line=745 (Interpreted frame)

我的问题是,如果有 200 个人这样做,那么我的线程池就会饿死,合法的请求也无法进入。这似乎是针对在 tomcat 上运行的任何东西的非常简单的 DOS 攻击。

我认为有一种方法可以解决这个问题,方法是让 NIO HTTP 连接器提前读入其缓冲区。如果是这样,我将如何进行设置?

即便如此,恶意代理似乎也可以通过向服务发送大型对象轻松地使服务瘫痪。人们通常如何在缓慢、错误或恶意客户端连接时防止线程饥饿?

最佳答案

查看 Stuck Thread Detection Valve在汤姆猫中。

来自文档:

This valve allows to detect requests that take a long time to process, which might indicate that the thread that is processing it is stuck. Additionally it can optionally interrupt such threads to try and unblock them.

When such a request is detected, the current stack trace of its thread is written to Tomcat log with a WARN level.

您可以指定您希望请求花费的秒数,最大值(默认为 10 分钟!),如果超过该值,此阀将杀死它们。

关于java - 避免tomcat/spring-boot中慢客户端导致的线程饥饿,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27976951/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com