【问题标题】:How to process servlet requests during long shutdown如何在长时间关闭期间处理 servlet 请求
【发布时间】:2013-08-26 12:42:15
【问题描述】:

我们需要在我们的 Servlet 应用程序中实现一个优雅的关闭机制。

编辑:我们想让它尽可能简单,这将处理通过操作系统函数发送的终止信号。这将允许系统管理员使用内置的 shell 实用程序(Windows 上的 kill 或 taskkill),否则他们必须安装另一个实用程序才能与服务器“对话”。

这种机制分两个阶段发挥作用:

  1. 根据关闭请求,拒绝某些关键活动
  2. 阻止,直到之前启动的关键操作完成;这些可能需要几个小时

阶段 #1 在我们的 DAO 层中实现。 阶段 #2 在我们的 ServletContextListener#contextDestroyed 方法中实现

我们的问题是,一旦 contextDestroyed 被调用,Servlet 容器就会停止为进一步的 HTTP 请求提供服务。

编辑:当有人在服务器进程上调用操作系统的 kill 函数时调用 contextDestroyed。

我们希望在第 2 阶段期间让应用程序处于活动状态,通知用户某些活动不可用。

【问题讨论】:

  • 好问题。如果要拒绝的活动在特定的 servlet 中实现,如果数据库查找表明正在进行关闭,您总是可以让这些(并且只有这些)返回 4xx 范围内的状态?
  • 有些活动是由 UI 操作发起的,有些是由调度程序发起的——这就是我考虑在 DAO 层控制它们的原因。

标签: java servlets


【解决方案1】:

使用filter 保留所有关键请求的列表。

当收到“准备关闭”请求时,过滤器应该开始拒绝一些请求。

编写一个 servlet,告诉您队列中还有多少关键作业。

在关机工具中,发送“准备关机”。轮询 servlet 以了解关键作业的数量。当达到 0 时,发送实际的关机命令。

要实现这一点,请在业务层中创建一个服务来协调这一点。请注意,所有事情都必须发生在之前 contextDestroyed() 被调用!您的特殊应用程序关闭不符合 J2EE 的世界观,因此您必须自己管理。

该服务应该能够告诉感兴趣的各方何时正在进行关闭、有多少关键作业仍在运行等。Servlet 和过滤器然后可以使用该服务拒绝请求或告知剩余的作业数量。

当所有作业都完成后,拒绝所有请求,除了对“关闭信息”servlet 的访问,该 servlet 应该告诉应用程序现在已准备好死亡。

编写一个工具,为管理员提供一个漂亮的用户界面来启动您的应用程序的关闭。

[编辑] 您可能想阻止操作系统关闭您的应用程序。 不要那样做。

你应该做的是编写一个特殊的工具来使用我上面描述的两阶段过程来关闭你的应用程序。这应该是标准的关机方式。

是的,管理员会抱怨它。在 Unix 上,您可以通过将其放入 init 脚本来隐藏此工具,因此不会有人注意到。 Windows 上可能有类似的解决方案。

在以下(非)预期情况下,终止服务器应该始终能够停止它:关闭代码中的错误、电源故障期间的紧急关闭、应用程序代码中的错误或墨菲发生时。

【讨论】:

  • 一些活动由 UI 操作发起,一些活动由调度程序发起。过滤器不适用于调度程序启动的操作。
  • 过滤器需要将列表/队列保存在全局位置(静态变量或应用程序范围内的条目)。这使得以调度程序可以看到的方式实现它成为可能。如果一切都失败了,请使用 DI 框架。
  • 这会让业务逻辑层“知道”表示层,不是吗?
  • 其实关机逻辑是业务层的一部分。表示层只是向它提供何时开始的信息。拒绝请求是 PL 询问 BL 是否正在关闭。显示作业数量的是 PL 显示来自 BL 的信息。所以我看不出这会如何颠倒这种关系。
  • 由于有些任务是由用户(通过表示层)发起的,并且有些任务计划在不同的时间间隔和/或事件中运行,我们无法在表示层检测到关键活动(如建议你)。我们可以在数据访问层 (DAO) 检测到这些。上述活动的检测和阻止不是问题。问题是在容器调用 contextDestroyed 方法的上下文之后保持上下文、servlet 和过滤器处于活动状态。我在 Servlets API 中找不到任何允许这样的东西。我错了吗?
猜你喜欢
  • 2020-10-17
  • 2010-10-05
  • 1970-01-01
  • 2012-09-11
  • 1970-01-01
  • 2013-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多