如何强制AmazonSQSBufferedAsyncClient刷新邮件?

时间:2014-06-17 17:28:37

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

我正在使用AWS SDK for Java,而我正在使用缓冲异步sqs客户端来批量请求,以便降低成本。

当我的应用程序关闭时,我想确保缓冲区中没有消息等待,但我在客户端上看不到.flush()方法。

调用时AmazonSQSBufferedAsyncClient.shutdown()是否会刷新我的消息?我查看了source code,目前还不清楚。该方法会在shutdown()上调用QueueBuffer,但在QueueBuffer.shutdown()内面会显示

public void shutdown() {
  //send buffer does not require shutdown, only
  //shut down receive buffer
  receiveBuffer.shutdown();
}

此外,.shutdown()的文档说:

  

关闭此客户端对象,释放可能的任何资源   保持开放。 这是一种可选方法,不需要调用方   称之为,但如果他们想明确释放任何开放的话   资源。客户端关闭后,不应该使用它   提出更多要求。

对于此应用程序,我需要确保在缓冲时不会丢失任何消息。我是否需要使用普通AmazonSQSClient而不是缓冲/异步来手动处理?

2 个答案:

答案 0 :(得分:2)

With 1.11.37 version of the SDK, there is a configuration parameter just for this purpose in QueueBufferConfig.

AmazonSQSBufferedAsyncClient bufClient =
    new AmazonSQSBufferedAsyncClient(
        realAsyncClient,
        new QueueBufferConfig( )
            .withFlushOnShutdown(true)
    );

答案 1 :(得分:0)

有一种方法可以显式调用flush,但是它无法访问,实际上我无法在amazon代码中找到对该方法的任何调用。似乎缺少某些东西。

在异步客户端上调用shutdown时,它会执行以下代码:

public void shutdown() {
    for( QueueBuffer buffer : buffers.values() ) {
        buffer.shutdown();
    }
    realSQS.shutdown();
}

QueueBuffer #shutdown()看起来像这样:

/**
 * Shuts down the queue buffer.  Once this method has been called, the 
 * queue buffer is not operational and all subsequent calls to it may fail
 * */
public void shutdown() {
    //send buffer does not require shutdown, only
    //shut down receive buffer
    receiveBuffer.shutdown();
}

所以看起来他们故意没有调用sendBuffer.shutdown(),这个方法会刷新缓冲区中仍未发送的每条消息。

您是否在关闭SQS客户端并丢失消息时发现了这种情况?看起来他们已经意识到这一点并且不应该发生这种情况,但是如果你想确定你可以用反射来调用那个方法,那它真的很讨厌,但它会满足你的需求。

    AmazonSQSBufferedAsyncClient asyncSqsClient = <your initialization code of the client>;
    Field buffersField = ReflectionUtils.findField(AmazonSQSBufferedAsyncClient.class, "buffers");
    ReflectionUtils.makeAccessible(buffersField);
    LinkedHashMap<String, Object> buffers = (LinkedHashMap<String, Object>) ReflectionUtils.getField(buffersField, asyncSqsClient);
    for (Object buffer : buffers.values()) {
        Class<?> clazz = Class.forName("com.amazonaws.services.sqs.buffered.QueueBuffer");
        SendQueueBuffer sendQueueBuffer = (SendQueueBuffer) ReflectionUtils.getField(ReflectionUtils.findField(clazz, "sendBuffer"), buffer);
        sendQueueBuffer.flush();//finally
    }

我想这样的东西应该有效。让我知道!