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 中运行时,它将通过网络获取凭证,这将自然比文件系统操作慢。4 秒更快?可能不会,所以我认为还有其他因素在作用,但确实这是一个因素。

至少需要几天时间我才能有时间去研究这个问题。如果您有时间,请贴出您在本地和在 Lambda 中看到的输出。

谢谢!

非常感谢您如此迅速地回复。我已经将两个环境中的输出以及项目中的(相关)依赖项更新到了原始问题中。

再次感谢!
跟进:性能差异很可能是完全由于冷启动引起的。在多次调用 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 编译的。

...