即使在积压时也传播状态

时间:2016-12-08 13:30:42

标签: okhttp okhttp3

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

就像这样......

  • 将跨度附加到本地线程
  • 包装一个执行者服务,它将调用线程的span重新附加到runnable
  • 让调度员使用该执行者服务

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

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

我在想,也许应用程序拦截器可能没有这个问题。如果在网络级强制执行主机/连接限制(通过提到的队列),我将能够通过双重注册拦截器来协调状态。这个拦截器可以通过映射应用程序/网络级请求来重新连接状态,而不依赖于线程本地。

可悲的是,这不起作用,因为在应用程序级别强制执行主机/连接限制(通过提到的队列),所以我很难过。

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

向brianm致敬,发现这个问题,btw

1 个答案:

答案 0 :(得分:3)

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

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);
}

解决这个问题。然而,它并不透明,因此可能不适合勇敢。它工作正常,因为在实践中,一旦配置了客户端,您只能真正使用Call.Factory接口: - )

Ctx位只是我们想要传播的东西的上下文,我们可以隐式或显式执行,因此需要额外的方法来明确地使用它。