Clojure:管理单个线程

时间:2016-05-08 18:50:48

标签: clojure

假设我有一个像这样的简单函数:

(defn process-files
  "Take file name and read data"
  [file]
   (let [data (slurp file)
        rows (rest (c/parse-csv data))]
        (doseq [row rows]
          (future (call-url (nth row 3 nil)))
    ))

它将ID传递给call-url,然后调用cgi脚本。 cgi脚本根据文档ID将文档放入队列,然后等待处理完成。就我的目的而言,等待进程完成的cgi调用部分仅对通过浏览器访问服务的人感兴趣。

所以我想做的就是开始,比方说,100个线程,等待足够长的时间让文档进入队列'要运行的cgi脚本的阶段,然后关闭这些线程(而不是坐在那里等待完成)并继续下一批100行。冲洗并重复。

(shutdown-agents)似乎就像system.exit一样,它会杀死整个程序甚至杀死我的代表。

(future-cancel)适用于单个线程,但我不确定如何取消一批线程。

任何见解都将不胜感激。

1 个答案:

答案 0 :(得分:2)

我不认为"等待足够长的时间让文档排入队列'要运行的cgi脚本的阶段"是个好主意。你怎么能定义足够长的时间"?您可能会尝试估计它的持续时间以及关闭或超时对端点的HTTP请求,但是如果运行CGI脚本的服务器会慢一点呢?

在我看来,您应该在CGI服务中公开两个独立的端点:

  • 为UI界面公开的用户将等待处理完成的文件
  • 一个单独的设计用于"火灾和忘记"你可以在你的场景中使用

这样的设计将使您的处理变得可靠,并且还会使您的客户端应用程序变得更加简单(线程将在需要时阻塞并等待,不再需要任何变通方法以便在现有端点中使用现有端点它没有被设计为。)

如果您不想或不想修改您的CGI端点,我会使用HTTP客户端库的超时功能。例如,您可以在clj-http中使用:socket-timeout:timeout参数,该参数适用于请求级别。我不确定它是否总能正常工作,因为这些超时在网络级别工作,任何收到的字节都会重置超时计数器。

您也可以使用异步客户端阻止并等待响应仅10秒并忽略响应。 httpkit client

(let [response-future (http/post "http://example.com/cgi-bin/abc")]
  (deref response-future 10000 :time-out))

http/post将调用服务器并返回包含响应的future对象。您可以使用For example using httpkit library来阻止并等待响应,但不会超过msecs中提供的超时。如果在10秒内没有响应,将返回:time-out值(您可以忽略返回值)。