传播correlation-id无法正常工作

时间:2017-07-28 17:53:48

标签: spring spring-cloud

我遇到的问题是,相关id不会从我的第一个传播到我的第二个微服务。我开始实现servlet过滤器,上下文和上下文持有者,如下所示:

@Component
// Do not name bean "RequestContextFilter", otherwise filter will not work!
public class CallContextFilter implements Filter {

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
        throws IOException, ServletException {

    HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;CallContextHolder.getContext().setCorrelationId(httpServletRequest.getHeader(CallContext.CORRELATION_ID));

  filterChain.doFilter(httpServletRequest, servletResponse);
}

@Override
public void init(FilterConfig filterConfig) throws ServletException {
}

@Override
public void destroy() {
}
}
@Component
@Getter
@Setter
public class CallContext {
   public static final String CORRELATION_ID = "correlation-id";

   private String correlationId = new String();
}
 public class CallContextHolder {

private static final ThreadLocal<CallContext> userContext = new ThreadLocal<>();

public static final CallContext getContext() {
    CallContext context = userContext.get();

    if (context == null) {
        context = new CallContext();
        userContext.set(context);
    }
    return userContext.get();
}

}

然后,我按如下方式实现了RestTemplate bean:

@Bean
public RestTemplate getRestTemplate() {
    RestTemplate template = new RestTemplate();
    List<ClientHttpRequestInterceptor> interceptors = template.getInterceptors();
    interceptors.add(new CallContextInterceptor());
    return template;
}

并且拦截器如下所示:

public class CallContextInterceptor implements ClientHttpRequestInterceptor {

@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
    HttpHeaders headers = request.getHeaders();
    headers.add(CallContext.CORRELATION_ID, CallContextHolder.getContext().getCorrelationId());

    return execution.execute(request, body);
}
}

当我调用我的端点时,执行servlet过滤器并将correlation-id存储在CallContextHolder中。到现在为止还挺好。但是,CallContextInterceptor似乎在另一个线程中调用,而CallContextHolder中的ThreadLocal变量为null。我需要做些什么来使这个工作?

@GetMapping("/ping")
public String ping() {
    return pongRestTemplateClient.getPong();
}

2 个答案:

答案 0 :(得分:0)

为什么不使用Spring Cloud Sleuth并让libary为你工作呢? http://cloud.spring.io/spring-cloud-sleuth/spring-cloud-sleuth.html

答案 1 :(得分:0)

问题在于我正在使用Hysterix。 Hystrix产生一个新线程来执行代码,完全不知道“外部”线程上下文。因此,在使用Hysterix命令时,执行线程将失去对ThreadLocal相关功能的访问权限。

我在这里找到了问题的答案:https://github.com/jmnarloch/hystrix-context-spring-boot-starter