求取一份极致的简单:全链路跟踪中间件探索之路
source link: http://www.10tiao.com/html/217/201807/2649698174/1.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
起初,我们全面调研了社区很多比较成熟的产品之后,发现这些产品与我们公司现存场景多有不符的地方,主要的一点就是我们公司内部应用之间通信方式的多样化。各业务部门之间技术栈极不统一,各业务部门内部的应用之间以及各业务部门应用之间的通信方式自然也多种多样,公开服务的方式包括:REST、RabbitMQ、Dubbo、RMI、Zookeeper等,调用服务的方式包括:OkHttp 2.x、OkHttp 3.x 、Apache HttpClient、Spring RestTemplate、RabbitMQ、Dubbo、RMI、Zookeeper等。我们在自研这套产品过程中,首先参考了谷歌公开的《Dapper大规模分布式系统的跟踪系统》这篇论文,借鉴了社区类似产品的很多思路和理念,像Twitter的Zipkin、阿里的鹰眼、去哪儿网的QTracer、GitHub上开源的PinPoint等产品。
低消耗:全链路跟踪中间件在接入后应该做到对在线服务的影响足够小,甚至可以忽略不计;
低侵入:不应该让各在线服务显示感受到跟踪API的存在,至少不应该显示侵入业务代码内部,也就是不能出现在类中的import处;
可开关:全链路跟踪中间件的调用链参数传递及日志落地时机要做到在线开关,以避免重大Bug影响在线服务;
延展性:全链路跟踪中间件至少在未来几年的服务体量和集群规模都应该能完全把控住,主要针对的是存储组件。
Trace Agent:各业务服务内部的埋点,其中包括各种通信方式的参数传递、配置模块、接入模块等,最终将调用链节点数据以日志形式落地;
Filebeat:采集Trace agent产生的调用链节点日志并送给Logstash;
Logstash:对跟踪日志进行再处理,像属性提取并结构化后输出到ElasticSearch;
ElasticSearch:调用链节点日志的最终存储地,每个节点日志以行为单位进行存储;
Trace Web UI:数据展现页分为四部分,调用链TraceId列表、调用链列表、依赖分析图(基于百度的Echarts)、节点详情页,如下:
调用链TraceId列表
调用链列表
依赖分析图
节点详情页
三. 追本溯源 全链路跟踪中间件产品要解决的第一个非常重要的问题就是调用链源头的追溯,随着对产品的理解逐渐加深,关于调用链源头我们梳理出两点,一是人为调用(触发页面上某事件),二是系统定时调用(定时任务触发):
人为调用:调用链源头可追溯至javax.servlet.Filter上
系统定时调用:调用链源头可追溯至定时任务的执行点(基于我们自研的分布式定时任务产品)
四. 传递之道 全链路跟踪中间件产品要解决的第二个非常重要的问题就是调用链参数(traceId和父spanId)向下游服务传递。在调用下游服务时,有些调用是不需要跟踪的,比如调用Kubernetes的REST接口、ES的REST接口,所以我们设计了三级开关处理:机器级开关(跳掉某个IP的跟踪)、应用级开关(跳掉某个应用的跟踪)、接口级开关(跳掉应用内某个接口的跟踪)。各种通信方式调用链参数传递逻辑如下:
OkHttp2.x、OkHttp3.x(HTTP)
Apache HttpClient(HTTP)
Spring RestTemplate(HTTP)
REST接口(HTTP)
RabbitMQ Send(MQ)
RabbitMQ Recv(MQ)
Dubbo Provider(RPC)
Dubbo Consumer(RPC)
RMI Server(RPC)
RMI Client(RPC)
异步调用时,线程池内的线程是获取不到与主线程关联的对象数据的,需要用使用阿里开源的一个类库(transmittable-thread-local)对原有线程池进行包装:
OkHttp2.x、OkHttp3.x(HTTP)
Apache HttpClient(HTTP)
Spring RestTemplate(HTTP)
REST接口(HTTP)
RabbitMQ Send(MQ)
RabbitMQ Recv(MQ)
Dubbo(RPC)
RMI Server(RPC)
BeanPostProcessor(Spring的扩展点实现隐式改造)
OkHttp3注册方式调整(OkHttp3的拦截器链List是不可能更改的):
Apached HttpClient注册方式调整(Apached HttpClient的拦截器链没有公开添加的方法):
Dubbo服务改造(Dubbo的Filter接口没有纳入Spring体系)
Q:TraceId生成算法,如何避免重复? A:TraceId的生成我们融入了业务语义,业务描述部分+System.nanoTimes,业务语义部分存储在ZK中,是动态可配置的。
Q:会不会将历史数据也查出来?有区分么? A:TraceId列表是按环境、应用、TraceId模糊查询、接口名、时间段查出来的。
8月17日正式上课,点击阅读原文链接即可报名。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK