简体   繁体   English

不能使用Lambda的SQS

[英]Can't use SQS from Lambda

What I've done: 我做了什么:

I'm creating an example scheduled lambda that needs to dequeue messages from a SQS queue. 我正在创建一个示例计划的lambda,它需要从SQS队列中出列消息。 I've created it using Serverless framework and Kotlin with the following configuration: 我使用无服务器框架和Kotlin使用以下配置创建它:

service: example

provider:
  name: aws
  runtime: java8
  region: eu-west-1
  memorySize: 128
  environment:
      sqs_url:
        Ref: MessagesQueue
  iamRoleStatements:
      - Effect: Allow
        Action:
          - sqs:*
        Resource:
          Fn::GetAtt: [ MessagesQueue, Arn ]

package:
  artifact: target/example-1.0.0.jar

functions:
  dequeue:
    handler: com.example.Handler
    events:
      - schedule: rate(2 minutes)

resources:
  Resources:
    MessagesQueue:
      Type: AWS::SQS::Queue
      Properties:
        QueueName: ${self:service}-queue

Here's the Handler class: 这是Handler类:

package com.example

import com.amazonaws.services.lambda.runtime.Context
import com.amazonaws.services.lambda.runtime.RequestHandler
import org.slf4j.LoggerFactory
import com.amazonaws.services.sqs.AmazonSQSClientBuilder

class Handler:RequestHandler<Map<String, Any>, Any> {
    override fun handleRequest(input:Map<String, Any>, context:Context):Any {

        LOG.info("Initializing SQS Client...")
        val sqs = AmazonSQSClientBuilder.defaultClient()
        LOG.info("SQS Client Initialized!")

        return Any()
    }
    companion object {
        private val LOG = LoggerFactory.getLogger(Handler::class.java)
    }
}

I'm using the following AWS dependencies on my POM: 我在我的POM上使用以下AWS依赖项:

    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-java-sdk-sqs</artifactId>
        <version>1.11.251</version>
    </dependency>
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-lambda-java-core</artifactId>
        <version>1.1.0</version>
    </dependency>

My problem: 我的问题:

My lambda is logging as following: 我的lambda记录如下:

START RequestId: ac75e49e-e56e-11e7-ba03-39085056ac2f Version: $LATEST
[2017-12-20 10:15:18.015] ac75e49e-e56e-11e7-ba03-39085056ac2f INFO c.p.Handler - Initializing SQS Client...
END RequestId: ac75e49e-e56e-11e7-ba03-39085056ac2f
REPORT RequestId: ac75e49e-e56e-11e7-ba03-39085056ac2f  Duration: 6006.13 ms  Billed Duration: 6000 ms Memory Size: 128 MB  Max Memory Used: 60 MB  
2017-12-20T10:15:23.185Z ac75e49e-e56e-11e7-ba03-39085056ac2f Task timed out after 6.01 seconds

So basically something bad happens when I'm trying to initialize the SQS client, since I can't see the "done" log, bringing Lambda to timeout. 因此,当我尝试初始化SQS客户端时,基本上会发生一些不好的事情,因为我看不到“完成”日志,导致Lambda超时。

I've searched for some working example using java for a simple lambda that dequeue, but I can't find anything valuable, only SQS SDK example without lambdas. 我已经搜索了一些使用java作为一个出列的简单lambda的工作示例,但我找不到任何有价值的东西,只有没有lambdas的SQS SDK示例。

Am I doing something wrong? 难道我做错了什么? Is there maybe another SDK that I need to use inside a Lambda? 是否可能需要在Lambda中使用另一个SDK?

The answer to this question has been discussed in the question's comments section. 问题的答案已在问题的评论部分中讨论过。 But I would like to emphasize on how to troubleshoot a problem like this if faced, and so that this question will get an answer and that it may also help the community. 但我想强调如何解决这样的问题,如果面临这样的问题,那么这个问题将得到答案,它也可能有助于社区。

When faced with a problem where Lambda terminates without executing a certain part of a code, it could be due to the following reasons. 当面临Lambda终止而不执行代码的某一部分的问题时,可能是由于以下原因。

Reason 1 : Lambda times out, even before it could finish processing. 原因1 :Lambda超时,甚至在它完成处理之前。 Lambda is meant to be a server-less architecture that can be used for small tasks. Lambda是一种无服务器架构,可用于小型任务。 If you want to run a process that needs to be running all the time, I recommend using an EC2 instance. 如果要运行需要一直运行的进程,我建议使用EC2实例。 Therefore every Lambda function has a time-out for the process to complete. 因此,每个Lambda函数都有一个超时来完成该过程。 Therefore increasing the time-out of the Lambda function can solve this problem. 因此,增加Lambda函数的超时可以解决这个问题。 (Always refrain from setting time-out to a maximum of 5 mins, because it can cost you a lot for unexpected function time-outs) - This is the answer to this question . (始终不要将超时设置为最多5分钟,因为它可能会因为意外的功能超时而花费很多) - 这就是这个问题的答案

Reason 2 : If the function is using asynchronous calls like in NodeJS, your lambda can terminate while you are still executing the asynchronous call. 原因2 :如果函数使用NodeJS中的异步调用,则lambda可以在您仍在执行异步调用时终止。 Therefore have a mechanism where lambda does not terminate until all asynchronous calls have returned their values. 因此,有一种机制,在所有异步调用返回其值之前,lambda不会终止。 Best way to solve this is by using sync call libraries instead of async calls. 解决此问题的最佳方法是使用同步调用库而不是异步调用。

Reason 3 : Most obvious reason where code has mistakes in it. 原因3 :最明显的原因是代码中存在错误。 This will terminate Lambda, where you can see the error and fix it accordingly. 这将终止Lambda,您可以在其中查看错误并相应地修复它。

Reason 4 : This could also happen due to lack of proper resource allocation like memory. 原因4 :由于缺乏像内存这样的适当资源分配,也可能发生这种情况。 If your function needs a certain memory to execute, do allocate it before hand by estimating the proper value required by running the function on a test environment beforehand. 如果您的函数需要执行某个内存,请事先通过估计在测试环境中运行该函数所需的正确值来预先分配它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM