语雀完整版:
https://www.yuque.com/g/mingrun/embiys/ch6d86/collaborator/join?token=vyXkXgZ7PHOQhTI5&source=doc_collaborator# 《基于Java日志平台的访问链路追踪实战》
基于Java日志平台的访问链路追踪实战
一、Java日志体系
- 概述

-
- 日志接口
-
- JCL(Jakarta Commons Logging,Commons Logging ),Java Apache的项目
-
- SLF4J: Simple Logging Facade for Java,缩写Slf4j,是⼀一套简易易Java日志门面,只提供相关接口,和其他日志⼯工具之间需要桥接
- 发展历程
-
- sout、e.printstack()
-
- Log4j
-
- Log4j2:性能好,但是完全不兼容一代
-
- Jul(性能不行,jdk自带的)
-
- JCL(为了抽象一层接口,解决混乱问题)
-
-
- jcl接口下的默认实现是 log4j,没有引入就会使用 jul
-
-
-
- jcl推荐下面这种写法,来避免参数拼接造成的浪费
-
if (logger.isDebugEnabled()) {
logger.debug("this is a debug info , message :" + msg);
}
-
- slf4j
-
-
- 他的实现是logback
-
-
-
- 他能桥接到 JCL那边去

- 他能桥接到 JCL那边去
-
- 配置详解
-
- 概述
-
-
- 日志级别
-
-
-
-
- trace: 路径跟踪
-
-
-
-
-
- debug: -般用于日常调式
-
-
-
-
-
- info: 打印重要信息
-
-
-
-
-
- warn:给出警告
-
-
-
-
-
- error: 出现错误或问题
而每个日志组件的具体级别划分稍有不同
- error: 出现错误或问题
-
-
-
-
- 日志组件
-
-
-
-
- appender: 日志输出目的地,负责日志的输出(输出到什么 地方, 文件、socket、kafka)
-
-
-
-
-
- logger:日志记录器,负责收集处理日志记录(如何处理日志)
-
-
-
-
-
- layout: 日志格式化,负责对输出的日志格式化(以什么形式展现)
-
-
- 日志建议
-
- 门面约束:使用 Log Facade 可以方便的切换具体的日志实现 ,实战中可以把pom中 日志实现框架依赖 scope设置为 runtime
-
- 单一原则,一个项目中只使用一个日志实现
-
- 依赖约束:pom中的optional选项设置为 true,这样别人继承你项目的时候 就不会继承你得依赖
-
- 避免传递
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
-
- 写法注意
-
- 减少分析
-
- 精简至上
二、中间件
- 概述:
-
- 日志的⽣生命周期一般分为采集,传输,存储和分析四个环节,选⽤用中间件时所关注的⻆角度:性能、可靠性、插件⽀支持程度、配置复杂度
-
- 总结:elk成熟,logstatch性能弱于filebeat,kafka做存储性能高
- 安装 Es、分词器、es-head、log_statsh、Kibana、kafka、kafka-manager、filebeat
- 流程与配置
fileBeat的速度比logStatsh要快,所以日志文件是由 fileBeat来采集的,然后给kafka,然后logstatsh从kafka获取,然后输出给 es
-
- fileBeat
filebeat.inputs:
- type: log
enabled: true
paths:
- /root/logs/*.log
fields:
from: filebeat
output.kafka:
enabled: true
hosts: ["39.98.133.153:9103"]
topic: filebeat
compression: gzip
-
- kafka补充知识
-
-
- 基本概念

- 基本概念
-
-
-
- offset管理
kafka允许consumer将当前消费的消息的offset提交到kafka中,这样如果consumer因异常退出后,下次启动仍然可以从上次记录的offset开始向后继续消费消息。
- offset管理
-
-
- logstash 配置
input {
kafka {
bootstrap_servers => ["39.98.133.153:9103"]
group_id => "logstash"
topics => ["filebeat"]
consumer_threads => 1
decorate_events => true
add_field => {"from" => "filebeat"}
codec => "json"
}
}
filter {
mutate {
rename => { "[host][name]" => "host" }
}
}
output {
elasticsearch {
hosts => "localhost:9200"
index => "mylog"
}
stdout {
}
}
三、项目搭建
- 设计目标
-
- 日志的内容应该包括 某次请求id(requestId )、某个用户会话id(sessionId)、某个终端请求id(terminalId),来做到快速检索
-
- 要能 满足集群、微服的使用
-
- 低侵入、低耦合,延时不能太高
-
- 日志的 缓存与防丢失
- 系统拓扑

- 具体搭建
-
- 创建项目 划分模块
-
- 引入依赖
logback-kafka-appender和kafka-clients
- 引入依赖
-
- 加入logback配置文件,主要配置了
kafkaAppender
- 加入logback配置文件,主要配置了
-
- 自定义一个 kafkaAppender
三、项目实施
- 前端请求:前端一般请求到nginx,这一层有如下两个方案
-
- 第一种是使用 filebeat采集日志文件
-
- 第二种是使用,lua脚本方式,直接输出到kafka,其中,rid和tid在这一步生成
-
-
- rid:一个随机数
-
-
-
- tid:可以使用 user-agent
-
- 微服务层
-
- 在拦截器中,向logbean放入 ip地址、sid(登陆的时候 可以放入用户名),rid(随机数 ,请求Id), tid(ip、user-agent)
-
- 定义一个 注解@logInfo,定义切面 对加上这个注解的方法,方法执行前后 打印执行日志,方法中可以对日志进行封装,如下所示
public class LogUtil {
private final static Logger logger = LoggerFactory.getLogger("kafka");
public static void printInfo(String msg) {
LogBean logBean = LogBean.logBeanThreadLocal.get();
logBean.setMessage(msg);
logger.info(logBean.toString());
}
}
- 跨服务调用
- 项目实现总结
-
- 引入依赖
logback-kafka-appender和kafka-clients,然后就创建一个自定义的KafkaAppender(统一定义这个一个),其中制定了kafka的配置,然后每个服务项目 都添加自己的logback.xml配置文件,并在其中配置上面自定义的 appender
- 引入依赖
-
- 定义一个实体类来存放日志信息(这条日志的信息、时间、IP地址、用户名之类的),同时这个实体类是在构造函数中 给其中一个threadLocal变量赋值
-
- 定义一个拦截器,将初始化上面这个实体类,并放入初始信息,IP地址、用户名等,再把他自己放到threadlocal变量中去,并打印下接收到了这个请求
-
- 然后自定义一个 logInfo注解,写个切面,对加了这个注解的方法做环绕通知,在方法之前前后打印日志,并标上方法名
-
- 要自己打印日志,就要先从上面这个 threadLocal中获取一个实体类对象,然后再把自己的msg放进去
- 日志内容
-
- rid(requestId):一次请求的唯一标示,⽣生成后一直传递到调⽤用结束
-
-
- 项目中使用随机字符,就是定义一个数组,里面放了字母和数字,然后随机去取,拼接成一个长度为10的字符串9
-
-
- sid(sessionId):⽤用户会话相关,涉及登陆时存在,不不登陆的操作为空
-
-
- 用户名-租户-用户Id
-
-
- tid(terminalId):同一个终端的请求标示,可以理理解为同一个设备。可能对应多个⽤用户的多次请求
-
-
- 从请求头中取出UserAgent(可以区分安卓、IOS、不同的浏览器)
-
-
- 另外还有Ip地址

912



被折叠的 条评论
为什么被折叠?



