簡體   English   中英

在使用帶有新關鍵字的 resttemplate 進行 API 調用時,無法將 Sleuth traceid 和 spanid 傳遞給下游服務

[英]Not able to pass Sleuth traceid and spanid to downstream services while making API calls using resttemplate with new keyword

目前,我正在將 Sleuth 集成到我們現有的微服務中以增強日志記錄機制。 MS 使用 Spring Boot 2.5.6 和 Spring Cloud 2020.0.6 構建(已解決為 Spring Cloud Sleuth 3.0)。

我試圖解決的挑戰是在進行出站 API 調用時,我們使用 new() 關鍵字創建 RestTemplate,而不是將 RestTemplate 作為 Bean 管理。 不幸的是,我們無權更改使用 resttemplate 作為 Bean 的方法,以使 Sleuth 和 Brave 工具無縫工作(以避免在應用程序中引入任何重大更改)以將 traceid 傳播到下游日志(如前所述在官方文檔中)。 因此,MS1 和 MS2 日志中的 traceid 不同,這使得跟蹤變得困難。

正如我從官方文檔中了解到的那樣,Brave 將攔截器注冊為喜歡 LazyTraceClientHttpRequestInterceptor 和 TracingClientHttpRequestInterceptor 以將 X-B3-Traceid、X-B3-SpanId 等標頭添加到出站請求中,我嘗試做類似的事情。

這是我的自定義攔截器的代碼:

import java.io.IOException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
 
@Component
public class RequestResponseLoggingInterceptor implements ClientHttpRequestInterceptor {
    
    private final Logger log = LoggerFactory.getLogger(this.getClass());
    
    private Tracer tracer;
    
    RequestResponseLoggingInterceptor(Tracer tracer){
        this.tracer = tracer;
    }
  
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException 
    {
        Span span = tracer.currentSpan();
        
        HttpHeaders headers = new HttpHeaders();
        headers.set("X-B3-Traceid", span.context().traceId());
        headers.set("X-B3-SpanId", span.context().spanId());
        headers.set("X-B3-ParentSpanId", span.context().parentId());
        request.getHeaders().addAll(headers);
        
        ClientHttpResponse response = execution.execute(request, body);
        return response;
    }
}

在我的 controller class 中,我已經自動連接了這個攔截器:

@Autowired
private RequestResponseLoggingInterceptor interceptor;

並使用此攔截器進行 resttemplate 調用,如下所示:

RestTemplate restTemplate = new RestTemplate();
        restTemplate.setInterceptors(Collections.singletonList(interceptor));
        ResponseEntity<ProductSale> responseEntity = restTemplate.getForEntity(
                "http://localhost:8000/product-service/pname/{pname}/cost/{cost}/qty/{qty}", ProductSale.class,
                uriVariables);
        ProductSale sales = responseEntity.getBody();

當我比較這個 API 調用的 MS1 和 MS2 日志時,traceid 是不同的。

  • 據我了解,MS2 應該尋找 X-B3 字段來生成
    日志的 traceid,但它沒有使用請求 header 中發送的 traceid。
  • 而且,在通常的設置中,MS2 的跨度應該已經注入到 MS1 內的標頭中
    撥打電話。 但是當我在攔截器中調試和檢查 Trace id 和 SpanId 時,它們是相同的。

誰能幫我我在這里做錯了什么? 以及如何通過使用 New() 關鍵字創建 RestTemplate 來實現向下游服務的 traceid 傳播。

我和 Sleuth 合作的不多,但我對每次創建一個新的 RestTemplate 都有很大的懷疑。

嘗試使用 singleton scope 將其定義為 bean,然后自動裝配 RestTemplate。

您需要將TracingClientHttpRequestInterceptor bean 注入到您的 rest 模板中,它將負責傳遞跟蹤上下文。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM