调用链监控 CAT 之 URL埋点实践
文章首发于公众号《程序员果果》
地址:https://mp.weixin.qq.com/s/0tLjjlUtKTyOlH-5elj0Xw
URL监控埋点作用
- 一个http请求来了之后,会自动打点,能够记录每个url的访问情况,并将以此请求后续的调用链路串起来,可以在cat上查看logview
- 可以在cat Transaction及Event 页面上都看到URL和URL.Forward(如果有Forward请求的话)两类数据;Transaction数据中URL点进去的数据就是被访问的具体URL(去掉参数的前缀部分)
- 请将catFilter存放filter的第一个,这样可以保证最大可能性监控所有的请求
实践
工程说明
工程名 | 端口 | 作用 |
---|---|---|
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 不再调用其他微服务,所以只在入口加入埋点。通过这样的埋点,可以组成一条完整的调用链。
关键代码
调用链上下文通用类
CatContextImpl.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); } }
CatHttpConstants
/** * 添加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"; }
CatServletFilter
/** * http协议传输,远程调用链目标端接收context的filter, * 通过header接收rootId、parentId、childId并放入CatContextImpl中,调用Cat.logRemoteCallServer()进行调用链关联 * 注:若不涉及调用链,则直接使用cat-client.jar中提供的filter即可 * 使用方法(视项目框架而定): * 1、web项目:在web.xml中引用此filter * 2、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() { } }
本节实例中每个工程都会用到调用链上下文通用类。
cat-ui 工程
CatRestInterceptor
@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 埋点的方式相同。
测试
发起请求
curl http://127.0.0.1:8082/start
cat 监控界面可以看到本节实例的服务。
点开 “logView” 可以看到完整的调用链信息。
点击 “Graph” 查看图表形式的调用链信息。
源码
https://github.com/gf-huanchupk/SpringCloudLearning/tree/master/chapter15
参考

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Python爬虫入门教程 40-100 博客园Python相关40W博客抓取 scrapy
爬前叨叨 第40篇博客吹响号角,爬取博客园博客~本文最终抓取到了从2010年1月1日到2019年1月7日的37W+文章,后面可以分析好多东西了呢 经常看博客的同志知道,博客园每个栏目下面有200页,多了的数据他就不显示了,最多显示4000篇博客如何尽可能多的得到博客数据,是这篇文章研究的一点点核心内容,能√get到多少就看你的了~ 单纯的从每个栏目去爬取是不显示的,转换一下思路,看到搜索页面,有时间~,有时间! 注意看URL链接 https://zzk.cnblogs.com/s/blogpost?Keywords=python&datetimerange=Customer&from=2019-01-01&to=2019-01-01 这个链接得到之后,其实用一个比较简单的思路就可以获取到所有python相关的文章
- 下一篇
保护企业信息安全,阿里云渗透测试服务发布
随着云服务和电商的发展,越来越多的用户将个人资料存储在“云”上,越来越多的交易通过网络完成。然而,云上业务应用漏洞泛滥,安全情况不容乐观。有感于国内企业防护状况不佳,阿里云为企业提供透测试服务,帮助保护企业信息安全。 阿里云渗透测试服务,由阿里安全专家以攻击者思维,模拟黑客对业务系统进行全面深入的安全测试,帮助企业挖掘出正常业务流程中的安全缺陷和漏洞。助力企业先于黑客发现安全风险,防患于未然。 一、阿里云渗透四大优势 1)精英安全专家团队(黑客视角)长期实战钻研于一线企业安全环境下的攻防专家,区别于传统测试,顶尖团队的精湛技术让渗透测试与众不同。 2)针对性更强(紧贴业务)服务会根据业务提供一套专属的攻防方案,深入用户业务,贴近用户需求,快速安全分析,全面深度检测。 3)完善的测试方案(覆盖全面)依据业界安全测试的最佳实践,参考国际标准制定
相关文章
文章评论
共有0条评论来说两句吧...