一年一度的双十一购物狂欢节就要到了,又到剁手党们开始表演的时刻了。当我们把种草很久的商品放入购物车以后,点击“结算”按钮时,就来到了买买买必不可少的结算页面了。让我们虚拟一个买买买结算系统,为结算页面提供商品、促销、库存等结算信息,就此系统展开如何在springboot项目中集成cat调用链。买买买结算系统包含以下4个项目:
时序图如下:
<dependency> <groupid>com.dianping.cat</groupid> <artifactid>cat-client</artifactid> <version>3.0.0</version> </dependency>
创建/data/appdatas/cat/
目录,并创建client.xml
文件:
<?xml version="1.0" encoding="utf-8"?> <config xmlns:xsi="http://www.w3.org/2001/xmlschema" xsi:nonamespaceschemalocation="config.xsd"> <servers> <server ip="127.0.0.1" port="2280" http-port="8080" /> </servers> </config>
注意:把127.0.0.1替换成cat服务端的ip。
买买买结算系统中一共有5个项目,每个项目都需要配置各自的项目名称。
首先,在每个项目中创建如下文件:
src/main/resources/meta-inf/app.properties
然后,在每个项目里添加如下内容:
app.name=buy-buy-buy-checkout
app.name=buy-buy-buy-cart
app.name=buy-buy-buy-product
app.name=buy-buy-buy-promotion
app.name=buy-buy-buy-store
注意:项目名称只能包含英文字母 (a-z, a-z)、数字 (0-9)、下划线 (_) 和中划线 (-)
在埋点之前,需要先写两个公共类,方便之后埋点时调用。
public class catcontext implements cat.context { private map<string, string> properties = new hashmap<>(); @override public void addproperty(string key, string value) { properties.put(key, value); } @override public string getproperty(string key) { return properties.get(key); } @override public string tostring() { return "catcontext{" + "properties=" + properties + '}'; } }
public class cathttpconstants { public static final string cat_http_header_child_message_id = "dd-cat-child-message-id"; public static final string cat_http_header_parent_message_id = "dd-cat-parent-message-id"; public static final string cat_http_header_root_message_id = "dd-cat-root-message-id"; }
使用cat进行分布式调用链监控,需要修改项目中的代码进行埋点:
那么在买买买结算系统中需要做哪些代码修改呢?看一下时序图的变化就明白了:
第一个埋点,在刚刚接收到请求时,这里使用filter实现,代码如下:
public class catservletfilter implements filter { @override public void init(filterconfig filterconfig) throws servletexception { } @override public void dofilter(servletrequest servletrequest, servletresponse servletresponse, filterchain filterchain) throws ioexception, servletexception { httpservletrequest request = (httpservletrequest) servletrequest; catcontext catcontext = new catcontext(); 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, request.getrequesturi()); 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() { } }
filter已经写好了,接下来还需要把filter注册到springboot中:
@configuration public class catconfiguration { @bean public filterregistrationbean catservletfilter() { filterregistrationbean registration = new filterregistrationbean(); catservletfilter filter = new catservletfilter(); registration.setfilter(filter); registration.addurlpatterns("/*"); registration.setname("cat-servlet-filter"); registration.setorder(1); return registration; } }
第两个埋点,在调用api的httpclient工具类中统一增加代码,以get方式为例:
public static string doget(string url) throws ioexception { httpget httpget = new httpget(url); closeablehttpresponse response = null; closeablehttpclient httpclient = httpclientbuilder.create().build(); string content = null; transaction t = cat.newtransaction(catconstants.type_call, url); try { context ctx = new catcontext(); cat.logremotecallclient(ctx); httpget.setheader(cathttpconstants.cat_http_header_root_message_id, ctx.getproperty(cat.context.root)); httpget.setheader(cathttpconstants.cat_http_header_parent_message_id, ctx.getproperty(cat.context.parent)); httpget.setheader(cathttpconstants.cat_http_header_child_message_id, ctx.getproperty(cat.context.child)); response = httpclient.execute(httpget); if (response.getstatusline().getstatuscode() == 200) { content = entityutils.tostring(response.getentity(), "utf-8"); t.setstatus(transaction.success); } } catch (exception e) { cat.logerror(e); t.setstatus(e); throw e; } finally { if (response != null) { response.close(); } if (httpclient != null) { httpclient.close(); } t.complete(); } return content; }
以上便是springboot集成cat调用链的整个实例了,可以灵活应用,更加优雅的集成到实际项目中。
另外,cat还有很多丰富的功能,可参见。
如对本文有疑问, 点击进行留言回复!!
[杭电多校2020]第一场 1004 Distinct Sub-palindromes
Swift -- 将本地生成的UIImage进行持久化保存(存到文件中fileManager.createFile)
网友评论