前言

最近在做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-alltlog-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.AspectLog4jMDCPatternConverterlogback: com.yomahub.tlog.core.enhance.logback.AspectLogbackMDCConverterlog4j2: 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个模块,这里放在一起讲

其次要的解决类为TLogDubboFilterTLogDubboxFilter,之前有提到过,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-corecom.yomahub.tlog.core.mq这个包中

主动打印参数和调用工夫:在RPC的filter上面,会有XxxInvokeTimeFilter

异步线程反对/线程池的反对:代码在tlog-corecom.yomahub.tlog.core.thread

自定义TraceId生成器:代码在tlog-commoncom.yomahub.tlog.id

以上所有性能的代码了解,联合着应用文档去浏览了解,应该很容易弄懂,就不作解读了

对于我

我是一个开源作者,也是一名内容创作者。「元人部落」是一个保持做原创的技术科技分享号,会始终分享原创的技术文章,陪你一起成长。