即使积压也传播状态

propagating state even when backlogged

在 Brave (zipkin tracer) 中,我们通过控制 Dispatcher 的 ExecutorService 附加拦截器读取的状态。

它是这样工作的..

这适用于同步请求(因为它们根本不使用调度程序线程)和正常的异步请求。

当正在进行的连接数超过允许数量时,它不起作用,因为异步请求在执行之前被推入就绪队列。就绪队列未被请求的调用线程处理,因此重新附加将不起作用。当拦截器在延迟请求上运行时,它无法看到中断跟踪的调用跨度。

我在想也许应用程序拦截器可能没有这个问题。如果 host/connection 限制在网络级别强制执行(通过上述队列),我将能够通过双注册拦截器来协调状态。该拦截器可以通过映射 application/network 级请求重新附加状态,而不依赖于线程本地。

遗憾的是,这不起作用,因为 host/connection 限制是在应用程序级别强制执行的(通过提到的队列),所以我很困惑。

我希望能够跟踪请求,尤其是当它们积压时。有什么想法吗?

感谢 brianm 发现了这个问题,顺便说一句

我们有一个内部 OkHttpClient 包装器实现 Call.Factory 它添加了一个初始拦截器:

public class HttpClient implements Call.Factory {

private final OkHttpClient ok;

HttpClient(final OkHttpClient ok) {
    this.ok = ok;
}

/**
 * Implements Call.Factory, uses implicit (thread local) Ctx
 */
public Call newCall(final Request request) {
    return newCall(Ctx.fromThread().orElseGet(Ctx::empty), request);
}


public Call newCall(Ctx ctx, final Request request) {
    OkHttpClient.Builder b = this.ok.newBuilder();
    b.interceptors().add(0, new CtxInterceptor(ctx));
    return b.build().newCall(request);
}

解决这个问题。然而,它不是透明的,因此可能对 Brave 不利。它工作正常,因为实际上一旦配置了客户端,您实际上只使用 Call.Factory 接口 :-)

Ctx 位只是我们想要传播的内容的上下文,我们可以隐式或显式地进行,因此需要额外的方法来显式获取它。