当前位置 : 主页 > 网络安全 > 测试自动化 >

异步 – 使用core.async和阻塞客户端/驱动程序:是否有性能优势?

来源:互联网 收集:自由互联 发布时间:2021-06-22
我正在使用Clojure编写Web应用程序后端,其中包括: http-kit作为HTTP服务器和客户端(非阻塞) monger作为我的DB驱动程序(阻塞) clj-aws-s3作为S3客户端(阻止) 我知道事件驱动的非阻塞堆栈的性能
我正在使用Clojure编写Web应用程序后端,其中包括:

> http-kit作为HTTP服务器和客户端(非阻塞)
> monger作为我的DB驱动程序(阻塞)
> clj-aws-s3作为S3客户端(阻止)

我知道事件驱动的非阻塞堆栈的性能优势,例如你在NodeJS和Play Framework上找到的堆栈(this question帮助我),以及它如何产生更好的负载能力.出于这个原因,我正在考虑使用core.async使我的后端异步.

我的问题是:您是否可以通过在阻止客户端/驱动程序库的基础上使用core.async来重新创建非阻塞Web堆栈的性能优势?

阐述:

我目前正在做的是通常的同步调用:

(defn handle-my-request [req]
  (let [data1 (db/findData1)
        data2 (db/findData2)
        data3 (s3/findData3)
        result (make-something-of data1 data2 data3)]
    (ring.util.response/response result))
  )

我打算做的是在thread块中包含任何涉及IO的调用,并在go块内同步它,

(defn handle-my-request! [req resp-chan] ;; resp-chan is a core.async channel through which the response must be pushed
  (go 
    (let [data1-ch (thread (db/findData1)) ;; spin of threads to fetch the data (involves IO)
          data2-ch (thread (db/findData2))
          data3-ch (thread (s3/findData3))
          result (make-something-of (<! data1-ch) (<! data2-ch) (<! data3-ch))] ;; synchronize
     (->> (ring.util.response/response result)
       (>! resp-chan)) ;; send response
     )))

这样做有什么意义吗?

我这样做是因为这是我发现的最佳实践,但它们的性能优势对我来说仍然是一个谜.我认为同步堆栈的问题是它们每个请求使用一个线程.现在看来他们使用不止一个.

在此先感谢您的帮助,祝您有个美好的一天.

简单的答案是否定的,你不会以这种方式增加容量.如果你有内存可以容纳100个线程,那么每3秒间隔就有300个“线程秒”的容量.所以,假设每个块需要一秒钟才能执行.如果每个请求同步运行,保持线程整整三秒,或者阻塞 – 异步,保持一个线程一秒钟三次,则无关紧要,您将永远不会每三秒钟提供超过100个请求.

但是,如果您使一步异步,则突然您的代码每个请求只需要两个线程秒,因此您现在可以每三秒提供300/2 = 150个请求.

更复杂的答案是它可能会变得更好或更糟,取决于客户端或Web服务器处理超时的方式,客户端重试请求的速度/频率,代码的可并行化程度,线程交换的成本等等.如果您尝试在同步实现中执行200个请求,然后100秒将在3秒后通过,剩余的100个将在6秒内完成.在异步实现中,由于它们都在各种异步接口处竞争线程,因此大多数都需要5-6秒才能完成.就是这样.但是如果这些块是可并行化的,那么一些请求可能只需一秒钟即可完成,所以也就是这样.

所以在最有利的方面它取决于,但最终容量是线程秒,并且通过标准同步或阻塞 – 异步,它们都是相同的.这不是特定的Clojure,并且肯定有很多更深入的资源详细说明了所有边缘情况,而不是我在这里提供的.

网友评论