工程名 | 端口 | 做用 |
---|---|---|
cat-ui | 8082 | 調用入口服務 |
cat-business-consumer | 8083 | 業務消費服務 |
cat-order-service | 8084 | 訂單服務 |
cat-storage-service | 8085 | 庫存服務 |
上圖是本節實例的埋點圖,首先 cat-ui 的入口 和 調用點 加入cat埋點,cat-business-consumer的入口和調用點加入埋點,cat-order-service 和 cat-storage-service 再也不調用其餘微服務,因此只在入口加入埋點。經過這樣的埋點,能夠組成一條完整的調用鏈。java
/** * Cat.context接口實現類,用於context調用鏈傳遞,相關方法Cat.logRemoteCall()和Cat.logRemoteServer() */ public class CatContextImpl implements Cat.Context { private Map<String, String> properties = new HashMap<>(16); @Override public void addProperty(String key, String value) { properties.put(key, value); } @Override public String getProperty(String key) { return properties.get(key); } }
/** * 添加header常量,用於http協議傳輸rootId、parentId、childId三個context屬性 */ public class CatHttpConstants { /** * http header 常量 */ public static final String CAT_HTTP_HEADER_ROOT_MESSAGE_ID = "X-CAT-ROOT-MESSAGE-ID"; public static final String CAT_HTTP_HEADER_PARENT_MESSAGE_ID = "X-CAT-ROOT-PARENT-ID"; public static final String CAT_HTTP_HEADER_CHILD_MESSAGE_ID = "X-CAT-ROOT-CHILD-ID"; }
/** * http協議傳輸,遠程調用鏈目標端接收context的filter, * 經過header接收rootId、parentId、childId並放入CatContextImpl中,調用Cat.logRemoteCallServer()進行調用鏈關聯 * 注:若不涉及調用鏈,則直接使用cat-client.jar中提供的filter便可 * 使用方法(視項目框架而定): * 一、web項目:在web.xml中引用此filter * 二、Springboot項目,經過注入bean的方式注入此filter */ public class CatServletFilter implements Filter { private String[] urlPatterns = new String[0]; @Override public void init(FilterConfig filterConfig) throws ServletException { String patterns = filterConfig.getInitParameter("CatHttpModuleUrlPatterns"); if (patterns != null) { patterns = patterns.trim(); urlPatterns = patterns.split(","); for (int i = 0; i < urlPatterns.length; i++) { urlPatterns[i] = urlPatterns[i].trim(); } } } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; String url = request.getRequestURL().toString(); for (String urlPattern : urlPatterns) { if (url.startsWith(urlPattern)) { url = urlPattern; } } CatContextImpl catContext = new CatContextImpl(); catContext.addProperty( Cat.Context.ROOT, request.getHeader(CatHttpConstants.CAT_HTTP_HEADER_ROOT_MESSAGE_ID)); catContext.addProperty(Cat.Context.PARENT, request.getHeader(CatHttpConstants.CAT_HTTP_HEADER_PARENT_MESSAGE_ID)); catContext.addProperty(Cat.Context.CHILD, request.getHeader(CatHttpConstants.CAT_HTTP_HEADER_CHILD_MESSAGE_ID)); Cat.logRemoteCallServer(catContext); Transaction t = Cat.newTransaction( CatConstants.TYPE_URL, url); try { Cat.logEvent("Service.method", request.getMethod(), Message.SUCCESS, request.getRequestURL().toString()); Cat.logEvent("Service.client", request.getRemoteHost()); filterChain.doFilter(servletRequest, servletResponse); t.setStatus(Transaction.SUCCESS); } catch (Exception ex) { t.setStatus(ex); Cat.logError(ex); throw ex; } finally { t.complete(); } } @Override public void destroy() { } }
本節實例中每一個工程都會用到調用鏈上下文通用類。git
@Component public class CatRestInterceptor implements ClientHttpRequestInterceptor { @Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { Transaction t = Cat.newTransaction(CatConstants.TYPE_REMOTE_CALL, request.getURI().toString()); try { HttpHeaders headers = request.getHeaders(); // 保存和傳遞CAT調用鏈上下文 Cat.Context ctx = new CatContextImpl(); Cat.logRemoteCallClient(ctx); headers.add(CatHttpConstants.CAT_HTTP_HEADER_ROOT_MESSAGE_ID, ctx.getProperty(Cat.Context.ROOT)); headers.add(CatHttpConstants.CAT_HTTP_HEADER_PARENT_MESSAGE_ID, ctx.getProperty(Cat.Context.PARENT)); headers.add(CatHttpConstants.CAT_HTTP_HEADER_CHILD_MESSAGE_ID, ctx.getProperty(Cat.Context.CHILD)); // 保證請求繼續被執行 ClientHttpResponse response = execution.execute(request, body); t.setStatus(Transaction.SUCCESS); return response; } catch (Exception e) { Cat.getProducer().logError(e); t.setStatus(e); throw e; } finally { t.complete(); } } }
CatServletFilter 對 cat-ui 的入口進行了埋點,CatRestInterceptor 實現 ClientHttpRequestInterceptor接口 能夠對 RestTemplate 發起的請求進行攔截,利用這一點對調用點埋點,同時在 Http Header 中存入 調用鏈的上下文,將調用鏈傳遞下去。程序員
cat-business-consumer、cat-order-service、cat-storage-service 中的埋點與 cat-ui 埋點的方式相同。github
發起請求web
curl http://127.0.0.1:8082/start
cat 監控界面能夠看到本節實例的服務。shell
點開 「logView」 能夠看到完整的調用鏈信息。微信
點擊 「Graph」 查看圖表形式的調用鏈信息。框架
https://github.com/gf-huanchu...curl
https://github.com/dianping/c...ide
歡迎掃碼或微信搜索公衆號《程序員果果》關注我,關注有驚喜~