Quarkus - DynamoDB + HTTP lambda 第一次响应慢
Quarkus - DynamoDB + HTTP lambda slow first response
我创建了一个测试项目,其中结合了两个指南:Quarkus-DynamoDB and Quarkus-HTTP lambda。这样做的最终目标是有一个示例项目,其中 lambda 与 DynamoDB 进行通信,并且这一切都是本地编译的(使用 GraalVM)。
这个方法效果比较好。我设法使用第二个指南中的工具将项目部署到 AWS lambda,并且我在调用端点时得到的响应符合预期。
但是,我对性能有一些疑问,尤其是在启动之后。
当点击第一个指南中的简单“hello”端点时,时间如下所示:
2021-05-09T20:41:06.986+02:00 START RequestId: ccc69797-3e58-47b1-a475-f2b0cc93cd7d Version: $LATEST
2021-05-09T20:41:06.986+02:00 __ ____ __ _____ ___ __ ____ ______
2021-05-09T20:41:06.986+02:00 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
2021-05-09T20:41:06.986+02:00 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
2021-05-09T20:41:06.986+02:00 --\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2021-05-09T20:41:06.986+02:00 2021-05-09 18:41:06,980 INFO [io.quarkus] (main) quarkus-amazon-lambda-http-archetype 1.0-SNAPSHOT native (powered by Quarkus 1.13.3.Final) started in 0.239s.
2021-05-09T20:41:06.986+02:00 2021-05-09 18:41:06,985 INFO [io.quarkus] (main) Profile prod activated.
2021-05-09T20:41:06.986+02:00 2021-05-09 18:41:06,985 INFO [io.quarkus] (main) Installed features: [amazon-dynamodb, amazon-lambda, cdi, mutiny, resteasy, resteasy-jackson, resteasy-mutiny, smallrye-context-propagation]
2021-05-09T20:41:07.225+02:00 END RequestId: ccc69797-3e58-47b1-a475-f2b0cc93cd7d
2021-05-09T20:41:07.225+02:00 REPORT RequestId: ccc69797-3e58-47b1-a475-f2b0cc93cd7d Duration: 237.21 ms Billed Duration: 623 ms Memory Size: 128 MB Max Memory Used: 92 MB Init Duration: 385.04 ms
从这里我们可以看出,启动后大约需要0.25秒才能收到响应(我认为这是可以预料的,我对此几乎没有经验)。然而,当到达端点“fruits”时,returns 水果列表(duh),时间看起来有点不同:
2021-05-09T20:23:00.521+02:00 START RequestId: 1ee2002c-15ad-491e-b24a-591b8d371bae Version: $LATEST
2021-05-09T20:23:00.521+02:00 __ ____ __ _____ ___ __ ____ ______
2021-05-09T20:23:00.521+02:00 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
2021-05-09T20:23:00.521+02:00 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
2021-05-09T20:23:00.521+02:00 --\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2021-05-09T20:23:00.521+02:00 2021-05-09 18:23:00,516 INFO [io.quarkus] (main) quarkus-amazon-lambda-http-archetype 1.0-SNAPSHOT native (powered by Quarkus 1.13.3.Final) started in 0.249s.
2021-05-09T20:23:00.522+02:00 2021-05-09 18:23:00,521 INFO [io.quarkus] (main) Profile prod activated.
2021-05-09T20:23:00.522+02:00 2021-05-09 18:23:00,521 INFO [io.quarkus] (main) Installed features: [amazon-dynamodb, amazon-lambda, cdi, mutiny, resteasy, resteasy-jackson, resteasy-mutiny, smallrye-context-propagation]
2021-05-09T20:23:01.657+02:00 END RequestId: 1ee2002c-15ad-491e-b24a-591b8d371bae
2021-05-09T20:23:01.657+02:00 REPORT RequestId: 1ee2002c-15ad-491e-b24a-591b8d371bae Duration: 1133.83 ms Billed Duration: 1539 ms Memory Size: 128 MB Max Memory Used: 103 MB Init Duration: 404.57 ms
2021-05-09T20:23:30.341+02:00 START RequestId: a546afa3-78a2-4219-8cef-075694c320ac Version: $LATEST
2021-05-09T20:23:30.456+02:00 END RequestId: a546afa3-78a2-4219-8cef-075694c320ac
2021-05-09T20:23:30.456+02:00 REPORT RequestId: a546afa3-78a2-4219-8cef-075694c320ac Duration: 111.38 ms Billed Duration: 112 ms Memory Size: 128 MB Max Memory Used: 105 MB
2021-05-09T20:24:53.644+02:00 START RequestId: 65104eb8-1e53-453a-bd67-ef25d3a919af Version: $LATEST
2021-05-09T20:24:53.815+02:00 END RequestId: 65104eb8-1e53-453a-bd67-ef25d3a919af
2021-05-09T20:24:53.815+02:00 REPORT RequestId: 65104eb8-1e53-453a-bd67-ef25d3a919af Duration: 168.10 ms Billed Duration: 169 ms Memory Size: 128 MB Max Memory Used: 107 MB
我们可以看到第一个请求在得到响应之前需要一秒钟的时间(我观察到它需要更长的时间)。之后的请求到达相同的端点,但速度非常快(快很多,即使您要在其上添加启动时间)。
所以这里的时间是我想知道的。为什么从 DynamoDB 的第一个请求得到响应要花这么长时间,我有什么方法可以改进吗?
第一次调用“新”Lambda 实例需要更长的时间,因为它必须初始化。这也称为 cold start.
检查第二个输出示例的以下两行:
Duration: 1133.83 ms Billed Duration: 1539 ms Memory Size: 128 MB Max Memory Used: 103 MB Init Duration: 404.57 ms
和
Duration: 111.38 ms Billed Duration: 112 ms Memory Size: 128 MB Max Memory Used: 105 MB
第一行末尾是这样的:Init Duration: 404.57 ms
。第二个没有这个,因为它不需要初始化。
关键是:当一个新的 Lambda 实例启动时,它需要初始化,这需要时间。您对此无能为力,除非在延迟是您的最高优先级的情况下尝试尽快进行初始化。你可以尝试减小包的大小(越小越好),你应该避免在你的初始化代码中做任何不必要的工作,也许它有助于增加你的 Lambdas 内存。
另一方面,在 Lambda 的初始化阶段,您绝对应该做很多事情,例如创建服务客户端、从 SSM 或 S3 或 DynamoDB 读取配置等。但所有这些都是延长 Lambda 的初始化时间。好处是以下所有请求都更快,因为它们不必这样做。
如果您不能进一步改进初始化,但您仍然对第一次调用延迟不满意,那么据我所知,您有两个选择:
- 选择另一个具有更快“冷启动”时间的运行时。
- Use provisioned concurrency.
请注意,预配置的并发确实需要额外费用。
我创建了一个测试项目,其中结合了两个指南:Quarkus-DynamoDB and Quarkus-HTTP lambda。这样做的最终目标是有一个示例项目,其中 lambda 与 DynamoDB 进行通信,并且这一切都是本地编译的(使用 GraalVM)。
这个方法效果比较好。我设法使用第二个指南中的工具将项目部署到 AWS lambda,并且我在调用端点时得到的响应符合预期。
但是,我对性能有一些疑问,尤其是在启动之后。
当点击第一个指南中的简单“hello”端点时,时间如下所示:
2021-05-09T20:41:06.986+02:00 START RequestId: ccc69797-3e58-47b1-a475-f2b0cc93cd7d Version: $LATEST
2021-05-09T20:41:06.986+02:00 __ ____ __ _____ ___ __ ____ ______
2021-05-09T20:41:06.986+02:00 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
2021-05-09T20:41:06.986+02:00 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
2021-05-09T20:41:06.986+02:00 --\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2021-05-09T20:41:06.986+02:00 2021-05-09 18:41:06,980 INFO [io.quarkus] (main) quarkus-amazon-lambda-http-archetype 1.0-SNAPSHOT native (powered by Quarkus 1.13.3.Final) started in 0.239s.
2021-05-09T20:41:06.986+02:00 2021-05-09 18:41:06,985 INFO [io.quarkus] (main) Profile prod activated.
2021-05-09T20:41:06.986+02:00 2021-05-09 18:41:06,985 INFO [io.quarkus] (main) Installed features: [amazon-dynamodb, amazon-lambda, cdi, mutiny, resteasy, resteasy-jackson, resteasy-mutiny, smallrye-context-propagation]
2021-05-09T20:41:07.225+02:00 END RequestId: ccc69797-3e58-47b1-a475-f2b0cc93cd7d
2021-05-09T20:41:07.225+02:00 REPORT RequestId: ccc69797-3e58-47b1-a475-f2b0cc93cd7d Duration: 237.21 ms Billed Duration: 623 ms Memory Size: 128 MB Max Memory Used: 92 MB Init Duration: 385.04 ms
从这里我们可以看出,启动后大约需要0.25秒才能收到响应(我认为这是可以预料的,我对此几乎没有经验)。然而,当到达端点“fruits”时,returns 水果列表(duh),时间看起来有点不同:
2021-05-09T20:23:00.521+02:00 START RequestId: 1ee2002c-15ad-491e-b24a-591b8d371bae Version: $LATEST
2021-05-09T20:23:00.521+02:00 __ ____ __ _____ ___ __ ____ ______
2021-05-09T20:23:00.521+02:00 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
2021-05-09T20:23:00.521+02:00 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
2021-05-09T20:23:00.521+02:00 --\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2021-05-09T20:23:00.521+02:00 2021-05-09 18:23:00,516 INFO [io.quarkus] (main) quarkus-amazon-lambda-http-archetype 1.0-SNAPSHOT native (powered by Quarkus 1.13.3.Final) started in 0.249s.
2021-05-09T20:23:00.522+02:00 2021-05-09 18:23:00,521 INFO [io.quarkus] (main) Profile prod activated.
2021-05-09T20:23:00.522+02:00 2021-05-09 18:23:00,521 INFO [io.quarkus] (main) Installed features: [amazon-dynamodb, amazon-lambda, cdi, mutiny, resteasy, resteasy-jackson, resteasy-mutiny, smallrye-context-propagation]
2021-05-09T20:23:01.657+02:00 END RequestId: 1ee2002c-15ad-491e-b24a-591b8d371bae
2021-05-09T20:23:01.657+02:00 REPORT RequestId: 1ee2002c-15ad-491e-b24a-591b8d371bae Duration: 1133.83 ms Billed Duration: 1539 ms Memory Size: 128 MB Max Memory Used: 103 MB Init Duration: 404.57 ms
2021-05-09T20:23:30.341+02:00 START RequestId: a546afa3-78a2-4219-8cef-075694c320ac Version: $LATEST
2021-05-09T20:23:30.456+02:00 END RequestId: a546afa3-78a2-4219-8cef-075694c320ac
2021-05-09T20:23:30.456+02:00 REPORT RequestId: a546afa3-78a2-4219-8cef-075694c320ac Duration: 111.38 ms Billed Duration: 112 ms Memory Size: 128 MB Max Memory Used: 105 MB
2021-05-09T20:24:53.644+02:00 START RequestId: 65104eb8-1e53-453a-bd67-ef25d3a919af Version: $LATEST
2021-05-09T20:24:53.815+02:00 END RequestId: 65104eb8-1e53-453a-bd67-ef25d3a919af
2021-05-09T20:24:53.815+02:00 REPORT RequestId: 65104eb8-1e53-453a-bd67-ef25d3a919af Duration: 168.10 ms Billed Duration: 169 ms Memory Size: 128 MB Max Memory Used: 107 MB
我们可以看到第一个请求在得到响应之前需要一秒钟的时间(我观察到它需要更长的时间)。之后的请求到达相同的端点,但速度非常快(快很多,即使您要在其上添加启动时间)。
所以这里的时间是我想知道的。为什么从 DynamoDB 的第一个请求得到响应要花这么长时间,我有什么方法可以改进吗?
第一次调用“新”Lambda 实例需要更长的时间,因为它必须初始化。这也称为 cold start.
检查第二个输出示例的以下两行:
Duration: 1133.83 ms Billed Duration: 1539 ms Memory Size: 128 MB Max Memory Used: 103 MB Init Duration: 404.57 ms
和
Duration: 111.38 ms Billed Duration: 112 ms Memory Size: 128 MB Max Memory Used: 105 MB
第一行末尾是这样的:Init Duration: 404.57 ms
。第二个没有这个,因为它不需要初始化。
关键是:当一个新的 Lambda 实例启动时,它需要初始化,这需要时间。您对此无能为力,除非在延迟是您的最高优先级的情况下尝试尽快进行初始化。你可以尝试减小包的大小(越小越好),你应该避免在你的初始化代码中做任何不必要的工作,也许它有助于增加你的 Lambdas 内存。
另一方面,在 Lambda 的初始化阶段,您绝对应该做很多事情,例如创建服务客户端、从 SSM 或 S3 或 DynamoDB 读取配置等。但所有这些都是延长 Lambda 的初始化时间。好处是以下所有请求都更快,因为它们不必这样做。
如果您不能进一步改进初始化,但您仍然对第一次调用延迟不满意,那么据我所知,您有两个选择:
- 选择另一个具有更快“冷启动”时间的运行时。
- Use provisioned concurrency.
请注意,预配置的并发确实需要额外费用。