在Instrumentation-spring-rabbit中,为什么勇敢地删除消息的标题?

时间:2019-03-27 05:32:36

标签: java spring rabbitmq spring-rabbitmq zipkin

instrumentation-spring-rabbit模块中,勇敢地提取和删除标头,为什么?

我探索了其他工具(Pointcenterspring-webhttpclient等),勇敢地从不删除包含跟踪键/扩展名的标头原始消息。

删除标头有一个副作用,即重试 interceptor -already added by spring-rabbit-第二次尝试处理消息,但是因为okhttp3已删除标头在第一次重试中,因此在以后的重试中将找不到它。

2 个答案:

答案 0 :(得分:2)

消息跟踪在两个主要方面不同于典型的RPC跟踪。由于它与众不同,因此与RPC相比并不是找出未来道路的最佳方法。我会在这里简要介绍几件事,这些事大部分是在我对此主题所做的slide deck中。

  1. 在消息传递中,使用者和消息处理器之间通常没有传递线程上下文。这与RPC不同,在RPC中,通常至少在请求侧存在切换。
  2. 当我们拥有线程上下文时,应该使用它来建立父级信息(在Rabbit处理中就是这种情况)。但是,通常并非如此。因此,我们通常在不知道消息传递处理抽象的情况下,对消息的标头重新序列化。

在您的示例中,您谈论的是spring-rabbit,它在处理块期间正在使用线程上下文来适当地设置“当前范围”。由于我们不想将基于线程的上下文与消息中的内容混淆,因此我们清除了标头。

“重试”案确实对此提出了质疑。在这种情况下,父母应该是什么?如何知道?有问题的检测工具的问题之一是,我们实际上看不到消耗消息的代码。

具体而言,不存在Rabbitmq民意测验工具,因此我们将“虚假消费者跨度”追溯到此。如果消息被重播,则第二个消费者跨度可能是有效的。坦白地说,我们没有考虑这一点。

无论如何,我的观点是,我们不应过多关注消息跟踪与RPC之间的差异,因为那里会有一些故意的差异。让我们专注于差距本身,并可能将其放在令人讨厌的地方,这会导致我认为是github问题。

无论如何,我希望上下文能够回答您的问题,即使它不会改变代码当前正在执行的操作的事实。

答案 1 :(得分:0)

@Andrain感谢您的回答和支持,它真的很有帮助。

作为解决方法,我们需要将重试拦截器向下移动。

@Bean
@Order
BeanPostProcessor reorderingSimpleRabbitListenerContainerFactory() {
    return new BeanPostProcessor() {
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

            if (SimpleRabbitListenerContainerFactory.class.isAssignableFrom(bean.getClass())) {

                final Class<RetryOperationsInterceptor> retryInterceptor = RetryOperationsInterceptor.class;
                Advice[] adviceChain = ((SimpleRabbitListenerContainerFactory) bean).getAdviceChain();
                Arrays.sort(adviceChain, (o1, o2) -> {
                    if (o1.getClass().isAssignableFrom(retryInterceptor)) {
                        return 1;
                    }
                    if (o2.getClass().isAssignableFrom(retryInterceptor)) {
                        return -1;
                    }
                    return 0; // it is stable sort, so no worry
                });
            }
            return bean;
        }
    };
}