内容简介:一周一更,UAVStack又来例行推新啦~~~在上周的推送中,我们介绍了调用链技术中的日志聚合、分布式跟踪及二者的关联运用,相信大家已经对调用链有了基本了解。本周,我们将继续介绍调用链的模型设计与模型时序图,小伙伴们上车啦在分布式在线服务中,一个请求需要经过多个系统中的多个模块,可能需要多达上百台机器的协作才能完成单次请求。在这种场景下,单靠人力已经无法掌握整个请求中各个阶段的性能开销,更无法快速定位系统中的性能瓶颈。发生故障时,通常需要多个团队合作,查看大量日志才能确定问题。作为一个在职场摸爬滚打很多年
一周一更,UAVStack又来例行推新啦~~~在上周的推送中,我们介绍了调用链技术中的日志聚合、分布式跟踪及二者的关联运用,相信大家已经对调用链有了基本了解。本周,我们将继续介绍调用链的模型设计与模型时序图,小伙伴们上车啦
在分布式在线服务中,一个请求需要经过多个系统中的多个模块,可能需要多达上百台机器的协作才能完成单次请求。在这种场景下,单靠人力已经无法掌握整个请求中各个阶段的性能开销,更无法快速定位系统中的性能瓶颈。发生故障时,通常需要多个团队合作,查看大量日志才能确定问题。
举个栗子
作为一个在职场摸爬滚打很多年的资深工程师,程序猿小亮面对的系统设计可能是这个样子的:
借助良好的系统设计和编码规范,对于一般有问题的请求处理,小亮能够凭借对多个系统的了解,在翻阅大量日志文件(前提是日志输出也是规范的)后定位到问题。随着用户数量的增加,系统复杂度也越来越高,小亮的大部分时间都花费在团队沟通工作上了。
这时,小亮可能会想,如果有一个 工具 能够把每次请求经过的系统都记录下来,并把每个节点的消耗时间和处理类等信息也抓取出来,那这个世界该多么美好啊。
一个偶然的机会,小亮了解到了UAVStack中的调用链功能,能够在对业务代码没有任何侵入的前提下轻松解决他的难题。下面就让我们一起开启神奇的调用链探索之旅吧。
UAVStack调用链技术栈支持
效果展示
轻型调用链展示详情:
重调用链开启以后请求报文体抓取视图:
更多使用说明请参阅官网:用户指南具体实现
UAVStack调用链实现分为模型设计、服务端信息收集(轻/重)、方法级信息收集(轻/重)、客户端信息收集(轻/重)、调用链协议设计(轻/重)、调用链上下文传递、调用信息记录及传递、调用数据统计处理等。由于篇幅限制,本期暂时只分享其中的模型设计及实现调用链模型时序图。
在参考现有经验并结合具体业务场景需求的基础上,我们抽象出了如下调用链模型:
调用链元数据:
-
SpanEndpointType:调用类型(Root(“E”),Service(“S”), Client(“C”), Method(“M”))。
☆ Root指本条调用链中的第一个节点,即一条调用链的开始位置,可以是一个服务请求,一次httpclient调用等;
☆ Service指当前调用链中非第一个节点且是系统对外提供的服务,如用户登录服务;
☆ Client指当前调用链中非第一个节点且是当前系统与外部沟通的一种途径,如httpclient、mongoclient等;
☆ Method值当前调用链中非第一个节点且是系统中的一个函数,如日志数出函数等。
-
traceId:调用链唯一标识符。
-
spanId:一条调用链中当前节点的调用顺序(与SpanEndpointType 结合唯一);spanId采用分层设计,形如1.2.1,既能表示调用顺序同时又能反应所才调用链层级。
-
parentId:一条调用链中当前节点的父调用节点。
调用链绘制规则:
- 调用者(服务、web)最初调用(无父调用)记为开始节点E,并生成唯一调用链ID,traceID;
- 系统内应用组件调用(如httpclient,方法调用等),spanId末尾数字加1(若为第一个则末尾加.1);
- 系统间调用(如A服务调用B服务),A服务与B服务span信息只有SpanEndpointType不同(分别对应span的两个端)。
举个栗子
用户小明想通过网络获取一些知识,通过网络,他进入了系统O。服务O中部署了服务A和B,A服务使用httpclient与B通讯,B服务先会与 Redis 交互然后和 MySQL 交互,最后系统O将小明感兴趣的内容返回给小明。
在完成此次请求的过程中,UAVStack抽象出如下调用链模型:
- 小明(下图中的调用方)通过门户访问了A服务,此时调用链生成唯一traceId并将当前节点的SpanEndpointType置为N(第一个节点的意思),spanId置为1(当前调用层中的第一个节点),parentId置为E(没有父节点的意思);
- A服务通过httpclient向B服务发起一次http请求,此时调用链元数据如下traceId(沿用父节点id);1.1(spanId末尾加.1,因为为第一次调用);1(parentId父节点的spanId);C(调用类型记录为C客户端调用);
- B服务接收到来自于A服务通过httpclient的调用,此时调用链元数据如下traceId(沿用初始调用时id);1.1(spanId沿用传递过来的spanId);1(parentId沿用传递过来的parentId);S(调用类型记录为S服务端处理请求);
- B服务先查询Redis,此时调用链元数据如下traceId(沿用初始调用时id);1.1.1(spanId末尾加.1,因为为第一次调用);1.1(parentId父节点的spanId);C(调用类型记录为C客户端调用);
- B服务又发起对MySQL的查询,此时调用链元数据如下traceId(沿用初始调用时id);1.1.2(spanId末尾数字加1,因为为非第一次调用);1.1(parentId父节点的spanId);C(调用类型记录为C客户端调用);
- 处理结束,调用链记录下了整个过程中的调用信息。
- UAVServer :中间件增强框架,提供在中间件的不同生命周期进行劫持的能力,即中间件劫持技术,如tomcat webcontainer启动开始时刻等;
- JEEServiceRunGlobalFilterHandler :借助中间件劫持技术延伸出的全局filter,能够拦截所有经过中间件(tomcat等)的请求;
- ServiceSpanInvokeChainHandler :调用链中专注处理归为Service类型节点的handler; ClientSpanInvokeChainHandler:调用链中专注处理归为Client类型节点的handler;
- XXAdapter :泛指调用链中所有的adapter,提供在handler(分为Service、Client、Method三种handler,图中省略了Method类型)执行动作before和after时刻操作数据的能力。
如此,在对用户代码无任何”侵入”的前提下便完成了调用链的生成,生成过程大致如下:
- 在JEEServiceRunGlobalFilterHandler的doRepuest中包装解析请求;
- xxAdapter中的before对数据进行适配;
- xxHandler处理对应范围内(Service、Client和Method)内请求数据;
- xxAdapter中的after对数据进行整理或记录;
- 在JEEServiceRunGlobalFilterHandler的doResponse中返回处理过后请求。
本文的主要目的是让大家初步了解一条调用链绘制的大致生命周期,具体实现将在下期分享中详细介绍,欢迎大家继续关注码完代码还要辛苦码字的技术小哥哥~~~
UAVStack已在Github上开放源码,并提供了安装部署、架构说明和用户指南等双语文档,欢迎访问-给星-拉取~~~
扫描下方二维码,关注一个不会让你失望的公众号
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 调用链系列二:解读UAVStack中的调用链技术
- 调用链系列三:解读UAVStack中的调用链技术
- Vue-js 源码解读系列——this 直接调用数据源
- 直观讲解-RPC调用和HTTP调用的区别
- Phoenix解读 | Phoenix源码解读之索引
- dubbo源码解析(二十七)远程调用——injvm本地调用
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
How to Design Programs, 2nd Edition
Matthias Felleisen、Robert Bruce Findler、Matthew Flatt、Shriram Krishnamurthi / MIT Press / 2018-5-4 / USD 57.00
A completely revised edition, offering new design recipes for interactive programs and support for images as plain values, testing, event-driven programming, and even distributed programming. This ......一起来看看 《How to Design Programs, 2nd Edition》 这本书的介绍吧!