我有一个应用程序,它会旋转一些未来来完成长时间的工作。它间歇性地失败了,我试图找出原因。
症状是代码停止执行,并在随机停止。我的未来创造代码是这样的:
(def future-timeout
; 1 hour
3600000)
(def concurrency 200)
(defn do-parallel
[f coll]
(let [chunks (partition-all concurrency coll)]
(doseq [chunk chunks]
(let [futures (doall
(map #(future
(try
(f %)
(catch Exception e
(log/error "Unhandled error in do-parallel:" (.getMessage e))
:exception)))
chunk))
results (doall (map #(deref % future-timeout :timeout) futures))
all-ok (every? true? results)]
(when all-ok
(log/info "Chunk successful."))
(when-not all-ok
(log/error "Chunk unsuccessful.")
(log/warn "Parallel execution results:" results))
(swap! chunk-count inc)))
(log/info "Finished batch")))
并发变量控制批量的大小,因此控制它尝试的并发执行的数量。 f
成功返回true
。如果超时或例外,他们会返回:timeout
或:exception
。
我这样做而不是pmap
,因为我想控制并发,f
是一个长期运行(约10分钟)的网络密集型任务。 pmap
似乎是针对中等规模的小批量调整的。
通常情况下这很好。但几个小时后它停止了:
f
期间,该功能停止运行。do-parallel
中的循环停止,不再显示日志条目。可能导致此问题的任何想法?或者采取措施帮助诊断?
答案 0 :(得分:1)
您可能想尝试安装未捕获的异常处理程序,以查看Executor
本身的异常异常是否导致工作停止。
https://github.com/pyr/uncaught有一个设施,但直接从代码直接做。
答案 1 :(得分:0)
Claypool对于控制并行性非常有用。
(cp/pmap (count chunk) f chunk)
将创建一个与块相同大小的临时线程池,并且并行执行所有函数。
这只是表达并行性的建议,而不是你的问题的答案,这是关于错误处理的;我也很好奇!
答案 2 :(得分:0)
也许尝试捕捉Throwable而不是Exception?我之前遇到过问题,因为它已经因为异常而陷入了异常。
我认为如果期货中有未被捕获的例外情况,它会抓住并死而不会将其进一步抛出,因此设置默认的欺骗行为并不会有所帮助。未经测试 - 但这是我的直觉。
你得到" Chunk不成功"至少在消息结束时的消息?因为如果你不这样做,那真的很奇怪......
查看future
的实现 - 它在下面使用了一个cachedthreadpool - 它没有线程限制,所以你可能最好直接使用ExecutorService,或类似{{ 3}},就像其他建议所示。