一、简介
sofa-rpc的全链路追踪技术是基于Sofa-Tracer实现的,Sofa-Tracer是基于ZipKin(谷歌Dapper)实现的,Sofa-Tracer参考了ZipKin的Trace-span设计;提供了相应的异步处理机制,每次会将父线程的上下文复制到子线程,为了防止多此异步调用的场景下,上下文的串用,不会再客户端相应阶段才清理上下文,而是会提前清理。
sofa-rpc在Sofa-Tracer的基础上,提供了以下新的特性
可插拔:基于Extension机制,用户可以重写,实现自己的trace,包括相应的Filter逻辑
总线设计:sofa-rpc的trace机制实现是基于其EventBus机制实现的,对于业务方来说是无侵入式的
trace/span:将一次系统调用用traceId标记,traceId通过IP地址+时间戳+自增+进程PID生成;而spanId将在一次服务间的调用分为了cs (client send)、cr (client recv)、sr (server recv)、ss (server send),如此设计,是为了区分在一个服务发生的多次调用,通过spanID能区分
数据采样设计:在高并发系统中,可能某个Error日志出现的时候,一定不会是一天,可能几千几万条,但并不是所有都需要被持久化的,sofa-rpc提供了基于RingBuffer的机制,对数据进行随机采样,当然,你也可以通过Sofa-Tracer的Sampler自定义采用规则
异步刷新机制:通常,我们的日志的持久化都是同步操作,但是在高并发系统,这会对业务系统造成一定的影响,特别是日志内容较大的时候,sofa-rpc的RingBuffer机制,是通过异步线程,消费RingBuffer里的trace日志任务,将日志持久化到磁盘
耗时计算:sofa-rpc的trace在上下文中提供了对于RPC操作的耗时计算
埋点数据透传:sofa-rpc每次request都会把traceId和spanId等信息带在SofaRequest的requestProps里,以便下一次请求对ID进行继承自增;此方式称为带内透传,谷歌的Dapper默认采用的是带外传播,即通过单独提供一个宽带来传播,不影响原调用数据和网络
异步线程的链路调动:为了防止多此异步调用的场景下,上下文的串用,不会再客户端相应阶段才清理上下文,而是会提前清理。
文件存储结构:sofa-rpc将日志按类型做了以下分类
文件 | 功能 |
---|---|
rpc-client-digest.log | 记录client rpc 调用的链路调用数据 |
rpc-client-stat.log | 记录 client rpc 链路调用的统计数据 |
rpc-server-digest.log | 记录 server rpc 调用的链路调用数据 |
rpc-server-stat.log | 记录 server rpc 链路调用的统计数据 |
static-info.log | 统计信息日志 |
tracer-self.log | tracer 自身的日志记录 |
二、源码分析
ClientProxyInvoker.invoke //客户端调用入口,Trace生产流程
//触发事件总线
1.EventBus.post
//消费到从EventBus来的trace消息,onEvent内对上述trace/span机制细分出来的各类消息进行了相应的处理
2.SofaTracerSubscriber.onEvent
//处理rpc调用前的消息,主要是生成当前调用的Span信息、生成上下游Span关系,并将新的Span放到SofaTracerThreadLocalTraceContext的ThreadLocal的变量里
2.1 Tracers.startRpc
//处理客户端发送请求前的消息,将当前线程的trace和spand等信息放到SofaRequest的requestProps里
2.2 Tracers.clientBeforeSend
//从相应消息体获取到trace和spand等信息并放到自己的线程上下文里
2.3 Tracers.clientAsyncReceivedPrepare
//处理客户端收到响应或者异常的消息,通过相应结果,判定成功或失败,失败则组装异常信息并抛出,异常包含服务端返回异常和客户端信息异常而产生的异常,无论成功与否,结束本次调用Span
2.4 Tracers.clientReceived
//处理服务端收到请求后的消息,获取请求体内的trace和spand等信息,并放到自己的当前线程
2.5 Tracers.serverReceived
//处理服务端返回请求或者异常的消息,判定自己的返回是否出现异常,异常则设置相应的返回的Span的code为(00=成功/01=业务异常/02=RPC逻辑错误)
2.6 Tracers.serverSend
//检查状态,在结束调用的时候进行调用,防止资源泄露
2.7 Tracers.checkState
三、总结
1.sofa-rpc的全链路追踪依靠sofa-trace实现,包含上述说的trace/span、数据采样设计、异步刷新机制等设计,核心功能还是在sofa-trace里