新消息停止进入后通知订户

时间:2019-05-22 12:28:23

标签: message-queue

在希望用户在短时间内进行一些更改的应用中,我想使用消息队列来收集这些事件,并且仅在新更改停止出现一段时间后才通知侦听器X

预期的工作流程为:

  • 用户进行编辑->添加到队列中的消息
  • 用户再次进行编辑->添加到队列中的消息
  • 有些时候过去了
  • 所有未完成的更改都会通知消费者

我已经研究了几种不同的消息队列的文档,但是似乎没有一个消息盒是现成的。

我确实找到了一些可能有助于推广自己的功能,例如Kafka有一个称为linger的生产者配置,告诉它等待X ms等待更多消息添加到批处理中,但这显然是为了提高性能。另外,此选项在生产者端,而对于我的用例,在消费者端更有意义。

这是一个用例消息队列可以支持吗?缺乏结果使我认为我可能尝试使用错误的消息队列。

1 个答案:

答案 0 :(得分:0)

队列不适用于此类用例。我建议使用Cadence Workflow来轻松实现您的逻辑。

这是一个满足您要求的稻草人设计:

  • 使用userID作为工作流ID将包含编辑信息的signalWithStart请求发送到用户工作流。它要么向工作流程传递信号,要么首先启动工作流程并向其传递信号。
  • 对该工作流的所有请求均由它缓冲。 Cadence坚决保证打开状态下只能存在一个具有给定ID的工作流程。因此,可以保证所有信号(事件)都将在属于用户的工作流中进行缓冲。
  • 配置超时后,将调用活动通知用户即将进行的更改。
  • 下一个活动将应用待处理的更改。
  • 工作流程完成。

以下是用Java实现它的工作流程代码(也支持Go客户端):

public interface BufferedEditsWorkflow {

    @WorkflowMethod
    void execute(String userId, Duration notifyAfter, Edit firstEdit);

    @SignalMethod
    void addEdit(Edit edit);
}

public interface BufferedEditsActivities {
    void notifyUser(String userId, List<Edit> edits);
    void process(String userId, List<Edit> edits);
}

public class BufferedEditsWorkflowImpl implements BufferedEditsWorkflow {

    private final List<Edit> edits = new ArrayList<>();
    private final BufferedEditsActivities activities = Workflow.newActivityStub(BufferedEditsActivities.class);

    @Override
    public void execute(String userId, Duration notifyAfter, Edit firstEdit) 
    {
        edits.add(firstEdit);
        // Cadence doesn't have limit on sleep duration.
        // It can sleep at this line for a year with no problem.
        Workflow.sleep(notifyAfter);
        activities.notifyUser(userId, edits);
        activities.process(userId, edits);
    }

    @Override
    public void addEdit(Edit edit) {
        edits.add(edit);
    }

}

启动第一次编辑工作流程的代码:

private void addFirstEdit(WorkflowClient cadenceClient, Edit edit) {
    WorkflowOptions options = new WorkflowOptions.Builder().setWorkflowId(edit.getUserId()).build();
    BufferedEditsWorkflow workflow = cadenceClient.newWorkflowStub(BufferedEditsWorkflow.class, options);
    workflow.execute(edit.getUserId(), Duration.ofHours(1), edit);
}

添加更多修改的代码。

private void addEdit(WorkflowClient cadenceClient, Edit edit) {
    WorkflowOptions options = new WorkflowOptions.Builder().setWorkflowId(edit.getUserId()).build();
    BufferedEditsWorkflow workflow = cadenceClient.newWorkflowStub(BufferedEditsWorkflow.class, options);
    workflow.addEdit(edit);
}

与使用队列进行任务处理相比,Cadence具有许多其他优点。

  • 构建具有无限到期间隔的指数重试
  • 故障处理。例如,它允许执行一个任务,如果在配置的时间间隔内两次更新均未成功,则该任务会通知另一服务。
  • 支持长时间运行的心跳操作
  • 能够实现复杂的任务依赖性。例如,在无法恢复的故障(SAGA)的情况下实现呼叫链或补偿逻辑的链接
  • 完全了解更新的当前状态。例如,当使用队列时,您就会知道队列中是否有某些消息,并且需要其他数据库来跟踪总体进度。使用Cadence可以记录每个事件。
  • 能够取消正在进行的更新。

请参见介绍Cadence编程模型的the presentation