Clojure http kit get请求在多个异步调用上卡住
我创建了一个小示例来突出问题:Clojure http kit get请求在多个异步调用上卡住,clojure,http-kit,Clojure,Http Kit,我创建了一个小示例来突出问题: (->> (range 0 4) (mapv (fn [i] (http/get "http://http-kit.org/" (fn [res] (info "first callback") (let [res2 @(http/get "http://http-kit.
(->> (range 0 4)
(mapv (fn [i]
(http/get "http://http-kit.org/"
(fn [res]
(info "first callback")
(let [res2 @(http/get "http://http-kit.org/")]
(info "second callback ")))))))
打印4s第一次回拨消息时卡住了
如果我将范围更改为0..3,它将工作,同步版本也工作
更新:
(info)
是一个tauenso.timber
日志库我目前的假设是,您会因为耗尽线程池而陷入死锁:
http/get
(这将需要一个新线程)
http/get
就无法运行
保养http/default pool
检查线程池http工具包的状态。在那里,您可以看到如下内容:
#object[java.util.concurrent.ThreadPoolExecutor 0x5a99e5c "java.util.concurrent.ThreadPoolExecutor@5a99e5c[Running, pool size = 8, active threads = 0, queued tasks = 0, completed tasks = 24]"]
当你没有陷入僵局的时候。或
#object[java.util.concurrent.ThreadPoolExecutor 0x5a99e5c "java.util.concurrent.ThreadPoolExecutor@5a99e5c[Running, pool size = 8, active threads = 8, queued tasks = 8, completed tasks = 28]"]
当你这么做的时候
我已经在我的机器上进行了测试(显示8为(.availableProcessors(Runtime/getRuntime))
),我得到了上面的结果。当我运行超过8个请求时,我陷入了僵局
关于我目前的假设是,通过耗尽线程池,您会陷入死锁:
http/get
(这将需要一个新线程)
http/get
就无法运行
保养http/default pool
检查线程池http工具包的状态。在那里,您可以看到如下内容:
#object[java.util.concurrent.ThreadPoolExecutor 0x5a99e5c "java.util.concurrent.ThreadPoolExecutor@5a99e5c[Running, pool size = 8, active threads = 0, queued tasks = 0, completed tasks = 24]"]
当你没有陷入僵局的时候。或
#object[java.util.concurrent.ThreadPoolExecutor 0x5a99e5c "java.util.concurrent.ThreadPoolExecutor@5a99e5c[Running, pool size = 8, active threads = 8, queued tasks = 8, completed tasks = 28]"]
当你这么做的时候
我已经在我的机器上进行了测试(显示8为(.availableProcessors(Runtime/getRuntime))
),我得到了上面的结果。当我运行超过8个请求时,我陷入了僵局
关于这看起来像是由于http kit客户端线程池在回调函数完成之前不会释放线程而导致的问题。因此,它最终会耗尽线程 因此,我开始思考如何使回调函数更快,并提出了以下解决方案: 我已经为http kit client get创建了异步包装函数,它使用回调中的
clojure.core.async/chan
快速将结果放入通道,然后等待结果并执行重回调:
(defn async-http-get
[url opts callback]
(let [channel (chan)]
(http/get url opts #(go (>! channel %)))
(go (callback (<! channel)))
nil))
问题似乎是由于http kit客户端线程池在回调函数完成之前不会释放线程造成的。因此,它最终会耗尽线程 因此,我开始思考如何使回调函数更快,并提出了以下解决方案: 我已经为http kit client get创建了异步包装函数,它使用回调中的
clojure.core.async/chan
快速将结果放入通道,然后等待结果并执行重回调:
(defn async-http-get
[url opts callback]
(let [channel (chan)]
(http/get url opts #(go (>! channel %)))
(go (callback (<! channel)))
nil))
我认为运行时没有问题。你得到了一个由4个寓言组成的向量,打印了4个“第一次回调”,打印了4个“第二次回调”。作为一个合理性检查,请记住
(范围0 4)
是4个元素,而不是5个元素。@Josh您能尝试将范围更改为10个元素吗?@Josh我认为它可能因不同的计算机而异,具体取决于CPU核。对我来说,我只是重新启动了我的mac,得到了4个derefables的响应,4个“首次回调”被打印出来,然后被卡住了。我在运行时没有看到任何问题。你得到了一个由4个寓言组成的向量,打印了4个“第一次回调”,打印了4个“第二次回调”。作为一个合理性检查,请记住(范围0 4)
是4个元素,而不是5个元素。@Josh您能尝试将范围更改为10个元素吗?@Josh我认为它可能因不同的计算机而异,具体取决于CPU核。对我来说,我刚刚重新启动了我的mac电脑,得到了4个derefables的响应,4个“first callback”被打印出来然后卡住。是的,我还认为这是一个问题,你能重现这个问题吗?是的,在我的框中,(.AvailableProcessor(Runtime/getRuntime))
为8,如果我运行8个以上的请求,它们就会卡住。是的,我还认为这是一个问题,你能重现这个问题吗?是的,在我的框中,(.availableProcessor(Runtime/getRuntime))
为8,如果我运行8个以上的请求,它们就会卡住。