2024 Clojure 状态调查! 中分享您的想法。

欢迎!请在 关于 页面了解更多关于其工作原理的信息。

+1

编辑

在我尝试使用 Cognitect 的 aws-api 在 Lambda 函数中从 S3 获取文件时,我遇到了意外的缓慢行为。下面的示例代码被用来获取每个相关操作所需的一般时间感。获取客户端 (aws/client {:api :s3}) 持续需要超过 4 秒钟。作为一个比较点,执行同一代码从我的本地开发环境访问同一个 S3 桶/键,执行时没有注意到同样的延迟,就像它在 Lambda 中执行时那样。

我应该指出,这个函数所在的命名空间利用了 gen-class 功能。

(defn read-s3-file
  [bucket obj-key]
  (let [_ (println (str "-----> Before declaring s3 client: " (java.time.LocalDateTime/now)))
        s3 (aws/client {:api :s3})
        _ (println (str "-----> After declaring s3 client: " (java.time.LocalDateTime/now)))
        _ (println (str "---> bucket: " bucket ", key " obj-key))
        body  (:Body (aws/invoke s3 {:op :GetObject :request {:Bucket bucket :Key obj-key}}))
        _ (println (str "-----> After GetObject: " (java.time.LocalDateTime/now)))
        ]
    (println (str "-----> Before calling slurp: " (java.time.LocalDateTime/now)))
    (slurp body)
    )
  )

这是否是由于 Lambda 所需的 java8 运行时引起的?

本地输出

clj-lead-updater.core=> (clj-lead-updater.s3/read-s3-file "automattix-incoming-emails" "tdf10001AnsSvc/0dqsmtvh5mquq3tdhpq550lnqcp6162f0k29da01")
-----> Before declaring s3 client: 2019-11-18T18:52:27.611925
-----> After declaring s3 client: 2019-11-18T18:52:27.638097
---> bucket: automattix-incoming-emails, key tdf10001AnsSvc/0dqsmtvh5mquq3tdhpq550lnqcp6162f0k29da01
-----> After GetObject: 2019-11-18T18:52:28.096044
-----> Before calling slurp: 2019-11-18T18:52:28.096431

两个相关的指标是

-----> Before declaring s3 client: 2019-11-18T18:52:27.611925
-----> After declaring s3 client: 2019-11-18T18:52:27.638097

Lambda 输出

-----> Before turning input into a map: 2019-11-17T02:27:08.705
-----> Before declaring s3 client: 2019-11-17T02:27:08.781
2019-11-17 02:27:10.641:INFO::main: Logging initialized @8431ms to org.eclipse.jetty.util.log.StdErrLog
-----> After declaring s3 client: 2019-11-17T02:27:12.923
-----> After GetObject: 2019-11-17T02:27:14.446
-----> Before calling slurp: 2019-11-17T02:27:14.446

再次,两个相关的指标是

-----> Before declaring s3 client: 2019-11-17T02:27:08.781
-----> After declaring s3 client: 2019-11-17T02:27:12.923

项目中的相关依赖项

  [org.clojure/clojure "1.10.1"]
  [com.cognitect.aws/api "0.8.391"]
  [com.cognitect.aws/endpoints "1.1.11.670"]
  [com.cognitect.aws/s3 "770.2.568.0"]

2 答案

+1

当 aws api 客户端在本地获取凭证时,它通常会直接从您的环境中、凭证文件或系统属性中获取,所有这些都是非常快速的操作。在 AWS 中运行时,它将通过网络 http 获取凭证,这自然会比文件系统操作慢。快 4 秒?可能不是,但我猜还有其他东西在起作用,但毫无疑问,这将是其中一个因素。

我至少需要几天的时间来研究这个问题。如果您有时间,请发布您在本地和 Lambda 中看到的内容。

谢谢!

感谢您如此迅速地回复。我已将环境输出的原始问题和项目中引用的(相关)依赖项更新。

再次感谢!
?qa=image&qa_blobid=2900738000518190006&qa_size=20" width="20" height="20" class="qa-avatar-image" alt="">
跟进:性能差异很可能完全由冷启动引起。在多次调用Lambda函数后,问题函数(创建aws客户端,获取凭证)的性能接近于通过repl在本地上执行同一代码时的测量时间。
+1
回复

我注意到相同的问题。在AWS Lambda环境中首次创建客户端并用其执行请求似乎有很大的开销。而这个开销似乎与Lambda冷启动时间无关。

例如,使用512M内存为lambda创建S3客户端并在1次元数据获取约需13秒。相比之下,使用aws-java-sdk(v1)在clojure中完成同样操作约为11-12秒,而与nodejs lambda相比则小于1秒。增加Lambda内存大小会大大提高速度。

在我的测试设置中,第三次调用lambda创建客户端并执行S3请求。在那之前的调用什么都不做。
1、lambda调用是冷启动且什么都不做,运行缓慢(例如,4秒)
2、lambda调用是热启动且什么都不做 => 快速(例如,0.002秒)
3、调用是热启动并首次创建客户端 => 慢(例如,13秒)
4、调用和随后的调用 => 快速(例如,0.8秒)

当作为AWS Lambda运行时,凭证作为环境变量可用,因此访问它们应该很快。

AWS几天前发布了Lambdas的java11运行时,但使用它似乎对执行时间影响不大。

我所有的代码都进行了AOT编译。

...