我遇到的问题是,相关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();
}
答案 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