我想問一些類似的問題conversationId,可以在一個 API 呼叫中在許多請求/回應之間共享。例如,我們有/test端點,這個端點呼叫另一個服務,然后另一個并根據獲得的結果回傳回應。它看起來像:
Conversation:
1) Sending test request.
2) API calls /info endpoint.
3) Returns /info response.
4) API calls /example endpoint.
5) Returns /example response.
6) Returns /test response.
當我們/test同時呼叫 API 4-5 次時,日志可能會很混亂,我們不知道如何組合各個呼叫。
我想用任何隨機請求范圍 ID 標記它,比如高值數字。它可能看起來像:
1) Sending test request of ID 12345.
2) Sending test request of ID 98765.
3) API calls /info endpoint of ID 12345.
4) Returns /info response of ID 12345.
5) API calls /info endpoint of ID 98765.
6) API calls /example endpoint of ID 12345.
7) Returns /info response of ID 98765.
and so on
是否有任何 Spring 機制可以在不重新創建這些 bean 的情況下以請求方式ClientHttpRequestInterceptor共享資料?GenericFilterBean就像具有生命周期的自定義范圍 bean 一樣從doFilter那里開始并結束。
uj5u.com熱心網友回復:
您可以將MDC與OncePerRequestFilter一起用于此類要求。:
@Component
public class MDCFilter implements OncePerRequestFilter{
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
MDC.put("request_ID", someNumberGeneratorUtility());
try {
filterChain.doFilter(request, response);
} finally {
MDC.remove("request_ID");
}
}
}
uj5u.com熱心網友回復:
1.使用Sleuth (限制——Spring Cloud Sleuth是基于Spring Boot的)
Spring sleuth 可以提供跟蹤 ID 和跨度 ID。使用跟蹤 ID,您可以組合單個呼叫。
下面的示例可能對某人有用。
添加彈簧偵探
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
你的 /test
@GetMapping("/test")
public String test() {
LOG.info("Sending test request.");
LOG.info("API calls /info endpoint.");
// Calling /info service or endpoint
LOG.info("Returns /info response.");
LOG.info("API calls /example endpoint.");
// Calling /example service or endpoint
LOG.info("Returns /example response.");
LOG.info("Returns /test response");
return "test";
}
同時呼叫/test API 5次,服務器呼叫日志如下圖
2022-04-28 00:40:11.108 INFO [test,be0b352e1f8664d1,be0b352e1f8664d1] 10766 --- [nio-9091-exec-5] c.k.d.d.a.AccountServiceApplication : Sending test request.
2022-04-28 00:40:11.109 INFO [test,29c2e863354fca33,29c2e863354fca33] 10766 --- [nio-9091-exec-1] c.k.d.d.a.AccountServiceApplication : Sending test request.
2022-04-28 00:40:11.115 INFO [test,29c2e863354fca33,29c2e863354fca33] 10766 --- [nio-9091-exec-1] c.k.d.d.a.AccountServiceApplication : API calls /info endpoint.
2022-04-28 00:40:11.115 INFO [test,29c2e863354fca33,29c2e863354fca33] 10766 --- [nio-9091-exec-1] c.k.d.d.a.AccountServiceApplication : Returns /info response.
2022-04-28 00:40:11.115 INFO [test,29c2e863354fca33,29c2e863354fca33] 10766 --- [nio-9091-exec-1] c.k.d.d.a.AccountServiceApplication : API calls /example endpoint.
2022-04-28 00:40:11.115 INFO [test,29c2e863354fca33,29c2e863354fca33] 10766 --- [nio-9091-exec-1] c.k.d.d.a.AccountServiceApplication : Returns /example response.
2022-04-28 00:40:11.115 INFO [test,29c2e863354fca33,29c2e863354fca33] 10766 --- [nio-9091-exec-1] c.k.d.d.a.AccountServiceApplication : Returns /test response
2022-04-28 00:40:11.115 INFO [test,be0b352e1f8664d1,be0b352e1f8664d1] 10766 --- [nio-9091-exec-5] c.k.d.d.a.AccountServiceApplication : API calls /info endpoint.
2022-04-28 00:40:11.116 INFO [test,be0b352e1f8664d1,be0b352e1f8664d1] 10766 --- [nio-9091-exec-5] c.k.d.d.a.AccountServiceApplication : Returns /info response.
2022-04-28 00:40:11.116 INFO [test,be0b352e1f8664d1,be0b352e1f8664d1] 10766 --- [nio-9091-exec-5] c.k.d.d.a.AccountServiceApplication : API calls /example endpoint.
2022-04-28 00:40:11.116 INFO [test,be0b352e1f8664d1,be0b352e1f8664d1] 10766 --- [nio-9091-exec-5] c.k.d.d.a.AccountServiceApplication : Returns /example response.
2022-04-28 00:40:11.116 INFO [test,be0b352e1f8664d1,be0b352e1f8664d1] 10766 --- [nio-9091-exec-5] c.k.d.d.a.AccountServiceApplication : Returns /test response
2022-04-28 00:40:11.109 INFO [test,b26d689f73b974b7,b26d689f73b974b7] 10766 --- [nio-9091-exec-4] c.k.d.d.a.AccountServiceApplication : Sending test request.
2022-04-28 00:40:11.116 INFO [test,b26d689f73b974b7,b26d689f73b974b7] 10766 --- [nio-9091-exec-4] c.k.d.d.a.AccountServiceApplication : API calls /info endpoint.
2022-04-28 00:40:11.116 INFO [test,b26d689f73b974b7,b26d689f73b974b7] 10766 --- [nio-9091-exec-4] c.k.d.d.a.AccountServiceApplication : Returns /info response.
2022-04-28 00:40:11.116 INFO [test,b26d689f73b974b7,b26d689f73b974b7] 10766 --- [nio-9091-exec-4] c.k.d.d.a.AccountServiceApplication : API calls /example endpoint.
2022-04-28 00:40:11.116 INFO [test,b26d689f73b974b7,b26d689f73b974b7] 10766 --- [nio-9091-exec-4] c.k.d.d.a.AccountServiceApplication : Returns /example response.
2022-04-28 00:40:11.116 INFO [test,b26d689f73b974b7,b26d689f73b974b7] 10766 --- [nio-9091-exec-4] c.k.d.d.a.AccountServiceApplication : Returns /test response
2022-04-28 00:40:11.109 INFO [test,4f28a79ecc2ce6da,4f28a79ecc2ce6da] 10766 --- [nio-9091-exec-2] c.k.d.d.a.AccountServiceApplication : Sending test request.
2022-04-28 00:40:11.109 INFO [test,ee7bfa89b05b69ad,ee7bfa89b05b69ad] 10766 --- [nio-9091-exec-3] c.k.d.d.a.AccountServiceApplication : Sending test request.
etc....
請注意,應用程式名稱位于開頭的括號內。這些括號是由 Sleuth 添加的。它們代表應用程式名稱、跟蹤 ID 和跨度 ID。
此外,您可以通過編程方式獲取當前跟蹤。
@Autowired
private Tracer tracer;
@GetMapping("/test")
public String account() {
LOG.info("Sending test request, " "trace ID=" tracer.currentSpan().context().traceId().toString());
LOG.info("API calls /info endpoint, " "trace ID=" tracer.currentSpan().context().traceId().toString());
// Calling /info service or endpoint
LOG.info("Returns /info response, " "trace ID=" tracer.currentSpan().context().traceId().toString());
LOG.info("API calls /example endpoint, " "trace ID="
tracer.currentSpan().context().traceId().toString());
// Calling /example service or endpoint
LOG.info("Returns /example response, " "trace ID=" tracer.currentSpan().context().traceId().toString());
LOG.info("Returns /test response, " "trace ID=" tracer.currentSpan().context().traceId().toString());
return "test";
}
日志
....Sending test request, trace ID=51322ee614962951
.... API calls /info endpoint, trace ID=51322ee614962951
.... Sending test request, trace ID=4bc5017e2beceaf8
.... Sending test request, trace ID=75b638bda78a7bb5
.... Returns /info response, trace ID=51322ee614962951
.... API calls /info endpoint, trace ID=4bc5017e2beceaf8
.... API calls /example endpoint, trace ID=51322ee614962951
.... Sending test request, trace ID=f20cde67b4376777
etc....
2.可以使用執行緒背景關系映射
@GetMapping("/test")
public String test() {
ThreadContext.put("id", UUID.randomUUID().toString());
LOG.info("Sending test request, " ThreadContext.get("id"));
LOG.info("API calls /info endpoint, " ThreadContext.get("id"));
// Calling /info service or endpoint
LOG.info("Returns /info response, " ThreadContext.get("id"));
LOG.info("API calls /example endpoint, " ThreadContext.get("id"));
// Calling /example service or endpoint
LOG.info("Returns /example response, " ThreadContext.get("id"));
LOG.info("Returns /test response, " ThreadContext.get("id"));
return "test";
}
uj5u.com熱心網友回復:
我創建了RequestContextbean 作為我的請求資料的持有者,例如conversationId:
@Component
@RequestScope
public class RequestContext {
private final String conversationId;
public RequestContext() {
conversationId = UUID.randomUUID().toString();
}
public String getConversationId() {
return conversationId;
}
}
然后,將其注入我的過濾器:
@Component
public class LoggingFilter extends GenericFilterBean {
private final RequestContext requestContext;
public RestServerLoggingFilter(RequestContext requestContext) {
this.requestContext = requestContext;
}
...
}
但最重要的是配置和順序:
@Configuration
public class RestServerConfiguration {
private static final int LOGGING_FILTER_ORDER = -104;
@Bean
public FilterRegistrationBean<RestServerLoggingFilter> initFilter(LoggingFilter filter) {
FilterRegistrationBean<RestServerLoggingFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(filter);
registrationBean.setDispatcherTypes(
EnumSet.complementOf(EnumSet.of(DispatcherType.ERROR))
);
registrationBean.setOrder(LOGGING_FILTER_ORDER);
return registrationBean;
}
}
過濾器被堆疊到ApplicationFilterChain類下的串列中。當我們瀏覽這個堆疊時,我們得到了一個OrderedRequestContextFilterbean,它的-105initRequestScope定義了它的屬性initContextHolders。了解這一點非常重要。然后您可以將請求的范圍 bean 注入到任何過濾器中,即OrderedRequestContextFilter在鏈中之后。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/467295.html
