Clojure/jetty : Force URL to only be Hit Once at a Time

标签 clojure locking jetty

我正在开发 Clojure/Jetty Web 服务。我有一个特殊的 url,我希望一次只处理一个请求。如果请求了 url,在它返回之前,又请求了 url,我想立即返回。所以在更多 core.clj 中,我定义了我的路线,我有这样的东西:

(def work-in-progress (ref false)) 

然后过一段时间
(compojure.core/GET "/myapp/internal/do-work" []
    (if @work-in-progress
        "Work in Progress please try again later"
        (do
            (dosync
                (ref-set work-in-progress true))
            (do-the-work)
            (dosync
                (ref-set rebuild-in-progress false))
            "Job completed Successfully")))

我已经在本地 Jetty 服务器上尝试过这个,但我似乎能够点击 url 两次并使工作翻倍。在线程 Web 服务器环境中,在 Clojure 中实现这一点的好模式/方法是什么?

最佳答案

想象以下 race condition对于问题中提出的解决方案。

  • 线程 A 开始执行处理程序的主体。 @work-in-progressfalse ,所以它进入 do表达。但是,在它设法设置 work-in-progress 的值之前至 true ...
  • 线程 B 开始执行处理程序的主体。 @work-in-progress是假的,所以它进入 do表达。

  • 现在有两个线程正在执行 (do-the-work)同时。那不是我们想要的。

    为防止出现此问题,请检查并在 dosync 中设置 ref 的值。交易。
    (compojure.core/GET "/myapp/internal/do-work" []
      (if (dosync
            (when-not @work-in-progress
              (ref-set work-in-progress true)))
        (try
          (do-the-work)
          "Job completed Successfully"
          (finally
            (dosync
              (ref-set work-in-progress false))))
        "Work in Progress please try again later"))
    

    在这种情况下,您可能会发现另一个有用的抽象是原子和 compare-and-set! .
    (def work-in-progress (atom false))
    
    (compojure.core/GET "/myapp/internal/do-work" []
      (if (compare-and-set! work-in-progress false true)
        (try
          (do-the-work)
          "Job completed Successfully"
          (finally
            (reset! work-in-progress false)))
        "Work in Progress please try again later"))
    

    关于Clojure/jetty : Force URL to only be Hit Once at a Time,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16947882/

    相关文章:

    emacs - 如何在苹果酒中正确使用 lein try?

    sql - ISAM 错误 :record is locked

    java - 如何处理 Apache Curator 分布式锁连接丢失

    java - 从 HttpServletRequest 读取二进制数据

    java - Jetty.util.MultiMap 抛出 ConcurrentModificationException

    Spring 管理的 Clojure bean

    Clojure - map 索引是否可以从 0 以外的索引开始?

    arrays - 在循环中将 conj 与数组一起使用时出现空指针错误

    c# - .NET 字典 : Potential concurrency problems?

    java - 两个上下文一个服务器 jetty