如何在不关闭 TCP 连接的情况下关闭处理 TCP 请求的线程?

Posted

技术标签:

【中文标题】如何在不关闭 TCP 连接的情况下关闭处理 TCP 请求的线程?【英文标题】:How do you close threads handling TCP requests without closing the TCP connection? 【发布时间】:2022-01-15 14:39:16 【问题描述】:

我遇到了下面的线程,并希望为请求而不是客户端连接实现线程,但我不确定如何在不关闭每次 TCP 传输之间与客户端的连接的情况下这样做。我看到了下面的内容,但不确定如何在不为该连接保持线程活动的情况下保持服务器和客户端之间的 TCP 连接活动。

最佳答案指定:“请注意,每个请求的线程并不意味着框架必须关闭 HTTP 请求之间的 TCP 连接”我很想看看这是如何完成的。

What is the difference between thread per connection vs thread per request?

@aholbreich

【问题讨论】:

【参考方案1】:

您标记了 TCP,但包含的链接提到了 HTTP 内容。我假设您的意思是在 HTTP 上下文中提出您的问题,或者我们只是假设 TCP 之上的通用请求/回复协议。

关于这个:

请注意,每个请求线程并不意味着框架必须 关闭 HTTP 请求之间的 TCP 连接

在连接上处理 IO 的线程策略通常取决于您处理 IO 的方式。如果您正在执行阻塞 IO,则每个连接必须(至少)一个线程。这意味着您至少有一个线程在 99% 的时间里被 read() 阻塞。

如果您处于这种情况,则无需为每个请求处理 1 个线程,除非您想同时处理多个请求。 如果是这种情况,您需要为每个请求生成一个新线程到handle 请求(即产生响应)。新的按请求线程位于您用来处理底层连接的 IO(读/写)的线程之上。在您产生响应的某个时刻,您必须将其发送回执行 IO 的线程之一。 (请注意,在 HTTP1.1 中,虽然可以重用连接来发送多个请求,但在单个连接上一次只能有一个未完成的请求......因此,如果您已经在做,最终每个请求都不需要一个线程每个连接 1 个线程)。对于具有多路复用功能的 HTTP2 而言,情况并非如此。

在这种情况下有很多 ifs 并且值得。

这样做的问题是创建线程是一项昂贵的操作。仅当由于计算而产生响应需要很长时间(即您受 CPU 限制)或产生响应的行为需要阻塞 IO 时,这样做才有意义。但那时......我不会首先使用阻塞 IO 来处理连接(即我会放弃 1 线程 1 连接的想法。

我的直觉是你把两个不同的东西混为一谈:

    执行实际 IO(从套接字读取和写入)。 在您的服务器中执行“处理”特定消息并最终产生响应的实际业务逻辑。

个人事先没有太多了解,一个安全的选择是使用类似Netty 的东西作为 IO(用于非阻塞 IO 的多线程事件循环),然后将长请求或阻塞请求处理卸载到固定大小的线程池.

阻塞本身并不坏,当它浪费操作系统资源时就不好了。未来免责声明:当 Loom 项目登陆 JDK 时,我认为阻塞 API 的使用将会重新兴起,并且该领域的实践将会发生一些变化。

【讨论】:

以上是关于如何在不关闭 TCP 连接的情况下关闭处理 TCP 请求的线程?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用系统关闭按钮的情况下关闭MDI子项

有啥方法可以在不关闭其 BaseStream 的情况下关闭 StreamWriter?

如何在不关闭模式的情况下关闭从 modalViewController 推送的 viewController?

unp第七章补充之TCP半开连接与半闭连接

在不添加完成键的情况下关闭数字键盘式键盘

有没有办法在不关闭底层流的情况下关闭 Writer?