2017-07-28 27 views
0

我有問題,相關性ID不會從我的第一個傳播到我的第二個微服務。我開始實施一個Servlet過濾器,上下文和語境持有人如下:傳播相關性ID不起作用

@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 
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過濾器並將相關標識存儲在CallContextHolder中。到現在爲止還挺好。但是,CallContextInterceptor似乎在其他線程中調用,並且CallContextHolder中的我的ThreadLocal變量爲null。我需要做些什麼才能做到這一點?

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

回答

0

問題是我正在使用Hysterix。 Hystrix產生一個新的線程來執行代碼,完全不知道「外部」線程上下文。因此,執行線程在使用Hysterix命令時會失去對ThreadLocal相關功能的訪問權限。

我在這裏找到了我的問題的答案:https://github.com/jmnarloch/hystrix-context-spring-boot-starter

+0

偵探樂器Hystrix也。基本上覆制我們在那裏做了什麼,因爲我明白你正在重做同樣的工作 –

+0

我將在未來幾天嘗試一下Sleuth,謝謝! –