当前位置: 首页 > news >正文

基于Java日志平台的访问链路追踪实战

语雀完整版:

https://www.yuque.com/g/mingrun/embiys/ch6d86/collaborator/join?token=vyXkXgZ7PHOQhTI5&source=doc_collaborator# 《基于Java日志平台的访问链路追踪实战》

基于Java日志平台的访问链路追踪实战

一、Java日志体系

  1. 概述

    • 日志接口
    • JCL(Jakarta Commons Logging,Commons Logging  ),Java Apache的项目
    • SLF4J: Simple Logging Facade for Java,缩写Slf4j,是⼀一套简易易Java日志门面,只提供相关接口,和其他日志⼯工具之间需要桥接
  1. 发展历程
    • 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那边去

  1. 配置详解
    • 概述
      • 日志级别
        • trace: 路径跟踪
        • debug: -般用于日常调式
        • info: 打印重要信息
        • warn:给出警告
        • error: 出现错误或问题
          而每个日志组件的具体级别划分稍有不同
      • 日志组件
        • appender: 日志输出目的地,负责日志的输出(输出到什么 地方,  文件、socket、kafka)
        • logger:日志记录器,负责收集处理日志记录(如何处理日志)
        • layout: 日志格式化,负责对输出的日志格式化(以什么形式展现)
  1. 日志建议
    • 门面约束:使用 Log Facade 可以方便的切换具体的日志实现 ,实战中可以把pom中 日志实现框架依赖 scope设置为 runtime
    • 单一原则,一个项目中只使用一个日志实现
    • 依赖约束:pom中的optional选项设置为 true,这样别人继承你项目的时候 就不会继承你得依赖
    • 避免传递
<exclusion><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId>
</exclusion>

    • 写法注意
    • 减少分析
    • 精简至上

二、中间件

  1. 概述:
    • 日志的⽣生命周期一般分为采集,传输,存储和分析四个环节,选⽤用中间件时所关注的⻆角度:性能、可靠性、插件⽀支持程度、配置复杂度
    • 总结:elk成熟,logstatch性能弱于filebeat,kafka做存储性能高
  1. 安装 Es、分词器、es-head、log_statsh、Kibana、kafka、kafka-manager、filebeat
  1. 流程与配置
    fileBeat的速度比logStatsh要快,所以日志文件是由 fileBeat来采集的,然后给kafka,然后logstatsh从kafka获取,然后输出给 es
    • fileBeat
filebeat.inputs:
- type: logenabled: truepaths:- /root/logs/*.logfields:from: filebeat
output.kafka:enabled: truehosts: ["39.98.133.153:9103"]topic: filebeatcompression: gzip

    • kafka补充知识
      • 基本概念

      • offset管理
        kafka允许consumer将当前消费的消息的offset提交到kafka中,这样如果consumer因异常退出后,下次启动仍然可以从上次记录的offset开始向后继续消费消息。
    • logstash 配置
input {kafka {bootstrap_servers => ["39.98.133.153:9103"]group_id => "logstash"topics => ["filebeat"]consumer_threads => 1decorate_events => trueadd_field => {"from" => "filebeat"}codec => "json"}
}
filter {mutate {rename => { "[host][name]" => "host" }}
}
output {elasticsearch {hosts => "localhost:9200"index => "mylog"}stdout {}
}

三、项目搭建

  1. 设计目标
    • 日志的内容应该包括 某次请求id(requestId )、某个用户会话id(sessionId)、某个终端请求id(terminalId),来做到快速检索
    • 要能 满足集群、微服的使用
    • 低侵入、低耦合,延时不能太高
    • 日志的 缓存与防丢失
  1. 系统拓扑

  1. 具体搭建
    • 创建项目 划分模块
    • 引入依赖 logback-kafka-appenderkafka-clients
    • 加入logback配置文件,主要配置了 kafkaAppender
    • 自定义一个 kafkaAppender

三、项目实施

  1. 前端请求:前端一般请求到nginx,这一层有如下两个方案
    • 第一种是使用 filebeat采集日志文件
    • 第二种是使用,lua脚本方式,直接输出到kafka,其中,rid和tid在这一步生成
      • rid:一个随机数
      • tid:可以使用 user-agent
  1. 微服务层
    • 在拦截器中,向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());}
}

  1. 跨服务调用
  1. 项目实现总结
    • 引入依赖 logback-kafka-appenderkafka-clients,然后就创建一个自定义的KafkaAppender(统一定义这个一个),其中制定了kafka的配置,然后每个服务项目 都添加自己的logback.xml配置文件,并在其中配置上面自定义的 appender
    • 定义一个实体类来存放日志信息(这条日志的信息、时间、IP地址、用户名之类的),同时这个实体类是在构造函数中 给其中一个threadLocal变量赋值
    • 定义一个拦截器,将初始化上面这个实体类,并放入初始信息,IP地址、用户名等,再把他自己放到threadlocal变量中去,并打印下接收到了这个请求
    • 然后自定义一个 logInfo注解,写个切面,对加了这个注解的方法做环绕通知,在方法之前前后打印日志,并标上方法名
    • 要自己打印日志,就要先从上面这个 threadLocal中获取一个实体类对象,然后再把自己的msg放进去
  1. 日志内容
    • rid(requestId):一次请求的唯一标示,⽣生成后一直传递到调⽤用结束
      • 项目中使用随机字符,就是定义一个数组,里面放了字母和数字,然后随机去取,拼接成一个长度为10的字符串9
    • sid(sessionId):⽤用户会话相关,涉及登陆时存在,不不登陆的操作为空
      • 用户名-租户-用户Id
    • tid(terminalId):同一个终端的请求标示,可以理理解为同一个设备。可能对应多个⽤用户的多次请求
      • 从请求头中取出UserAgent(可以区分安卓、IOS、不同的浏览器)
    • 另外还有Ip地址
http://www.dtcms.com/a/277930.html

相关文章:

  • JAVA并发——synchronized的实现原理
  • C#特性:从元数据到框架基石的深度解析
  • 强化学习初探及OREAL实践
  • Word中的批注显示与修订显示
  • 【vs2022】 error C2338: Unicode support requires compiling with /utf-8
  • 时间的弧线,逻辑的航道——标准单元延迟(cell delay)的根与源
  • [附源码+数据库+毕业论文+答辩PPT+部署教程+配套软件]基于SpringBoot+MyBatis+MySQL+Maven+Vue实现的交流互动管理系统
  • 基于Springboot+UniApp+Ai实现模拟面试小工具四:后端项目基础框架搭建下
  • 长上下文能力:FlashAttention vs. RingAttention
  • 协程的 callbackFlow 函数的使用和原理
  • 认识数据分析
  • 第一,二次作业
  • LAN-401 linux操作系统的移植
  • DHS及HTTPS工作过程
  • 【Claude Code】 AI 编程指南
  • sql初学见解
  • 多线程死锁
  • 飞算Java AI开发助手:引领智能编程新风尚
  • Llama系列:Llama1, Llama2,Llama3内容概述
  • 【读书笔记】《C++ Software Design》第九章:The Decorator Design Pattern
  • HTML 基本骨架
  • [GWCTF 2019]我有一个数据库
  • SOMEIP协议与测试
  • LeetCode 2401.最长优雅子数组
  • C++数组指针与函数指针
  • 为什么要有延时回调?
  • 2024-2025-2 山东大学《软件工程与实践》期末(回忆版)
  • p4 大小写检查
  • C++高级编程,类模版成员函数类外实现
  • windows10如何安装vue开发环境