在Java中异步处理队列中的Amazon SQS消息

时间:2014-01-31 10:57:33

标签: java amazon-web-services

我很难搞清楚如何处理来自Amazon SQS的消息。

我正在尝试实施以下内容:

  1. SQS的听众
  2. 处理来自队列的消息并将其添加到DB
  3. 从队列中删除已处理的消息
  4. 让我困扰的是如何实施第2步。我有课程SQSConnectorProfileDao。现在我想通过初始化SQSConnector中的ProfileDao并从队列接收消息来实现简单的实现。我的想法是启动新线程,开始轮询消息,当队列为空时,从ProfileDao中断线程。

    返回/处理消息的最佳方式是什么(回调函数?),如果还有其他方法可以做到这一点,我可以选择。

    谢谢

1 个答案:

答案 0 :(得分:3)

我使用Java的ExecutorServiceFutureConcurrentLinkedQueue与SQS完成了类似的工作。

ExecutorService创建一个线程池,该线程池可以执行实现Callable接口的类并返回Future。当ExecutorService创建期货时,我将它们推送到一个在一个线程中运行的ConcurrentLinkedQueue,并在期货完成时处理结果。

实施检查SQS并异步启动工作:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class SqsProcessor {

    private static final int THREAD_COUNT = 100;
    private ExecutorService _executor = null;
    private FutureResultProcessor futureResultProcessor = null;

    public SqsProcessor() {
        _executor = Executors.newFixedThreadPool(THREAD_COUNT);
        _futureResultProcessor = new FutureResultProcessor();
    }

    public void waitReceive() {

        // Receive a SQS message

        // Start the work related to the SQS message
        Callable<MyWorkderResult> sqsWorker = new MyWorker(sqsMessage);
        Future<MyWorkerResult> sqsFuture = _executor.submit(sqsWorker);

        // Send to the queue so the result can be processed when it completes
        _futureResultProcessor.add(sqsFuture);
    }
}

完成工作的班级:

import java.util.concurrent.Callable;

public class MyWorker implements Callable<MyWorkerResult> {

    private String _sqsMessage = null;

    public MyWorker(String sqsMessage) {
        _sqsMessage = sqsMessage;
    }

    @Override
    public MyWorkerResult call() throws Exception {
        // Do work relating to the SQS message
    }
}

保留工作成果:

public class MyWorkerResult {
    // Results set in MyWorker call()
}

ConcurrentLinkedQueue接收和处理未来结果:

import java.util.concurrent.Future;
import java.util.concurrent.ConcurrentLinkedQueue;

public class FutureResultProcessor extends Thread {

    private final ConcurrentLinkedQueue<Future<MyWorkerResult>> resultQueue = new ConcurrentLinkedQueue<Future<MyWorkerResult>>();
    private final Integer CHECK_SLEEP = 300;

    public FutureResultProcessor() {
    }

    public void run() {
        while(true) {
            Future<MyWorkerResult> myFuture = resultQueue.poll();

            if(myFuture == null) {
                // There's nothing to process
                try { Thread.sleep(CHECK_SLEEP); } catch (InterruptedException e) {}
                continue;
            }

            // Process result
            if(myFuture != null) {

                MyFutureResult myFutureResult = myFuture.get();

                // Process result
            }
        }
    }

    public void add(Future<MyWorkerResult> sqsFuture) {
        resultQueue.offer(sqsFuture);
    }
}

或者你可以收集一组期货,等待它们全部完成,然后再处理结果。

Akka可能非常适合。我没有直接使用它,但它提供了一个运行异步任务的框架,提供了错误处理,甚至可以将任务分发给远​​程实例。