请在 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 中看到的输出。

谢谢!

谢谢您的快速回复。我已经将原始问题更新为两个环境的输出,以及项目中引用的(相关)依赖项。

再次感谢!
跟进:性能差异很可能完全归因于冷启动。在 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 最近发布了几天的 Lambda java11 运行时,但使用它似乎并没有在很大程度上影响执行时间。

我所有的代码都是 AOT 编译的。

...