Rightnow,我正在尝试实现基于队列工作线的设计,我们在队列中收到数百万条消息。工人是有限的,所以我使用以下代码将工作分配给工人。我正在使用ExecutorService:
ExecutorService pool = Executors.newFixedThreadPool(POOL_SIZE);
while(LISTEN_FOR_MESSAGE_FLAG == true){
Message receivedMessage = sqsClient.receiveMessage(request);
if(receivedMessage == null){
Thread.sleep(5000); // sleep for 5 seconds
}
else {
// lock the message for a certain amount of time (60 secs).
// Other workers can't receive a message, when it is locked.
sqsClient.changeMessageVisibility(receivedMessage, 60);
pool.execute(new Task(receivedMessage); // process the message.
}
}
我目前正在使用Amazon SQS作为队列。上面的代码有严重的问题。它每5秒接收一次消息,并以可见性超时锁定它们。一旦可见性超时消失,此锁将被破坏。这导致工人持有不再被锁定的消息。因此,它存在重复处理的问题。 注意:Amazon SQS提供了一种扩展可见性超时的方法。
请帮助,如何编写上述代码来处理此案例。
答案 0 :(得分:1)
如果你改变了
pool.execute(new Task(receivedMessage);
到:
Future<?> task = pool.submit(new Task(receivedMessage));
您可以执行辅助任务,在时间用完之前延长可见时间。辅助任务基本上对Future执行get(),超时时间小于60秒锁定。当发生TimeoutException时,它会扩展可见性超时,并再次开始等待Future。
pool.execute(new Runnable() {
@Override
public void run() {
boolean done = false;
while (!done) {
try {
task.get(50, TimeUnit.SECONDS);
done = true;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
done = true;
} catch (ExecutionException e) {
done = true;
// handle e.getCause()
} catch (TimeoutException e) {
// we need more time
sqsClient.changeMessageVisibility(receivedMessage, 60);
}
}
}
});