在instrumentation-spring-rabbit
模块中,勇敢地提取和删除标头,为什么?
我探索了其他工具(Point
,center
,spring-web
,httpclient
等),勇敢地从不删除包含跟踪键/扩展名的标头原始消息。
删除标头有一个副作用,即重试 interceptor -already added by spring-rabbit-第二次尝试处理消息,但是因为okhttp3
已删除标头在第一次重试中,因此在以后的重试中将找不到它。
答案 0 :(得分:2)
消息跟踪在两个主要方面不同于典型的RPC跟踪。由于它与众不同,因此与RPC相比并不是找出未来道路的最佳方法。我会在这里简要介绍几件事,这些事大部分是在我对此主题所做的slide deck中。
在您的示例中,您谈论的是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;
}
};
}