死信主题分区选择

默认情况下,记录被发布到死信主题时使用与原始记录相同的分区。这意味着死信主题必须至少拥有与原始记录相同数量的分区。

要改变这种行为,可以将一个 DlqPartitionFunction 实现作为 @Bean 添加到应用上下文中。应用中只能存在一个这样的 Bean。该函数会接收消费者组、失败的 ConsumerRecord 和异常作为参数。例如,如果您总是想路由到分区 0,可以使用

@Bean
public DlqPartitionFunction partitionFunction() {
    return (group, record, ex) -> 0;
}
如果您将消费者绑定的 dlqPartitions 属性设置为 1(并且 binder 的 minPartitionCount 等于 1),则无需提供 DlqPartitionFunction;框架将始终使用分区 0。如果您将消费者绑定的 dlqPartitions 属性设置为大于 1 的值(或 binder 的 minPartitionCount 大于 1),则**必须**提供一个 DlqPartitionFunction bean,即使分区数量与原始主题的分区数量相同。

也可以为 DLQ 主题定义自定义名称。为此,可以在应用上下文中创建一个 DlqDestinationResolver 实现作为 @Bean。当 binder 检测到这样的 bean 时,它将优先使用,否则将使用 dlqName 属性。如果两者都未找到,则默认使用 error.<destination>.<group>。以下是 DlqDestinationResolver 作为 @Bean 的示例。

@Bean
public DlqDestinationResolver dlqDestinationResolver() {
    return (rec, ex) -> {
        if (rec.topic().equals("word1")) {
            return "topic1-dlq";
        }
        else {
            return "topic2-dlq";
        }
    };
}

在提供 DlqDestinationResolver 实现时需要记住一件重要的事情,那就是 binder 中的 provisioner 不会自动为应用创建主题。这是因为 binder 无法推断出该实现可能发送到的所有 DLQ 主题的名称。因此,如果您使用这种策略提供 DLQ 名称,则应用有责任确保这些主题事先被创建。