多服務部署的時候,各個服務通過httpClient進行調用時候,有時候出現問題,需要進行追查。但是如果沒有一個標記,就會很迷茫,特別是多個服務來回調用,就無法快速定位問題。這個時候一般是使用MDC的 traceId來追蹤。但是由於每個服務的traceId不同,在使用elk進行查詢的時候,仍然不能快速定位。於是,決定統一traceId以方便快速定位。
原理:
發起請求經過Nginx的時候,第一次請求時 nginx 會生成X-Request-Id。 服務里面的攔截器會攔截獲取,如果request的header頭里面帶有該X-Request-Id,則會直接讀取,如果沒有,會重新生成. 在使用mp-util的 MpHttpclient 時候,會將該值放到header頭信息里面,以便在請求下個服務時候可以直接獲取。從而從上游到下游統一traceId。
具體使用就是:封裝http包的header部分,在每個調用方法的header里面添加traceId給下游。每個服務自己定義攔截器,在攔截器里面進行攔截。如果含有traceId就進行輸入到日志里面,如果沒有,則創建。攔截器
public class InitRequestAuthDataFilter extends OncePerRequestFilter { // log 追蹤ID private final static String TRACE_KEY = "X-Request-Id"; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException { //一、當前登錄用戶(用於日志輸出) SSOLoginUser loginUser = WebSessionUtil.getCurrentLoginUser(); if(loginUser==null) { MDC.put("loginUser", "【游客身份】"); }else { MDC.put("loginUser", "【"+ loginUser.getId() +"-"+ loginUser.getName() +"-"+ loginUser.getLoginName()+"】"); } //二、用於頁面渲染 request.setAttribute("currentLoginUser", loginUser ); //先從param里取,沒有的話從header里取,還沒有的話再創建 String reqId = request.getParameter("X-Request-Id"); if(reqId==null || "".equals(reqId.trim()) ) { reqId = request.getHeader("X-Request-Id"); } if(reqId==null || "".equals(reqId.trim()) ) { reqId = UUID.randomUUID().toString().replace("-", ""); } MDC.put(TRACE_KEY, reqId); //該traceId是讓日志打印出來的key值 MDC.put("traceId",reqId); /**防止MDC 多次生成,引入的sq-component-log 有攔截 header 頭信息**/ logger.info("header:" + request.getHeader("X-Request-Id")); filterChain.doFilter(request, response); MDC.remove(TRACE_KEY); } }
之后再日子里面進行驗證
沒問題后,再通過elk進行查詢時候就方便多了: