在《2024年Clojure状态调查!》(点击参与)中分享您的想法。

欢迎!请查阅关于页面以了解该网站的更多信息。

+1
Libs
编辑了

在我尝试使用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的冷启动时间无关。

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

我有一个测试环境,Lambda的第三次调用创建客户端并执行S3请求。之前的调用什么都不做。
Lambda的第一次调用是冷启动,什么也不做,因此运行较慢(例如4秒)。
Lambda的第二次调用是热启动且无操作箭头>快速(例如0.002秒)
Lambda的第三次调用是热启动且第一次创建客户端箭头>慢(例如13秒)
Lambda的第四次调用及其之后的调用箭头>快速(例如0.8秒)

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

AWS 几天前发布了 Lambda 的 java11 运行时,但使用它似乎不会太多地影响执行时间。

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

...