2016-05-08 27 views
1

假設我有一個簡單的功能,像這樣: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爲呼叫URL,然後讓一個CGI腳本調用。 cgi腳本根據ID將文檔放入隊列中,然後等待處理完成。出於我的目的,等待過程完成的cgi調用部分只有通過瀏覽器訪問服務的用戶才感興趣。

因此,我想要做的就是啓動100個線程,等待足夠長的時間來運行cgi腳本的'將文檔放入隊列'階段,然後關閉這些線程(而不是坐在那裏等待完成),然後繼續下一批100行。沖洗並重復。

(shutdown-agents)似乎像system.exit一樣,它殺死了整個程序,甚至殺死了我的repl。

(未來取消)在單線程上工作,但我不知道如何取消一批線程。

任何見解,將不勝感激。

回答

2

我不認爲「等待足夠長的時間來將'放入隊列'階段的cgi腳本運行」是一個好主意。你如何定義「足夠長」?您可能會嘗試估計它到底有多長時間,並且將HTTP請求關閉或超時給端點,但如果運行CGI腳本的服務器會稍微慢一點怎麼辦?

在我看來,你應該在你的CGI服務公開兩個獨立的端點:

  • 一個暴露的UI界面,用戶將等待處理完成
  • 一個單獨的一個是設計成「發射後不管」,你可以在你的場景中使用

這樣的設計會使你的處理可靠的,也將讓你的客戶端應用程序要簡單得多(線程將阻止,並根據需要等待太長的時間和沒多久呃所以你不需要任何解決方法來使用現有的端點,而不是爲它設計的)。

如果您不能或不想修改您的CGI端點,我會使用HTTP客戶端庫的超時功能。您可以使用:socket-timeoutclj-http:timeout參數httpkit client,該參數適用於請求級別。但我不確定它是否始終工作可靠,因爲這些超時在網絡級別上工作,並且任何接收到的字節都會重置超時計數器。

您可能還會使用異步客戶端,您會阻止並等待響應僅10秒鐘,並忽略響應。 For example using httpkit library

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

http/post將調用服務器並返回未來的對象將包含響應。您可以使用deref阻止並等待響應,但不超過以msecs提供的超時值。如果在10秒內沒有響應,則會返回:time-out值(您可以忽略返回值)。

+0

通常,cgi的返回部分將等待文檔轉換爲PDF並將其顯示在瀏覽器中。如果退出等待部分,後端進程仍然會將轉換後的文檔護送到「轉換後的文檔」文件管理器中供最終用戶使用,所以我不關心是否在後端等待每個文檔。我只是想劫持推送功能並退出。這是一個遺留系統,我們正在遷移,因此我們正在避免對現有代碼進行任何不必要的修改。每個文檔的前端可預測@〜10秒。我在等待20. –

+0

我已經使用異步http調用和超時添加了一個可能的解決方案。 –

+0

謝謝。我會考慮你提到的方法。 –