簡體   English   中英

從 Java Lambda 減少 DynamoDB 延遲

[英]Reduce DynamoDB latency from Java Lambda

如何減少我目前在 Lambda 和 DynamoDB 之間看到的延遲?

這是一個 Java lambda,使用 AWS 提供的 SDK 執行 2 個 DynamoDB 操作中的每一個需要 4 秒。 我聽說這些通常在 <20 毫秒內完成,但對我來說它高 3 個數量級。 這些長操作是 (a) 創建 DynamoDB 對象和 (b) 在一個完全空的表上執行表掃描(下面的代碼)。

我應該怎么做才能減少延遲?

我嘗試過的事情

  • lambda 和 DynamoDB 都在同一區域 (eu-west-1)。
  • 該表有 5 個 RCU 和 WCU。 增加這些沒有幫助。
  • lambda 使用的最大內存為 92MB。 如果我分配最小 128MB,那么它會在 15 秒后超時。 將內存增加到 512MB 可實現每次調用 4 秒的計時,再次增加到 1GB 可將其減少到每次調用 2 秒。 然而,對於一個微不足道的 lambda 來說,這是一個荒謬的內存量,仍然讓我有超過 200 倍的預期延遲。
  • 表格指標顯示表格掃描時間在 12 毫秒到 15 毫秒之間。 這是我所期待的。 即使有建立網絡連接的開銷,我仍然期待幾十毫秒,而不是幾秒。
  • 我正在使用 AWS 控制台中的測試函數觸發 lambda。 我還嘗試通過 API Gateway(這是我最終將要做的)觸發,結果相同。
  • 我已經嘗試快速連續多次調用 lambda(以減少我遭受設置成本的可能性)。 它沒有幫助。
  • 日志顯示 lambda 的所有其他部分運行得非常快(毫秒)。

代碼片段

創建 DynamoDB 對象

log("Creating AmazonDynamoDB");
AmazonDynamoDB db = AmazonDynamoDBClientBuilder                        
  .standard()
  .withRegion(Regions.EU_WEST_1)
  .build();

log("Creating DynamoDBMapper");
DynamoDBMapper mapper = new DynamoDBMapper(db);

執行掃描

log("Scanning table");
List<MyItem> items = dbMapper.scan(MyTable.class, new DynamoDBScanExpression());
for (MyItem item : items) {
        // Irrelevant - there aren't any
}
log("Table scan complete");

示例日志

這是運行的日志。

20:07:41 START RequestId: 9d436db7-5d32-11e8-8555-8564d2094ccc Version: $LATEST
20:07:41 Received request: APIGatewayRequest(path=/data/foo, httpMethod=POST, body=)
20:07:41 Creating AmazonDynamoDB
20:07:45 Creating DynamoDBMapper
20:07:45 Creating DataHandler
20:07:45 Handling request
20:07:45 Scanning table
20:07:49 Table scan complete
20:07:49 Request handled - response object: []
20:07:49 APIGatewayResponse(isBase64Encoded=false, statusCode=200, body=[], headers={})
20:07:49 END RequestId: 9d436db7-5d32-11e8-8555-8564d2094ccc
20:07:49 REPORT RequestId: 9d436db7-5d32-11e8-8555-8564d2094ccc Duration: 8256.47 ms Billed Duration: 8300 ms Memory Size: 512 MB Max Memory Used: 85 MB

根據這個帖子從該AWS論壇的AWS員工,在建設AmazonDynamoDB對象是昂貴的。 將構造(返回)移動到靜態初始值設定項中並結合一點額外的內存(=CPU)分配基本上可以解決問題。

日志中的數據仍然顯示,上面確定的 2 個緩慢步驟中的每一個都需要大約一半的時間。 因此,據推測, AmazonDynamoDB對象的構建和首次使用都很慢。

顯然,這對第一個請求沒有幫助,它仍然需要與問題相同的時間。 但是,一旦 lambda 被加熱,后續請求需要大約 15毫秒(遠低於 100 毫秒的最低計費閾值)。 解決第一個請求問題很容易理解- 例如,通過使用 CloudWatch Events 安排對 lambda 的定期調用以使其保持溫暖。

2020年編輯:也可以使用Provisioned Currency來處理冷啟動問題。

(不是答案,但我希望它可以幫助其他人)我已經在此處發布了更新,除此之外,我還必須在 dynamoDb 上進行“虛擬”查詢操作(以打開與它的連接),就在如果幫助別人,我的代碼如下:

class MyFunctionHandler : RequestHandler<Map<String, Any>, ApiGatewayResponse> {

//var dbClient: AmazonDynamoDB = AmazonDynamoDBClientBuilder.defaultClient()
var dbClient: AmazonDynamoDB = AmazonDynamoDBClientBuilder
        .standard().withRegion("sa-east-1").build()

override fun handleRequest(input: Map<String, Any>, context: Context): ApiGatewayResponse {
    LOG.info("received input: $input")

    input["wakeup"]?.let {

        if (it == true) {

            with(EmpresaRepository(dbClient)) {
                LOG.info("### Connection was not stablished at this point")

                someDynamoQueryHere("dummyParameter")

                LOG.info("### The Connection was opened and will keep alived for 1 minute")
            }

            return buildResponseForWakeUpReq(input)
        }
    }

    val param = input["queryStringParameters"]?.toString()
...

將打開 dynamoDb 連接的后續操作將以毫秒為單位發生!

所有 aws ClientBuilder.build() 函數在 lambda 中都需要一段時間,並且依賴於專用於該函數的內存。 但是,如果容器已經初始化並且您第二次或在后續請求中調用 ClientBuilder.build(),則它以毫秒而不是秒為單位發生。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM