我可以配置我的 servlet 容器的线程管理吗?
Can I configure my servlet container's thread management?
我目前正在开发一款与地图密切相关的应用程序。为了显示地图,我们在许多线程中生成一堆图块,存储它们并在用户想要查看地图的特定部分时获取它们。
问题是,我正在命名以某种方式生成图块的线程,但是,当我想要获取图块以显示地图时,我的 servlet 容器从池中获取随机线程,因此线程命名为生成一个图块最终会从存储中获取它。当然,我可以在生成回贴后重命名线程,但我想知道是否有其他选择。
我想知道我是否可以通过某种方式配置我的 servlet 容器,使其在空闲一段时间后杀死线程,或者在我想要的地方创建一个新线程,或者分配多个线程来处理这部分代码?
我在配置 servlet 容器方面所能找到的就是设置它的最小和最大线程池大小,我认为这对我没有帮助。
容器 100% 控制它的线程。
如果您试图操纵容器的线程,那么您就是在打一场必败仗。
无法安全地终止或停止 运行 容器上的线程,因为这是非常不安全的,并且 将导致许多内存问题(泄漏)和未关闭的资源。 Thread.stop()
方法自 Java 1.2.
以来已被弃用
既然我们已经排除了负面因素...
Jetty 是 100% 异步 Java Web 服务器。
1 个请求使用 1 个线程的经典假设是错误的。 (如果你想要这种行为,那么你应该使用 Jetty 6 或更早的版本。Jetty 9.2 之前的版本现在都 EOL/End of Life)
当您使用传统上是阻塞调用的 Servlet 调用时,Jetty 服务器必须伪造该阻塞调用以满足 API 合同。
即使使用老式/传统的阻塞 Servlet APIs,您仍然会遇到许多情况,即 1 个请求在该 1 个请求的生命周期内由多个线程处理。
如果你想使用 Servlet API 和它的容器,那么你应该做的第一件事就是开始使用 Servlet Async Processing APIs 和 Servlet Async I/O APIs 合并。请务必阅读 API 上的陷阱!
异步处理将允许您在服务器端处理更多的请求,而不是大量使用容器线程,允许更多地控制线程的行为方式,让您更好地控制请求超时,甚至获得通知您将始终在网络服务器上处理的 request/response 个错误案例。
Async I/O 将允许您仅在 request/connection 中有内容可供读取或连接允许写入时才使用线程。该连接不会消耗线程,除非 I/O 是可能的。这意味着每台服务器更多 connections/requests,并且行为不端的客户端(缓慢、死机、有问题等)不会通过消耗对您没有任何生产力的线程来影响其他客户端的行为。
如果您不想使用 Servlet API 并按照自己的方式做事,那么您将不得不管理服务器不知道的自己的 Executor/ThreadGroup/ThreadPool。但这仍然意味着您需要使用 Servlet Async Processing APIs 来允许 2 和谐共存(您需要使用 AsyncContext 来通知容器您现在正在控制处理请求,然后通过 AsyncContext 通知它您已完成并且请求已完成)。
这种方法最大的问题是您无法从容器不受控制的线程安全地写入 HttpServletResponse。
意味着容器在一个线程上分派给您的应用程序,该线程是唯一可以安全地使用 HttpServletResponse 来编写响应的线程。您可以让一个不同的线程进行处理,一个不同的线程将数据提供给 HttpServletResponse,甚至一个不同的线程将内容泵送到调度线程。但是你被分派到的那个线程需要用来写。
这是 servlet 规范中的混合线程行为陷阱。 (您处于 servlet 异步模式,在不同的线程上进行处理,但没有使用异步模式 read/write。)这是 servlet 规范中导致许多问题的非常复杂且定义不明确的行为,我劝你不要追这条路。
如果你也使用 Servlet Async I/O APIs,这个问题就消失了,但在这一点上,上述两个选择的区别是可以忽略不计。
我目前正在开发一款与地图密切相关的应用程序。为了显示地图,我们在许多线程中生成一堆图块,存储它们并在用户想要查看地图的特定部分时获取它们。
问题是,我正在命名以某种方式生成图块的线程,但是,当我想要获取图块以显示地图时,我的 servlet 容器从池中获取随机线程,因此线程命名为生成一个图块最终会从存储中获取它。当然,我可以在生成回贴后重命名线程,但我想知道是否有其他选择。
我想知道我是否可以通过某种方式配置我的 servlet 容器,使其在空闲一段时间后杀死线程,或者在我想要的地方创建一个新线程,或者分配多个线程来处理这部分代码?
我在配置 servlet 容器方面所能找到的就是设置它的最小和最大线程池大小,我认为这对我没有帮助。
容器 100% 控制它的线程。
如果您试图操纵容器的线程,那么您就是在打一场必败仗。
无法安全地终止或停止 运行 容器上的线程,因为这是非常不安全的,并且 将导致许多内存问题(泄漏)和未关闭的资源。 Thread.stop()
方法自 Java 1.2.
既然我们已经排除了负面因素...
Jetty 是 100% 异步 Java Web 服务器。
1 个请求使用 1 个线程的经典假设是错误的。 (如果你想要这种行为,那么你应该使用 Jetty 6 或更早的版本。Jetty 9.2 之前的版本现在都 EOL/End of Life)
当您使用传统上是阻塞调用的 Servlet 调用时,Jetty 服务器必须伪造该阻塞调用以满足 API 合同。
即使使用老式/传统的阻塞 Servlet APIs,您仍然会遇到许多情况,即 1 个请求在该 1 个请求的生命周期内由多个线程处理。
如果你想使用 Servlet API 和它的容器,那么你应该做的第一件事就是开始使用 Servlet Async Processing APIs 和 Servlet Async I/O APIs 合并。请务必阅读 API 上的陷阱!
异步处理将允许您在服务器端处理更多的请求,而不是大量使用容器线程,允许更多地控制线程的行为方式,让您更好地控制请求超时,甚至获得通知您将始终在网络服务器上处理的 request/response 个错误案例。
Async I/O 将允许您仅在 request/connection 中有内容可供读取或连接允许写入时才使用线程。该连接不会消耗线程,除非 I/O 是可能的。这意味着每台服务器更多 connections/requests,并且行为不端的客户端(缓慢、死机、有问题等)不会通过消耗对您没有任何生产力的线程来影响其他客户端的行为。
如果您不想使用 Servlet API 并按照自己的方式做事,那么您将不得不管理服务器不知道的自己的 Executor/ThreadGroup/ThreadPool。但这仍然意味着您需要使用 Servlet Async Processing APIs 来允许 2 和谐共存(您需要使用 AsyncContext 来通知容器您现在正在控制处理请求,然后通过 AsyncContext 通知它您已完成并且请求已完成)。
这种方法最大的问题是您无法从容器不受控制的线程安全地写入 HttpServletResponse。
意味着容器在一个线程上分派给您的应用程序,该线程是唯一可以安全地使用 HttpServletResponse 来编写响应的线程。您可以让一个不同的线程进行处理,一个不同的线程将数据提供给 HttpServletResponse,甚至一个不同的线程将内容泵送到调度线程。但是你被分派到的那个线程需要用来写。
这是 servlet 规范中的混合线程行为陷阱。 (您处于 servlet 异步模式,在不同的线程上进行处理,但没有使用异步模式 read/write。)这是 servlet 规范中导致许多问题的非常复杂且定义不明确的行为,我劝你不要追这条路。
如果你也使用 Servlet Async I/O APIs,这个问题就消失了,但在这一点上,上述两个选择的区别是可以忽略不计。