Java 在SpringRabbit中,为什么brave会删除消息的标题?

Java 在SpringRabbit中,为什么brave会删除消息的标题?,java,spring,rabbitmq,spring-rabbit,zipkin,Java,Spring,Rabbitmq,Spring Rabbit,Zipkin,在模块中,brave正在提取和删除标题,为什么 我研究了其他工具(SpringWeb,httpclient,okhttp3,grpc,以及其他工具),但从不从原始消息中删除包含跟踪键/附加项的标题 删除标头会产生副作用,重试拦截器将尝试第二次处理消息,但这是因为brave在第一次重试时删除了标头,因此在随后的重试中找不到该标头。消息传递跟踪与典型的RPC跟踪在两个主要方面不同。因为它是不同的,与RPC相比并不是找到前进道路的最佳方式。我将在这里简要地提到这两件事,它们主要是在我就这个主题所做的讨

在模块中,brave正在提取和删除标题,为什么

我研究了其他工具(
SpringWeb
httpclient
okhttp3
grpc
,以及其他工具),但从不从原始消息中删除包含跟踪键/附加项的标题


删除标头会产生副作用,重试拦截器将尝试第二次处理消息,但这是因为
brave
在第一次重试时删除了标头,因此在随后的重试中找不到该标头。

消息传递跟踪与典型的RPC跟踪在两个主要方面不同。因为它是不同的,与RPC相比并不是找到前进道路的最佳方式。我将在这里简要地提到这两件事,它们主要是在我就这个主题所做的讨论中

  • 在消息传递中,使用者和消息处理器之间通常不传递线程上下文。这与RPC不同,RPC通常至少在请求端有一个切换
  • 当我们有一个线程上下文时,我们应该使用它来建立父信息(兔子处理就是这种情况)。然而,情况往往并非如此。因此,当我们不知道消息处理抽象时,我们通常会重新序列化消息头
  • 在您的示例中,您讨论的是SpringRabbit,它在处理块期间使用线程上下文适当地设置“当前范围”。因为我们不想混淆基于线程的上下文和消息中的内容,所以我们清除了标题

    “重试”一案确实使这一点受到质疑。在这种情况下,父母应该是什么,如何知道?所讨论的工具的一个问题是,我们实际上看不到消耗消息的代码

    具体地说,rabbitmq轮询工具并不存在,因此我们引入了一个“假消费者跨度”来追溯解释这一点。如果消息被重新播放。。也许第二个消费者跨度是有效的。坦白地说,我们没有考虑这个问题。 无论如何,我的观点是,我们不应该过分关注消息跟踪和RPC之间的区别,因为这两者之间会有一些有意的区别。让我们把重点放在gap本身上,也许在gitter上这样做会导致github问题


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

    @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;
            }
        };
    }
    
    @Bean
    @命令
    BeanPostProcessor重新排序SimpleRableBitListenerContainerFactory(){
    返回新的BeanPostProcessor(){
    @凌驾
    公共对象后处理初始化后(对象bean、字符串beanName)抛出BeansException{
    if(SimpleRableBitListenerContainerFactory.class.isAssignableFrom(bean.getClass())){
    最终类retryInterceptor=RetryOperationsInterceptor.Class;
    Advice[]adviceChain=((SimpleRableBitListenerContainerFactory)bean);
    数组.排序(adviceChain,(o1,o2)->{
    if(o1.getClass().isAssignableFrom(retryInterceptor)){
    返回1;
    }
    if(o2.getClass().isAssignableFrom(retryInterceptor)){
    返回-1;
    }
    返回0;//这是稳定排序,所以不用担心
    });
    }
    返回豆;
    }
    };
    }