前言
最近在做 TLog 1.2.5 版本的迭代,许多小伙伴之前也示意说很想参加开源我的项目的奉献。为了让我的项目更好更疾速的迭代新个性以及本着发挥开源精力互相学习交换,很有幸招募到了很多小伙伴与我一起前行。
为了不便大家了解 TLog 我的项目的外围原理和架构,便有了此篇内容。此篇内容偏差 TLog 技术设计和外围原理,同时也涵盖着做一个开源框架所须要思考的问题和技术要点。
我始终置信,好的技术内容应提领关键点,疏导大家该去如何读懂源码。而不是全篇的贴代码。所以此篇也不是源码解析,而是提炼关键点,让大家如何的更好去了解。
因为阅读者在某些点上可能会有常识盲区,为了讲了粗疏,在某些点上我尽可能附加了延长浏览。晓得相干知识点的同学,能够间接跳过。
还有,如果你是第一次浏览到此篇内容,不晓得 TLog 是什么我的项目,则能够移步 Gitee 的托管仓库以及我的项目主页去查看我的项目个性:
gitee 托管仓库:https://gitee.com/dromara/TLog
github 托管仓库:https://github.com/dromara/TLog
我的项目主页:https://yomahub.com/tlog/
你也能够看之前公布的一篇介绍 TLog 文章
https://mp.weixin.qq.com/s/-l…
模块
理解一款开源框架,首先从模块开始理解,TLog 定位是一款轻量级日志追踪框架,它由 10 个模块组成
首先 TLog 既然是一款日志框架,日志加强就是它的外围,得适配支流的日志框架 (log4j / log4j2 /logback),这些最次要的逻辑和最外围的性能实现都在tlog-core
模块中(当前可能还会独自拆出 3 个日志框架的独自模块)。
其次,TLog 可能进行日志追踪,天然要适配微服务架构,反对 RPC 框架 / 协定(dubbo / dubbox / spring cloud feign / http)。因为每种 RPC 框架有本人的扩大点,天然不可能形象写出对立的解决逻辑。所以就有了以下模块:
tlog-dubbo
为对接 apache dubbo 的适配模块
tlog-dubbox
为对接晚期的当当的 dubbox 开源版本,因为有的公司还在用
tlog-feign
为对接 spring cloud feign 的适配模块
tlog-webroot
为对接最一般的 http 调用适配模块
思考到用 spring cloud 的很多公司都会用 spring 全家桶的 spring cloud gateway,所以就有了适配 spring cloud gateway 的适配模块tlog-gateway
在 spring 反对方面,tlog 反对了传统 spring 的 xml 配置构造,也反对了 springboot 的主动拆卸。因为 spring 是 springboot 的子集,所以必然有 2 个模块,所以就有了 tlog-all
和tlog-all-springboot-starter
。之所以要加上 all 字样,因为这 2 个包也是开发者援用的门面包,这 2 个提供独自的依赖地址,会把所须要其余的 tlog 包一起依赖带入。这样就不必一个个去申明依赖了。
TLog 提供了基于 javaagent 的无依赖应用形式,所以就有了 tlog-agent
模块。在打包时,会独自打成一个 jar 包。
其余 tlog 模块所公共应用的一些 VO,枚举,util 类则抽出来造成一个独自的模块,所以就有了tlog-common
。
模块之间的依赖关系图如下:
启动装载
TLog 大概有 80% 的工作都是启动时实现的,所以第一步就要弄清楚 TLog 随着我的项目启动时干了些什么。
因为 springboot 有主动拆卸性能,所以只须要弄清楚 tlog-all-springboot-starter
主动拆卸了什么,就能够理解非 springboot 我的项目那些手动配置 xml 的意义了。
不分明 springboot 主动拆卸性能的同学,能够先去理解下这块的常识,我感觉这篇文章讲的比拟透彻,能够延长浏览下:
https://zhuanlan.zhihu.com/p/…
TLog 在 springboot 环境下所有主动拆卸的配置类,都在 spring.factories
中体现:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.yomahub.tlog.springboot.TLogPropertyConfiguration,\
com.yomahub.tlog.springboot.TLogWebAutoConfiguration,\
com.yomahub.tlog.springboot.TLogFeignAutoConfiguration,\
com.yomahub.tlog.springboot.TLogAspectAutoConfiguration,\
com.yomahub.tlog.springboot.TLogCommonAutoConfiguration,\
com.yomahub.tlog.springboot.TLogGatewayAutoConfiguration
TLogPropertyConfiguration
次要用来主动拆卸的是 TLog 配置初始化器,最终注入的是 TLogPropertyInit
,在传统 spring 环境下,也只须要独自配置TLogPropertyInit
的 xml 就能够了,所以两种 spring 环境造成最终的对立。
TLogWebAutoConfiguration
次要用来主动拆卸 http 协定的拦截器。
TLogFeignAutoConfiguration
次要用来主动拆卸 spring cloud feign 环境下的拦挡过滤器。
TLogAspectAutoConfiguration
次要用来主动拆卸自定义标签的切面,spring 会主动为切中的类生成动静代理注入上下文。
TLogCommonAutoConfiguration
次要用来主动拆卸基于 spring 上下文的工具类。在很多不在 spring 容器治理中的 bean 想获取 spring 上下文中的 bean 时,都会用到这个工具类。
TLogGatewayAutoConfiguration
次要用来主动拆卸 spring cloud gateway 环境下的拦挡过滤器。
只有注册了以上的主动拆卸类,在 springboot 环境下,启动时都会帮你主动拆卸好。然而在传统 spring 下,你还是得在 xml 中一个个的配置。所以开源我的项目反对 springboot 是很有必要的。
这些主动拆卸的程序,也并不是依照配置的程序进行的,有先后依赖关系。具体能够认真钻研源码,源码正文有写。
如果有人不晓得如何管制 springboot 主动拆卸的程序的话,举荐看我之前写的一篇文章,专门针对这个知识点进行了解读
https://mp.weixin.qq.com/s/-7…
那不晓得会不会有人问,那 dubbo/dubbox,三大日志框架的加强就不须要注册主动拆卸器么?
这里一一解释:
dubbo/dubbox,在设计时就有基于 spi 的实现,可能自动识别出扩大的插件,所以无需注册任何 bean 到 spring 容器,所以不须要拆卸。
log4j&logback,字节码模式的话,在 springboot/spring 启动前就得加载了。下文会说到。所以不在 springboot/spring 启动阶段拆卸。至于日志适配模式,因为须要开发者提前替换好相干的 encoder,所以日志框架在加载日志配置文件时就会做这件事。所以也不须要主动拆卸任何货色。
log4j2 的设计齐全采纳插件式,他本人能扫描并辨认到相干扩大插件,所以也不须要在 springboot/spring 拆卸时干任何事。
Log 框架的反对解析
对于 log 框架的反对是 TLog 的重点,次要都在 tlog-core
这个模块中。TLog 接入有三种形式,javaagent 接入,字节码接入,适配模式接入。接入形式和对应的类,有下图:
其实能够发现,javaagent 实质上也是利用字节码的形式进行,区别是,javaagent 的 jar 包外置,不必我的项目依赖。而字节码形式,须要依赖,并且要在启动类外面手动增加 AspectLogEnhance.enhance()
代码进行触发。
还能够发现,javaagent 模式和字节码模式目前是不反对异步日志的。只有适配模式能力反对。
可能会有人有疑难,上图为什么没提到 log4j2 呢。
答:因为之前也说了,log4j2 是插件模式,从实质上来讲。log4j2 的失效形式只有一种,log4j2 主动会去检测插件,严格的说,log4j2 日志加强的形式不属于下面任何一种。也不须要任何拆卸,任何触发条件,只须要定义相干插件就能够了。具体 log4j2 的插件定义在 tlog-core
的如下包里:
com.yomahub.tlog.core.enhance.log4j2
Log 框架中的 MDC
TLog 对 3 大日志框架的 MDC 也有反对,具体三个反对类在以下门路
log4j: com.yomahub.tlog.core.enhance.log4j.AspectLog4jMDCPatternConverter
logback: com.yomahub.tlog.core.enhance.logback.AspectLogbackMDCConverter
log4j2: com.yomahub.tlog.core.enhance.log4j2.AspectLogLog4j2MDCConverter
要留神的是,这 3 个类,并不是间接对 MDC 作解决,这 3 个类的作用是:检测 log 配置是否用了 MDC
如果检测到配置文件有用 mdc,则在 TLog 线程上线文中设置一个标记
TLogContext.setHasTLogMDC(true);
而真正对 MDC 进行解决的是这个类TLogRPCHandler
,这个类是所有 rpc 调用的一个形象层,外面有以下代码进行了 MDC 的解决逻辑:
...
// 如果有 MDC,则往 MDC 中放入日志标签
if (TLogContext.hasTLogMDC()) {MDC.put(TLogConstants.MDC_KEY, tlogLabel);
}
如果这个标记为 true,则用 slf4j 的 MDC API 进行设值
RPC 反对
TLog 对于 RPC 的反对,次要用到的是各个 RPC 框架本人的拦截器和过滤器来实现。
dubbo/dubbox
dubbo 和 dubbox 是应用 dubboFilter 来实现,其原理 2 者统一。代码也都差不多。因为包门路和个别类命名有区别,所以分成了 2 个模块,这里放在一起讲
其次要的解决类为 TLogDubboFilter
和TLogDubboxFilter
,之前有提到过,dubbo/dubbox 有本人的 SPI,能检测出插件。定义 dubbo 的插件形式如下:
@Activate(group = {CommonConstants.PROVIDER, CommonConstants.CONSUMER}, order = -10000)
public class TLogDubboFilter extends TLogRPCHandler implements Filter {...}
dubbo/dubbox 这里分 provider 端和 consumer 端去解决,A->B,A 就是 consumer,B 就是 provider。2 端的解决逻辑不一样。
provider 端:承受隐式传参里的参数 –> 解决参数 –> 放入 tlog 的线程上下文 –> 调用原有业务逻辑
consumer 端:从 tlog 线程上下文中取得参数 –> 解决参数 –> 调用远端业务逻辑
feign/http
在 spring cloud feign 的场景,个别用 feign 作为 consumer,一般的 controller 作为 provider。所以这 2 个放到一起讲。
feign 次要的解决类为TLogFeignFilter
,作为 consumer 端,大抵做了如下事件:
从 tlog 线程上下文中取得参数 –> 参数解决 –> 放入 http header–> 申请 http
而 Controller 解决类次要为TLogWebInterceptor
, 作为 provider 端,大抵做了如下事件:
从 http header 中承受到标签参数 –> 解决参数 –> 放入 tlog 线程上下文 –> 调用原有业务逻辑
自定义标签
自定义标签是 TLog 中一个特色功能模块,能让用户本人定义标签编入 log 日志中。
其次要的解决类就一个 aop,为 AspectLogAop
,地位在tlog-core
中。
其次要思维就是去切 @TLogAspect
标签,而后解析相干参数,最初把后果 append 到线程上下文的标签值中。
这外面波及了标注的解析,点操作符的解析和值的获取等操作。想弄明确,间接看 AspectLogAop
这个类就能够了。
其余性能
TLog 还有其余辅助性能。
对 mq 中间件的反对:代码在 tlog-core
的com.yomahub.tlog.core.mq
这个包中
主动打印参数和调用工夫:在 RPC 的 filter 上面,会有 XxxInvokeTimeFilter
类
异步线程反对 / 线程池的反对:代码在 tlog-core
的com.yomahub.tlog.core.thread
中
自定义 TraceId 生成器:代码在 tlog-common
的com.yomahub.tlog.id
中
以上所有性能的代码了解,联合着应用文档去浏览了解,应该很容易弄懂,就不作解读了
对于我
我是一个开源作者,也是一名内容创作者。「元人部落」是一个保持做原创的技术科技分享号,会始终分享原创的技术文章,陪你一起成长。