【问题标题】:How to cancel a servlet request if a new one comes in before old one finishes如果在旧请求完成之前有新请求进入,如何取消 servlet 请求
【发布时间】:2013-07-05 15:08:42
【问题描述】:

我有一个 JavaScript 应用程序,它可以允许用户向我的 Tomcat 服务器发出多个重叠的只读请求,这样以后的请求应该取消并覆盖任何早期的请求。在收到请求之前,我可以禁用所有客户端控件,但我宁愿让它们保持启用状态,让用户随时点击,然后取消之前的请求。

我想做的是取消除最新请求之外的所有请求,这样我的服务器就不会浪费时间完成永远不会看到的请求。我希望服务器中止它为该请求运行的线程,以减少服务器资源。

最好的方法是什么?

【问题讨论】:

  • 您不能在服务器上执行此操作 - 而应在客户端执行此操作。如果前一个呼叫尚未完成,则在发起新呼叫时使用 AJAX 并取消上一个呼叫。见this question
  • @AleksG 感谢您的快速回复!那里有很好的链接。正如您所说,您不能在服务器上执行此操作。但我不太容易接受“不能”。

标签: tomcat servlets


【解决方案1】:

如果只是为了节省服务器 CPU 时间,客户端取消请求将无济于事。简单的方法是:忽略它,接受请求仍然会计算,直到服务器端请求处理器意识到其输出流已关闭并将失败。

如果您有一些确实需要相当长一段时间才能完成的繁重操作,我会选择分块执行服务器端工作,并且 - 中间 - 检查请求是否仍需要继续。任何新请求都可以设置同一用户的其他线程正在检查的标志。

在 java 线程级别(例如 Thread.stop 等)上进行交互并不是在应用程序逻辑中进行交互的好方法。但是,如果您有一些应用程序逻辑来确定哪个用户需要完成哪个操作,并且每个操作都可以检查它是否仍然需要,那可能会对您有所帮助。你仍然会浪费几个周期,但不一定是全部。

另外,如果您在 java 线程级别上进行交互,请记住线程很可能归应用程序服务器所有,并在线程池中用于请求处理 - 因此您不应该弄乱它们(来自外面)。

【讨论】:

    【解决方案2】:

    我认为您可以在服务器上执行此操作,但这会有点不切实际,正如 cmets 所暗示的那样。

    您需要一个数据结构(可能是 HashMap)来跟踪

    • 发出请求的用户
    • 当前为请求提供服务的Thread 对象
    • 任何其他有助于识别请求的上下文内容

    对于 servlet 的传入 HTTP 请求,请查阅查找表并确定是否已经存储了一个 Thread 对象。如果是,则stop the thread,并在当前线程中继续执行。在线程将内容返回给客户端之前,请务必从 HashMap 中移除 Thread 的条目。

    这是一个相当复杂的情况。任何时候你处理并发,你都冒着把事情搞砸的风险。如果您真的,真的想要节省服务器端资源,我只会遵循这条路线。否则,正如Aleks G 所建议的那样,仅使用 AJAX 在客户端取消之前的调用可能会容易得多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-24
      • 1970-01-01
      • 2011-04-20
      • 1970-01-01
      • 1970-01-01
      • 2016-09-06
      • 2020-08-26
      • 2020-10-26
      相关资源
      最近更新 更多