java - 每个连接的线程与每个请求的线程有什么区别?

标签 java multithreading http servlets

您能否解释一下已在各种 servlet 实现中实现的两种方法:

  1. 每个连接的线程
  2. 每个请求的线程

以上两种策略中哪一种更适合扩展?为什么?

最佳答案

Which of the above two strategies scales better and why?

每个请求的线程比每个连接的线程更好。

Java 线程相当昂贵,通常每个使用 1Mb 内存段,无论它们是 Activity 的还是空闲的。如果您为每个连接提供自己的线程,则该线程通常会在连接上的连续请求之间处于空闲状态。最终,框架需要停止接受新连接(因为它无法创建更多线程)或开始断开旧连接(如果/当用户醒来时,这会导致连接流失)。

由于 TCP/IP 的工作方式,HTTP 连接需要的资源比线程堆栈少得多,尽管每个 IP 地址有 64K 个打开连接的限制。

相比之下,在每个请求线程模型中,线程仅在处理请求时关联。这通常意味着服务需要更少的线程来处理相同数量的用户。而且由于线程使用大量资源,这意味着服务将更具可扩展性。

(请注意,thread-per-request 并不意味着框架必须关闭 HTTP 请求之间的 TCP 连接...)


话虽如此,当每个请求的处理过程中存在长时间的停顿时,每个请求的线程模型并不理想。 (并且当服务使用 comet 方法时尤其不理想,该方法涉及长时间保持回复流打开。)为了支持这一点,Servlet 3.0 规范提供了一种“异步 servlet”机制,该机制允许 servlet 的请求方法来挂起它与当前请求线程的关联。这会释放线程去处理另一个请求。

如果可以将 Web 应用程序设计为使用“异步”机制,那么它可能比每请求线程或每连接线程更具可扩展性。


跟进

Let's assume a single webpage with 1000 images. This results in 1001 HTTP requests. Further let's assume HTTP persistent connections is used. With the TPR strategy, this will result in 1001 thread pool management operations (TPMO). With the TPC strategy, this will result in 1 TPMO... Now depending on the actual costs for a single TPMO, I can imagine scenarios where TPC may scale better then TPR.

我认为有些事情你没有考虑到:

  • Web 浏览器需要获取大量 URL 以完成一个页面,很可能会打开多个连接。

  • 使用 TPC 和持久连接,线程必须等待客户端收到响应并发送下一个请求。如果网络延迟很高,则此等待时间可能很长。

  • 服务器无法知道何时可以关闭给定(持久)连接。如果浏览器不关闭它,它可能会“徘徊”,束缚 TPC 线程,直到服务器超时连接。

  • TPMO 开销并不大,尤其是当您将池开销与上下文切换开销分开时。 (您需要这样做,因为 TPC 会在持久连接上引发上下文切换;见上文。)

我的感觉是,这些因素可能会超过每个连接专用一个线程所节省的 TPMO。

关于java - 每个连接的线程与每个请求的线程有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15217524/

相关文章:

java - 如何在 WebSphere 的 jython 中导入 AdminControl?

java - Scala - 使用 scalaj.http.Http 发送多个 header

java - 为什么我的 HTTP GET 请求开始超时?

apache - 将结果从 Zookeeper 传输到网络服务器

java - 错误: `elasticsearch` directory is missing in the plugin zip

java - 如何显示本地 h2 数据库(Web 控制台)的内容?

c - 线程池加入函数

c++ - 管理多个并发线程

java - Java 中的同步 - Thinking in Java 示例

java - 如何配置 IntelliJ/gradle 以使用 dagger 2.0