如何在Spring Cloud AWS SQS中以编程方式设置消息处理程序?

时间:2016-09-28 18:44:52

标签: spring rabbitmq spring-cloud amazon-sqs

也许有人对我的下列问题有所了解:

我目前正在开展一个项目,我希望将AWS SQS与Spring Cloud集成使用。对于接收器部分,我想提供一个API,用户可以注册一个"消息处理程序"在队列上,这是一个接口,将包含用户的业务逻辑,例如

MyAwsSqsReceiver receiver = new MyAwsSqsReceiver();
receiver.register("a-queue-name", new MessageHandler(){
  @Override
  public void handle(String message){
    //... business logic for the received message
  }
});

我找到了例子,例如 https://codemason.me/2016/03/12/amazon-aws-sqs-with-spring-cloud/ 并阅读文件 http://cloud.spring.io/spring-cloud-aws/spring-cloud-aws.html#_sqs_support

但我唯一能找到的就是" connect"用于处理传入消息的功能是对方法的注释,例如, @SqsListener@MessageMapping

但是,这些注释固定为某个队列名称。所以现在我不知所措,如何动态地连接"我提供的" MessageHandler" (从我的API)到指定的queuename的传入消息。

在Config示例中有一个SimpleMessageListenerContainer,它获得QueueMessageHandler集,但是这个QueueMessageHandler看起来不像 是设置我的处理程序或覆盖其方法并提供我自己的QueueMessageHandler子类的正确位置。

我已经使用Spring Amqp集成和RabbitMq做了类似的事情,并认为它与AWS SQS类似。

有没有人有想法,如何做到这一点?

thx + bye, Ximon

修改

我发现,Spring JMS实际上可以做到这一点,例如 www.javacodegeeks.com/2016/02/aws-sqs-spring-jms-integration.html 。有谁知道,使用JMS协议有什么后果,好还是坏?

2 个答案:

答案 0 :(得分:0)

当我们做Spring和SQS时,我们使用spring-cloud-starter-aws-messaging。

然后只创建一个Listener类

@Component
public class MyListener {

@SQSListener(value="myqueue")
public void listen(MyMessageType message) {
//process the message
}
}

答案 1 :(得分:0)

我面临同样的问题。

我试图以一种不寻常的方式在构建时设置一个 Aws 客户端 bean,然后我使用预定的注释,而不是使用 sqslistener 注释从特定队列中使用,我可以通过编程方式池< /strong>(在我的例子中每 10 秒)我想从哪个队列中消费。

我做了一个例子,遍历属性中定义的队列,然后从每个队列中消费。

客户端 Bean:

@Bean
@Primary
public AmazonSQSAsync awsSqsClient() {
    return AmazonSQSAsyncClientBuilder
            .standard()
            .withRegion(Regions.EU_WEST_1.getName())
            .build();
}

消费者:

// injected in the constructor
private final AmazonSQSAsync awsSqsClient;

@Scheduled(fixedDelay = 10000)
public void pool() {
    properties.getSqsQueues()
            .forEach(queue -> {
                val receiveMessageRequest = new ReceiveMessageRequest(queue)
                        .withWaitTimeSeconds(10)
                        .withMaxNumberOfMessages(10);

                // reading the messages
                val result = awsSqsClient.receiveMessage(receiveMessageRequest);
                val sqsMessages = result.getMessages();
                log.info("Received Message on queue {}: message = {}", queue, sqsMessages.toString());

                // deleting the messages
                sqsMessages.forEach(message -> {
                    val deleteMessageRequest = new DeleteMessageRequest(queue, message.getReceiptHandle());
                    awsSqsClient.deleteMessage(deleteMessageRequest);
                });
            });
}

只是为了澄清,就我而言,我需要多个队列,每个租户一个,每个队列的队列 URL 都在属性文件中传递。当然,在您的情况下,您可以从另一个来源获取队列名称,也许是一个 ThreadLocal,其中包含您在运行时创建的队列。

如果您愿意,您还可以尝试使用 JMS 方法创建消息使用者并为您希望的每个使用者添加一个侦听器(请参阅文档 Aws Jms documentation)。