我们在研讨会上讨论的一个常见问题是, 如何在发生故障后重新启动队列读取器。
答案并非您想象的那么简单。
小费
我们举办了一个为期一周的现场研讨会,以帮助启动一个新项目,以确保基础架构在速度和简便性之间达到良好的平衡。 通常,简单性是最重要的,它也足够快。 您可以联系Chronicle软件销售以获取更多详细信息。
我们举办了一个为期一周的现场研讨会,以帮助启动一个新项目,以确保基础架构在速度和简便性之间达到良好的平衡。 通常,简单性是最重要的,它也足够快。 您可以联系Chronicle软件销售以获取更多详细信息。
知道何时应在启动时重播消息。
仅仅知道播放了哪些消息还不够。 您需要知道在事务中成功完成了哪些消息。 假定您必须对每个消息进行一次精确处理。 更简单的选择是:
- 再次播放每条消息,并忽略重复项。
- 从末尾(或最后N分钟)开始播放每条消息,并假设已过期的任何旧消息。
更新数据库时,实现此目的的一种方法是更新数据库中一行读取的索引,方法是:
- 事务成功,不需要再次播放该消息。
- 事务失败,确实需要再次播放该消息。
重要的细节是,在任何情况下都不清楚是否应重播输入消息。
写入队列作为输出时,重新启动阅读器。
通常,建议您将结果写入输出队列。 输出队列可以代替日志记录和监视手段,但也可以记录每个事件的来源。 特别是,输出队列可以帮助:
- 以相同的顺序重放消息,这些消息来自多个输入队列。
- 确保在升级软件后,您能够兑现之前所做的决定。 即,新软件重放输入消息可能会做出不同的决定。 通过读取输出,可以确保升级后知道应该处于什么状态。
- 从为该队列的输入成功输出的最后一条消息中重新启动输入队列。
在此示例中,它仅读取一条未处理的消息。
阅读一条未处理的消息。
try (SingleChronicleQueue in = SingleChronicleQueueBuilder.binary(queuePath)
.sourceId(1) (1)
.build();
SingleChronicleQueue out = SingleChronicleQueueBuilder.binary(queuePath2)
.rollCycle(RollCycles.TEST_DAILY)
.build()) {
MarketDataListener mdListener = out.createAppender()
.methodWriterBuilder(MarketDataListener.class)
.recordHistory(true) (2)
.get();
SidedMarketDataCombiner combiner = new SidedMarketDataCombiner(mdListener);
MethodReader reader = in.createTailer()
.afterLastWritten(out) (3)
.methodReader(combiner);
assertTrue(reader.readOne());
}
Give the queue a unique id for tracing purposes.
Write a history for timings and sources for each message processed.
Read the output queue to see what the last message processed was.
每次都做这一切真的很低效。 每个消息唯一需要的行是
reader.readOne();
结论
尽管有多种方法可以实现重新启动,但是如果需要,可以对这种最常用的方法之一进行内置支持很有用。
在下一部分中。
翻译自: https://www.javacodegeeks.com/2017/03/microservices-chronicle-world-part-4.html