【问题标题】:Connection reset while sending data from AWS Lambda to SQS queue将数据从 AWS Lambda 发送到 SQS 队列时连接重置
【发布时间】:2019-06-18 00:14:45
【问题描述】:

我正在使用 AWS SDK for Java 将数据从 AWS Lambda 发送到 SQS。

我们遇到了异常:

Caused by: java.net.SocketException: Connection reset
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:115)
at java.net.SocketOutputStream.write(SocketOutputStream.java:155)
at sun.security.ssl.OutputRecord.writeBuffer(OutputRecord.java:431)
at sun.security.ssl.OutputRecord.write(OutputRecord.java:417)
at sun.security.ssl.SSLSocketImpl.writeRecordInternal(SSLSocketImpl.java:886)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:857)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)
at org.apache.http.impl.io.SessionOutputBufferImpl.streamWrite(SessionOutputBufferImpl.java:124)
at org.apache.http.impl.io.SessionOutputBufferImpl.write(SessionOutputBufferImpl.java:160)
at org.apache.http.impl.io.ContentLengthOutputStream.write(ContentLengthOutputStream.java:113)
at org.apache.http.impl.io.ContentLengthOutputStream.write(ContentLengthOutputStream.java:120)
at org.apache.http.entity.StringEntity.writeTo(StringEntity.java:167)
at org.apache.http.impl.DefaultBHttpClientConnection.sendRequestEntity(DefaultBHttpClientConnection.java:156)
at org.apache.http.impl.conn.CPoolProxy.sendRequestEntity(CPoolProxy.java:160)
at org.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:238)
at com.amazonaws.http.protocol.SdkHttpRequestExecutor.doSendRequest(SdkHttpRequestExecutor.java:63)
at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:123)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:272)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
at com.amazonaws.http.apache.client.impl.SdkHttpClient.execute(SdkHttpClient.java:72)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1236)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1056)

代码:

 List<SendMessageBatchRequestEntry> sqsList= new LinkedList<SendMessageBatchRequestEntry>();
    int batchId = 0; //To send a unique batchId for each msg in a batch
    for (Metadata metadata: metadataList) {
        String jsonString = new Gson().toJson(metadata);
        sqsList.add(new SendMessageBatchRequestEntry(batchId + "", jsonString));
        batchId++;
    }
    amazonSqs.sendMessageBatch(new SendMessageBatchRequest(queueUrl, sqsList));

背景我们正在尝试做的事情:

我们有一个主要的 Lambda 函数,它创建和初始化一个 SQS 队列,并包含应处理的每条记录的详细信息。 现在需要设置 SQS 队列以从队列中创建 X 条消息的批次,并为每个批次自动调用另一个 SQS Lambda 函数。

【问题讨论】:

    标签: java amazon-web-services aws-lambda amazon-sqs


    【解决方案1】:

    每个批次的最大消息数为 10。您不能一次用 20k 填充 SQS 队列并发送该请求。试着把它分成 10 个。

    https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-limits.html#limits-queues

    【讨论】:

    • 谢谢德扬。代码中的一个简单调整已经奏效。在这个问题的答案中添加代码。
    【解决方案2】:

    我们可以批量发送 10 个。 工作代码:

    List<SendMessageBatchRequestEntry> sqsList= new LinkedList<SendMessageBatchRequestEntry>();
        int batchId = 1; //To send a unique batchId for each msg in a batch
        for (Metadata metadata: metadataList) {
            String jsonString = new Gson().toJson(metadata);
            if (sqsList.size() == 10) {
                amazonSqs.sendMessageBatch(new SendMessageBatchRequest(queueUrl, sqsList));
                sqsList.clear();
            } 
            sqsList.add(new SendMessageBatchRequestEntry(batchId + "", jsonString)); 
            batchId++;
        }
        if(sqsList.size()>0) {
            amazonSqs.sendMessageBatch(new SendMessageBatchRequest(queueUrl, sqsList));
        }
    

    【讨论】:

      【解决方案3】:

      似乎您的代码很好,据我记得(我自己已经多次看到此错误),由于 SDK 如何重用 HTTP 连接,在使用 SDK 时会不时发生这种情况。此错误仅告诉您您的 Lambda 重置了 HTTP 连接,但 SDK 内置了重试失败请求的功能,因此如果您在每个请求上都没有看到此错误,您应该没问题。

      【讨论】:

      • 感谢 Matus... 即使我不介意 SDK 是否有故障转移。但它每次都发生在我身上。尝试发送的记录总数约为 20k。造成问题的数据数量是多少?
      • @Raushan 您使用的是 FIFO 还是标准队列,您发送到队列中的消息大小是多少?
      • 这是一个标准队列。大小为 6800 KB :(。如何分解?我的意思是它应该分批发送到队列,以便其他 Lambda 分批处理它。(因为我们被限制为 15 分钟)。
      • @Raushan 您可以发送到队列的消息的最大大小为 256 KB,任何更大的都将被丢弃。有一些解决方法,但我需要知道消息的用例和内容。为什么消息这么大?
      • 嗯...我们正在将 CRON 作业从 EC2 实例转移到 Lambda。其中一项工作有 20k 条记录,并且每条记录都需要从服务中收集它们的元数据。所以15分钟会很短。然后我们考虑将这些数据推送到队列中,然后从另一个 lambda 处理这个,该 lambda 在单个调用中处理 X 记录。所以SQS队列需要分批创建X消息。这就是我们这样做的原因。希望我朝着正确的方向前进!!!
      猜你喜欢
      • 2016-04-13
      • 2017-04-27
      • 1970-01-01
      • 2020-04-27
      • 1970-01-01
      • 2018-09-24
      • 1970-01-01
      • 1970-01-01
      • 2021-09-07
      相关资源
      最近更新 更多