Clojure - 并行执行一堆HTTP请求 - pmap?

 熙8778_565 发布于 2023-01-30 14:21

我需要发出200个左右的HTTP请求.我希望它们可以并行运行,也可以批量运行,我不知道在Clojure中可以从哪里开始.pmap似乎有我想要的效果,例如,使用http.async.client:

(defn get-json [url]
    (with-open [client (http/create-client)]
        (let [resp (http/GET client url)]
            (try
                (println 1)
                (http/string (http/await resp))
                (println "********DONE*********")
                nil

            (catch Exception e (println e) {})))))


music.core=> (pmap get-json [url url2])
1
1
********DONE*********
********DONE*********
(nil nil)

但我不能证明请求实际上是并行执行的.我是否需要调用JVM的Thread API?我正在四处寻找其他图书馆,如Netty,Lamina,Aleph - 我应该使用其中一个吗?请指出我正确的方向,以了解最佳实践/最简单的解决方案.

2 个回答
  • 理想情况下,您不希望绑定一个等待每个http请求结果的pmap线程,因此或其他基于线程的方法并不是一个好主意.

    你真正想做的是:

    以异步方式触发所有请求

    只用一个线程等待结果

    我建议的方法是使用http-kit立即触发所有异步请求,产生一系列的promise.然后,您只需要在单个线程中取消引用所有这些promise,这将阻塞线程,直到返回所有结果.

    就像是:

    (require '[org.httpkit.client :as http])
    
    (let [urls (repeat 100 "http://google.com") ;; insert your URLs here
          promises (doall (map http/get urls))
          results (doall (map deref promises))]
      #_do_stuff_with_results 
      (first results))
    

    2023-01-30 14:22 回答
  • 你所描述的是一个非常好的用途,pmap我会以类似的方式处理它.

    至于"证明"它并行运行,你必须相信每次迭代pmap都会在新线程中运行该函数.但是,一个简单的方法是确保将线程id打印为完整性检查:

    user=> (defn thread-id [_] (.getId (Thread/currentThread)))
    
    user=> (pmap thread-id [1 2 3])
    
    (53 11 56)
    

    由于线程数实际上是不同的 - 意味着clojure每次都在创建一个新线程 - 您可以放心地相信JVM将并行运行您的代码.

    另请参阅其他并行函数,如pvalues和pcalls.它们为您提供了不同的语义,可能是正确的答案,具体取决于手头的问题.

    2023-01-30 14:22 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有