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

欢迎!请查阅关于页面了解此工作的更多信息。

+1

编辑

当我尝试在Lambda函数中使用Cognitect的aws-api从S3检索文件时,遇到了意料之外的缓慢操作。下面的示例代码用于获取每个相关操作的耗时。获取客户端(aws/client {:api :s3})总是需要超过4秒钟。作为比较,相同的代码在本地开发环境中执行,访问同一S3存储桶/键,没有出现同样的明显延迟。

需要注意的是,这个函数所在的命名空间使用了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

Λàmá输出

-----> 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 中则需要不到一秒。增加 Lambda 内存大小可以使事物运行得更快。

在我的测试设置中,Lambda 的第三次调用创建客户端并执行 S3 请求。之前的调用什么都不做。
1. Lambda 的第一次调用是冷启动,它什么都不做,并且很慢(例如 4 秒)
2. Lambda 的第二次调用是热启动,它什么都不做 => 快速(例如 0.002 秒)
3. Lambda 的第三次调用是热启动,但首次创建客户端 => 慢(例如 13 秒)
4. Lambda 的后续调用 => 快速(例如 0.8 秒)

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

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

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

...