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

谢谢!

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

再次感谢!
by
跟进:性能差异很可能完全是由于冷启动引起的。在 Lambda 函数调用几次之后,创建 AWS 客户端(获取凭证)这一操作的性能,将接近通过 repl 在本地执行相同代码时所测量的时间。
+1
by

我也有同样的观察。在 AWS Lambda 环境中第一次创建客户端并使用它执行请求时,似乎存在显著的额外开销。而且这种开销似乎与 Lambda 冷启动时间无关。

例如,使用 512M 内存为 lambda 创建 S3 客户端并执行一次元数据检索大约需要 13 秒。相比之下,使用 aws-java-sdk(v1)在 clojure 中执行相同操作需要 11-12 秒,而使用 nodejs lambda 则不到一秒。增加 Lambda 内存大小会使事情变得更快。

我在一个测试设置中创建了一个 lambda 的第三次调用,用于创建客户端并执行 S3 请求。之前的调用什么都不做。
1. lambda 的第一次调用是冷启动,什么都不做,速度慢(例如 4 秒)
2. lambda 的第二次调用是热启动,什么都不做 => 快(例如 0.002 秒)
3. 第三次调用是热启动并第一次创建客户端 => 慢(例如 13 秒)
4. 第四次调用及以后的调用 => 快(例如 0.8 秒)

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

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

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

...