我的任务可能长时间运行(几小时)。该任务由从消息队列(在我的情况下为AWS SQS)读取的多个工作程序(在我的情况下为AWS ECS实例)执行。我有多个用户将消息添加到队列中。问题是,如果Bob将5000条消息添加到队列中,足以使工作人员忙3天,那么Alice就会出现并要处理5个任务,Alice将需要等待3天才能开始任何Alice的任务。 / p>
我想在爱丽丝提交任务后立即以相同的速度向爱丽丝和鲍勃传达信息。
我通过在每个上下文中为每个用户(甚至用户提交的每个批次)创建多个队列(子队列),并在消费者请求下一条消息时在所有子队列之间交替来解决了这个问题。
至少在我的世界中,这似乎是一个普遍的问题,我想知道是否有人知道解决该问题的既定方法。
我看不到ActiveMQ的任何解决方案。我对Kafka有所了解,因为它具有在一个主题中循环分区的能力,并且可能起作用。现在,我正在使用Redis实现某些功能。
答案 0 :(得分:0)
我建议使用Cadence Workflow而不是队列,因为它支持长期运行的操作和状态管理。
在您的情况下,我将为每个用户创建一个工作流实例。每个新任务将通过信号API发送到用户工作流程。然后,工作流实例会将收到的任务排队,并一一执行。
这是实现的概述:
public interface SerializedExecutionWorkflow {
@WorkflowMethod
void execute();
@SignalMethod
void addTask(Task t);
}
public interface TaskProcessorActivity {
@ActivityMethod
void process(Task poll);
}
public class SerializedExecutionWorkflowImpl implements SerializedExecutionWorkflow {
private final Queue<Task> taskQueue = new ArrayDeque<>();
private final TaskProcesorActivity processor = Workflow.newActivityStub(TaskProcesorActivity.class);
@Override
public void execute() {
while(!taskQueue.isEmpty()) {
processor.process(taskQueue.poll());
}
}
@Override
public void addTask(Task t) {
taskQueue.add(t);
}
}
然后通过信号方法将任务排队到工作流中的代码:
private void addTask(WorkflowClient cadenceClient, Task task) {
// Set workflowId to userId
WorkflowOptions options = new WorkflowOptions.Builder().setWorkflowId(task.getUserId()).build();
// Use workflow interface stub to start/signal workflow instance
SerializedExecutionWorkflow workflow = cadenceClient.newWorkflowStub(SerializedExecutionWorkflow.class, options);
BatchRequest request = cadenceClient.newSignalWithStartRequest();
request.add(workflow::execute);
request.add(workflow::addTask, task);
cadenceClient.signalWithStart(request);
}
与使用队列进行任务处理相比,Cadence具有许多其他优点。
请参见介绍Cadence编程模型的the presentation。