Spring 云侦探与 Webservicetemplate
Spring cloud sleuth with Webservicetemplate
Spring cloud sleuth 是否支持 WebserviceTemplate?我的意思是 - 我有一项服务可以调用 2 个服务 - 一个使用 RestTemplate,另一个使用 Webservicetemplate。 Rest 调用正在 Zipkin 中显示,而使用 Webservicetemplate 的 Soap 调用则没有。我是否必须将 @NewSpan 添加到我的所有 soap 调用中?不是像Resttemplate那样自动完成吗?
否 - 我们尚未添加任何有关 Webservicetemplate 的工具。您必须添加一个类似于我们为 RestTemplate 添加的拦截器。您必须将所有跟踪 headers 传递给请求,以便另一方可以正确解析它。
这里是如何使用 spring 云侦探与 Webservicetemplate 的示例,
如果服务A向服务B发送请求,
首先,您将通过以下代码
在已发送请求的header中发送跟踪ID
@Service
public class WebServiceMessageCallbackImpl implements WebServiceMessageCallback {
@Autowired
private Tracer tracer;
public void doWithMessage(WebServiceMessage webServiceMessage) throws TransformerException {
Span span = tracer.currentSpan();
String traceId = span.context().traceId();
SoapMessage soapMessage = (SoapMessage) webServiceMessage;
SoapHeader header = soapMessage.getSoapHeader();
StringSource headerSource = new StringSource("<traceId>" + traceId + "</traceId>");
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(headerSource, header.getResult());
}
}
然后在服务 B 中,您将创建一个拦截器,然后从即将到来的请求的 header 中读取跟踪 ID,然后将此跟踪 ID 放入 MDC 中,如下面的代码
@Slf4j
@Component
public class HttpInterceptor2 extends OncePerRequestFilter {
private final String traceId = "traceId";
@Autowired
private Tracer tracer;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String payload = new String(request.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
String traceId = traceId(payload);
MDC.put("traceId", traceId);
try {
chain.doFilter(request, response);
} finally {
MDC.remove(traceId);
}
}
private String traceId(String payload) {
StringBuilder token = new StringBuilder();
if (payload.contains(traceId)) {
int index = payload.indexOf(traceId);
while (index < payload.length() && payload.charAt(index) != '>') {
index++;
}
index++;
for (int i = index; ; i++) {
if (payload.charAt(i) == '<') {
break;
}
token.append(payload.charAt(i));
}
}
if (token.toString().trim().isEmpty()) {
token.append(traceId());
}
return token.toString().trim();
}
private String traceId() {
Span span = tracer.currentSpan();
String traceId = span.context().traceId();
return traceId;
}
}
Spring cloud sleuth 是否支持 WebserviceTemplate?我的意思是 - 我有一项服务可以调用 2 个服务 - 一个使用 RestTemplate,另一个使用 Webservicetemplate。 Rest 调用正在 Zipkin 中显示,而使用 Webservicetemplate 的 Soap 调用则没有。我是否必须将 @NewSpan 添加到我的所有 soap 调用中?不是像Resttemplate那样自动完成吗?
否 - 我们尚未添加任何有关 Webservicetemplate 的工具。您必须添加一个类似于我们为 RestTemplate 添加的拦截器。您必须将所有跟踪 headers 传递给请求,以便另一方可以正确解析它。
这里是如何使用 spring 云侦探与 Webservicetemplate 的示例,
如果服务A向服务B发送请求,
首先,您将通过以下代码
在已发送请求的header中发送跟踪ID@Service
public class WebServiceMessageCallbackImpl implements WebServiceMessageCallback {
@Autowired
private Tracer tracer;
public void doWithMessage(WebServiceMessage webServiceMessage) throws TransformerException {
Span span = tracer.currentSpan();
String traceId = span.context().traceId();
SoapMessage soapMessage = (SoapMessage) webServiceMessage;
SoapHeader header = soapMessage.getSoapHeader();
StringSource headerSource = new StringSource("<traceId>" + traceId + "</traceId>");
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(headerSource, header.getResult());
}
}
然后在服务 B 中,您将创建一个拦截器,然后从即将到来的请求的 header 中读取跟踪 ID,然后将此跟踪 ID 放入 MDC 中,如下面的代码
@Slf4j
@Component
public class HttpInterceptor2 extends OncePerRequestFilter {
private final String traceId = "traceId";
@Autowired
private Tracer tracer;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String payload = new String(request.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
String traceId = traceId(payload);
MDC.put("traceId", traceId);
try {
chain.doFilter(request, response);
} finally {
MDC.remove(traceId);
}
}
private String traceId(String payload) {
StringBuilder token = new StringBuilder();
if (payload.contains(traceId)) {
int index = payload.indexOf(traceId);
while (index < payload.length() && payload.charAt(index) != '>') {
index++;
}
index++;
for (int i = index; ; i++) {
if (payload.charAt(i) == '<') {
break;
}
token.append(payload.charAt(i));
}
}
if (token.toString().trim().isEmpty()) {
token.append(traceId());
}
return token.toString().trim();
}
private String traceId() {
Span span = tracer.currentSpan();
String traceId = span.context().traceId();
return traceId;
}
}