链路追踪:指的是一次任务的开始到结束,期间调用的所有系统以及耗时(时间跨度)都可以完整记录下来。
1、引入客户端FeignBlockingLoadBalancerClient
由自动装配类FeignLoadBalancerAutoConfiguration
引入实现客户端一侧负载均衡的类FeignBlockingLoadBalancerClient
。
2、引入子容器工厂类TraceFeignContext
sleuth引入FeignContextBeanPostProcessor:
public class FeignContextBeanPostProcessor implements BeanPostProcessor {
private final BeanFactory beanFactory;
public FeignContextBeanPostProcessor(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof FeignContext && !(bean instanceof TraceFeignContext)) {
FeignContext feignContext = (FeignContext) bean;
TraceFeignContext traceFeignContext = new TraceFeignContext(traceFeignObjectWrapper(), feignContext);
traceFeignContext.setApplicationContext(feignContext.getParent());
return traceFeignContext;
}
return bean;
}
private TraceFeignObjectWrapper traceFeignObjectWrapper() {
return new TraceFeignObjectWrapper(this.beanFactory);
}
}
与Feign ~ FeignContext 相对应,sleuth引入FeignContext的子类TraceFeignContext。在初始化FeignContext过程中被子类TraceFeignContext取代。
3、引入sleuth提供的客户端client之TraceFeignBlockingLoadBalancerClient
class TraceFeignContext extends FeignContext {
private final TraceFeignObjectWrapper traceFeignObjectWrapper;
//delegate 就是Feign提供的FeignContext
private final FeignContext delegate;
@Override
@SuppressWarnings("unchecked")
public <T> T getInstance(String name, Class<T> type) {
//通过子容器FeignContext创建客户端client,最终得到FeignBlockingLoadBalancerClient的代理
T object = this.delegate.getInstance(name, type);
if (object != null) {
return (T) this.traceFeignObjectWrapper.wrap(object);
}
return null;
}
...
}
final class TraceFeignObjectWrapper {
Object wrap(Object bean) {
if (bean instanceof Client && !(bean instanceof TracingFeignClient)
&& !(bean instanceof LazyTracingFeignClient)) {
if (loadBalancerPresent && bean instanceof FeignBlockingLoadBalancerClient
&& !(bean instanceof TraceFeignBlockingLoadBalancerClient)) {
return instrumentedFeignLoadBalancerClient(bean);
}
...
}
return this.traceFeignBuilderBeanPostProcessor.postProcessAfterInitialization(bean, null);
}
private Object instrumentedFeignLoadBalancerClient(Object bean) {
if (AopUtils.getTargetClass(bean).equals(FeignBlockingLoadBalancerClient.class)) {
FeignBlockingLoadBalancerClient client = ProxyUtils.getTargetObject(bean);
return new TraceFeignBlockingLoadBalancerClient(
(Client) new TraceFeignObjectWrapper(this.beanFactory).wrap(client.getDelegate()),
(LoadBalancerClient) loadBalancerClient(), loadBalancerClientsProperties(),
(LoadBalancerClientFactory) loadBalancerClientFactory(), this.beanFactory);
}else {
...
}
}
}
OtelHttpClientHandler、OtelHttpServerHandler
TracingFilter