Tomcat 下部署若依单体应用可观测最佳实践

实现目标

  • 采集指标信息
  • 采集链路信息
  • 采集日志信息
  • 采集 RUM 信息
  • 会话重放 即用户访问前端的一系列过程的会话录制信息,包括点击某个按钮、操作界面、停留时间等,有助于客户真是意图、操作复现

版本信息

  • Tomcat (9.0.81)
  • Springboot(2.6.2)
  • JDK (>=8)
  • DDTrace (>=1.0)

特别说明:如果是 Springboot 项目,Tomcat 大版本需与 Springboot 内置的 Tomcat 大版本一致,否则可能会存在启动异常。

若依的单体应用

  • 下载源码

若依的单体应用:RuoYi: 🎉 基于SpringBoot的权限管理系统 易读易懂、界面简洁美观。 核心技术采用Spring、MyBatis、Shiro没有任何其它重度依赖。直接运行即可用 - Gitee.com

git clone https://gitee.com/y_project/RuoYi.git
  • 移除内部 tomcat

调整项目根目录的 pom.xml

......<dependencyManagement><dependencies><!-- SpringBoot的依赖配置--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.5.15</version><type>pom</type><scope>import</scope><!-- 移除内部 tomcat --><exclusions><exclusion><artifactId>spring-boot-starter-tomcat</artifactId><groupId>org.springframework.boot</groupId></exclusion></exclusions></dependency>
......
  • war 输出

调整 ruoyi-admin 模块下的 pom.xml 文件

<packaging>war</packaging>
  • 调整日志

在 ruoyi-admin/src/main/resources 新增 logback-spring.xml,原文如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration><!-- 日志存放路径 --><property name="log.path" value="/home/root/ruoyi/logs" /><!-- 日志输出格式 --><property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - [%method,%line] %X{dd.service} %X{dd.trace_id} %X{dd.span_id} - %msg%n" /><!-- 控制台输出 --><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${log.pattern}</pattern></encoder></appender><!-- 系统日志输出 --><appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.path}/sys-info.log</file><!-- 循环政策:基于时间创建日志文件 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 日志文件名格式 --><fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 日志最大的历史 60天 --><maxHistory>60</maxHistory></rollingPolicy><encoder><pattern>${log.pattern}</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 过滤的级别 --><level>INFO</level><!-- 匹配时的操作:接收(记录) --><onMatch>ACCEPT</onMatch><!-- 不匹配时的操作:拒绝(不记录) --><onMismatch>DENY</onMismatch></filter></appender><appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.path}/sys-error.log</file><!-- 循环政策:基于时间创建日志文件 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 日志文件名格式 --><fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 日志最大的历史 60天 --><maxHistory>60</maxHistory></rollingPolicy><encoder><pattern>${log.pattern}</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 过滤的级别 --><level>ERROR</level><!-- 匹配时的操作:接收(记录) --><onMatch>ACCEPT</onMatch><!-- 不匹配时的操作:拒绝(不记录) --><onMismatch>DENY</onMismatch></filter></appender><!-- 用户访问日志输出  --><appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.path}/sys-user.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 按天回滚 daily --><fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 日志最大的历史 60天 --><maxHistory>60</maxHistory></rollingPolicy><encoder><pattern>${log.pattern}</pattern></encoder></appender><!-- 系统模块日志级别控制  --><logger name="com.ruoyi" level="info" /><!-- Spring日志级别控制  --><logger name="org.springframework" level="warn" /><root level="info"><appender-ref ref="console" /></root><!--系统操作日志--><root level="debug"><appender-ref ref="file_info" /><appender-ref ref="file_error" /></root><!--系统用户操作日志--><logger name="sys-user" level="info"><appender-ref ref="sys-user"/></logger>
</configuration> 
  • 编译

进入项目根目录执行以下命令进行编译:

mvn clean package

如果没有安装 Maven,则需要先安装 Maven 再进行编译。

[INFO] --- spring-boot:2.5.15:repackage (default) @ ruoyi-admin ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for ruoyi 4.7.7:
[INFO] 
[INFO] ruoyi .............................................. SUCCESS [  0.179 s]
[INFO] ruoyi-common ....................................... SUCCESS [  4.622 s]
[INFO] ruoyi-system ....................................... SUCCESS [  0.770 s]
[INFO] ruoyi-framework .................................... SUCCESS [  0.950 s]
[INFO] ruoyi-quartz ....................................... SUCCESS [  0.388 s]
[INFO] ruoyi-generator .................................... SUCCESS [  0.378 s]
[INFO] ruoyi-admin ........................................ SUCCESS [  4.554 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  12.287 s
[INFO] Finished at: 2023-10-13T16:30:12+08:00
[INFO] ------------------------------------------------------------------------

DataKit

  • 安装 DataKit
  • 开启采集器

安装 DataKit

参考 DataKit 安装文档:主机安装 - 观测云文档

DataKit 开启 DDTrace 采集器

DDTrace 采集器用于采集应用链路信息,参考 DDTrace 采集器接入文档:DDTrace - 观测云文档

DataKit 开启 Log 采集器

Log 采集器用于采集日志信息,参考 Log 采集器接入文档:日志采集 - 观测云文档

需要调整以下信息:

 logfiles = ["/home/liurui/ruoyi/logs/*.log",]## Add service tag, if it's empty, use $source.service = "ruoyi"## Grok pipeline script name.pipeline = "ruoyi.p"
  • logfiles:需要采集的日志文件路径
  • service: 服务名称
  • pipeline: 日志解析

Pipeline 配置

Pipeline 用于数据治理,这里主要是将日志信息进行提取,以便与链路信息关联。

在 datakit/pipeline/ 目录下创建 ruoyi.p 文件,内容如下:

grok(_, "%{TIMESTAMP_ISO8601:time} %{NOTSPACE:thread_name} %{LOGLEVEL:status}%{SPACE}%{NOTSPACE:class_name} - \\[%{NOTSPACE:method_name},%{NUMBER:line}\\] %{DATA:service_name2} %{DATA:trace_id} %{DATA:span_id} - %{GREEDYDATA:msg}")default_time(time,"Asia/Shanghai")

DataKit 开启 StatsD 采集器

StatsD 采集器用于采集指标信息,参考StatsD 采集器接入文档:StatsD - 观测云文档

DataKit 开启 RUM 采集器

RUM 采集器: RUM(Real User Monitor)采集器用于收集网页端或移动端上报的用户访问监测数据。参考RUM 采集器接入文档:RUM - 观测云文档

重启 DataKit

重启 DataKit:服务管理 - 观测云文档

DDTrace

下载 dd-trace-java,尽量下载最新版本:Releases · GuanceCloud/dd-trace-java · GitHub

创建 RUM

  • 登陆观测云
  • 选择 用户访问检测,选择 应用列表,点击 新建应用
  • 应用名称 填写 ruoyi-admin应用 ID 可以自定义,也可以点击 随机生成 按钮
  • 应用类型 选择 web,右边 SDK 配置 有几个类型,这里我们选择 CDN 同步载入复制对应的脚本内容,后续会用到
  • 点击 创建 按钮,完成创建。

Tomcat

下载 Tomcat

下载对应版本的 Tomcat:Apache Tomcat® - Apache Tomcat 9 Software Downloads

配置 DDTrace

在 Tomcat bin 目录下新增脚本 setenv.sh 文件。

export CATALINA_OPTS="-javaagent:/home/root/agent/dd-java-agent-1.14.0-guance.jar \-Ddd.tags=env:test \-Ddd.jmxfetch.enabled=true \-Ddd.jmxfetch.statsd.host=localhost \-Ddd.jmxfetch.statsd.port=8125 \-Ddd.jmxfetch.tomcat.enabled=true\-Dlogging.config=classpath:logback-spring.xml"
  • javaagent: 指定 ddtace 目录
  • Dlogging.config: 指定应用的日志以 logback 日志输出。如果应用内部使用的是 log4j,指定对应的文件即可。

部署应用

将已经打包好的应用 RuoYi/ruoyi-admin/target/ruoyi-admin.war 复制到 Tomcat 的 webapps 下。

启动 Tomcat

执行 bin/startup.sh

apache-tomcat-9.0.81/bin$ ./startup.sh 
Using CATALINA_BASE:   /home/root/middleware/apache-tomcat-9.0.81
Using CATALINA_HOME:   /home/root/middleware/apache-tomcat-9.0.81
Using CATALINA_TMPDIR: /home/root/middleware/apache-tomcat-9.0.81/temp
Using JRE_HOME:        /home/root/middleware/jdk/jdk-11.0.18
Using CLASSPATH:       /home/root/middleware/apache-tomcat-9.0.81/bin/bootstrap.jar:/home/root/middleware/apache-tomcat-9.0.81/bin/tomcat-juli.jar
Using CATALINA_OPTS:   -javaagent:/home/root/agent/dd-java-agent-1.14.0-guance.jar                       -Ddd.tags=env:test                       -Ddd.jmxfetch.enabled=true                       -Ddd.jmxfetch.statsd.host=localhost                       -Ddd.jmxfetch.statsd.port=8125                       -Ddd.jmxfetch.tomcat.enabled=true                      -Dlogging.config=classpath:logback-spring.xml
Tomcat started.

加入 RUM

Tomcat 启动完成后,自动解压 war 应用,进入到 /webapps/ruoyi-admin/WEB-INF/classes/templates 目录下,调整 include.html,将上一步复制的脚本代码粘贴到 head

<head th:fragment=header(title)>
...
<script src="https://static.guance.com/browser-sdk/v3/dataflux-rum.js" type="text/javascript"></script>
<script>window.DATAFLUX_RUM &&window.DATAFLUX_RUM.init({applicationId: 'APP_ID',datakitOrigin: 'http://localhost:9529', // 协议(包括://),域名(或IP地址)[和端口号]env: 'production',version: '1.0.0',service: 'browser',sessionSampleRate: 100,sessionReplaySampleRate: 70,trackInteractions: true,traceType: 'ddtrace', // 非必填,默认为ddtrace,目前支持 ddtrace、zipkin、skywalking_v3、jaeger、zipkin_single_header、w3c_traceparent 6种类型allowedTracingOrigins: ['http://localhost:8080','http://localhost:8080/ruoyi-admin'],  // 非必填,允许注入trace采集器所需header头部的所有请求列表。可以是请求的origin,也可以是是正则});window.DATAFLUX_RUM && window.DATAFLUX_RUM.startSessionReplayRecording()
</script>
...
</head>
  • applicationId:复制过来的就不需要调整。
  • datakitOrigin: 用于接收 RUM 数据上报的 DataKit 地址
  • allowedTracingOrigins: 与后端 APM 串联,前端调用 API 接口,会在对应的接口新增 Trace 所需的 Header 信息

效果

访问 http://localhost:8080/ruoyi-admin,默认用户名:admin,密码:admin123

日志

进入日志详情,可以查看到当前日志对应的链路信息

链路信息

也可以通过链路查看日志和指标信息

指标信息

RUM 看板

会话重放

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/711072.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Redis笔记】Redis消息队列方案

Reids消息队列&#xff08;Message Queue&#xff09; 消息队列 是指利用 高效可靠 的 消息传递机制 进行与平台无关的 数据交流&#xff0c;并基于数据通信来进行分布式系统的集成。 消息队列具有 低耦合、可靠投递、广播、流量控制、最终一致性 等功能。 常见的消息队列 有 …

ensp路由器将不同网络连通在一起

1.拓扑结构信息如下 二层交换机&#xff1a;lsw2,lsw3,lsw5,lsw6 不进行ip配置&#xff0c;只是定义vlan&#xff0c;和主机标注的保持一致&#xff0c;向下连接pc用access&#xff0c;向上连接路由交换机用trunk lsw2配置信息如下图 定义vlan&#xff0c;设置各个连接口的方式…

tcpdump 常用用法

简要记录下tcpdump用法 监控某个ip上的某个端口的流量 tcpdump -i enp0s25 tcp port 5432 -nn -S 各个参数作用 -i enp0s25 指定抓包的网卡是enp0s25 -nn 显示ip地址和数字端口 &#xff0c;如果只 -n 则显示ip&#xff0c;但是端口为services文件中的服务名 如果一个…

用python写一个自动化部署工具

效果 起因 现在springboot项目的自动化部署已经非常普遍&#xff0c;有用Jenkins的&#xff0c;有用git钩子函数的&#xff0c;有用docker的…等等。这段时间在玩python&#xff0c;想着用python实现自动化部署&#xff0c;即能锻炼下编码能力&#xff0c;又方便运维。于是开始…

每日学习总结20240228

每日总结 20240228 1.获取系统命令执行结果 #include <stdio.h>#define TRUE 1 #define FALSE 0int get_system_cmd_result(const char *command, char *buffer, int bufferLen) {FILE *pipe popen(command, "r");if (pipe NULL) {return FALSE;}while (f…

HTML-表格、表单和CSS初识,选择器,书写规范

&#xff11;. 表格标签 &#xff11;.&#xff11;创建表格 表格标签是一种用来处理&#xff0c;显示表格式数据的常用标签。 注意&#xff1a; &#xff11;. tr 用于定义表格中的一行&#xff0c;必须嵌套在 table标签中&#xff0c;在 table中包含几对 tr&#xff0c;就有…

实用指南:SOLIDWORKS数据失真问题的解决之道

在数据处理和模拟计算的过程中&#xff0c;数据失真是一个常见的挑战。数据失真指的是由于计算机或人为操作导致的原始数据与计算结果或实际情况之间的偏差。特别是在使用SOLIDWORKS这类工程设计软件时&#xff0c;数据失真可能由多种因素引起&#xff0c;如软件版本老旧、设置…

AI大模型-启航

文章目录 什么是大模型&#xff1f;&#xff08;大体现在参数量巨大&#xff09;大模型将会改变那些行业&#xff08;大模型有哪些作用&#xff1f;&#xff09;如何搞数据训练模型&#xff1f;LangChain带来的技术变革LangChain架构 什么是大模型&#xff1f;&#xff08;大体…

九、GG bond的逻辑运算

描述 GG bond想要锻炼自己的逻辑能力&#xff0c;于是输入了两个整型变量x和y&#xff0c;分别判断它们的与、或、非关系&#xff0c;你能帮他输出x与y&#xff0c;x或y&#xff0c;非x&#xff0c;非y的值吗&#xff1f; 输入描述&#xff1a; 输入两个整数x和y&#xff0c…

Vue+SpringBoot打造不良邮件过滤系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统用户模块2.2 收件箱模块2.3 发件箱模块2.4 垃圾箱模块2.5 回收站模块2.6 邮箱过滤设置模块 三、实体类设计3.1 系统用户3.2 邮件3.3 其他实体 四、系统展示五、核心代码5.1 查询收件箱档案5.2 查询回收站档案5.3 新…

Linux学习-etcdctl安装

etcdctl3.5下载链接 1. 先通过上面链接下载gz包2. 解压 [rootk8s-master ~]# tar xf etcd-v3.5.11-linux-amd64.tar.gz [rootk8s-master etcd-v3.5.11-linux-amd64]# ls Documentation etcd etcdctl etcdutl README-etcdctl.md README-etcdutl.md README.md READMEv2-e…

图像分割 - 查找图像的轮廓(cv2.findContours函数)

1、前言 轮廓,是指图像中或者物体的外边缘线条。在简单的几何图形中,图形的轮廓是由平滑的线条构成,容易被识别。但不规则的图形或者生活中常见的物体轮廓复杂,识别起来比较困难 2、findContours函数 这里先介绍函数的参数,具体的含义会在下面实验中阐述 opencv 提供的轮…

『大模型笔记』自用的“科技文章翻译 GPT”和它的 Prompt

自用的“科技文章翻译 GPT”和它的 Prompt 你是一位精通简体中文的专业翻译,尤其擅长将专业学术论文翻译成浅显易懂的科普文章。请你帮我将以下英文段落翻译成中文,风格与中文科普读物相似。规则: - 翻译时要准确传达原文的事实和背景。 - 即使上意译也要保留原始段落格式,…

每天一个数据分析题(一百八十四)

在下列哪种情况下线性回归模型不适合代替逻辑回归模型&#xff1f; A. 预测的目标变量是连续型的并且分布范围不受限制 B. 预测的目标变量是二元的并且服从二项分布 C. 自变量与因变量之间的关系可以假设为线性关系 D. 需要预测客户的具体购买金额 题目来源于CDA模拟题库 …

React入门之React_渲染基础用法和class实例写法

渲染元素 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>04元素渲染</title><script src&…

什么是RPC?谈谈你对RPC的理解

RPC&#xff08;Remote Procedure Call&#xff0c;远程过程调用&#xff09;是一种计算机通信协议。它允许一台计算机&#xff08;客户端&#xff09;通过网络调用另一台计算机&#xff08;服务器&#xff09;上的程序&#xff0c;并等待该程序的结果返回。RPC抽象了网络通信的…

go mod中如何解决 xxx/yyy/lib@v1.1.0: unrecognized import path

需要检查的几个地方 这个错误通常出现在 Go 模块系统无法找到指定版本的模块时。有几种可能的原因和解决方法&#xff1a; 模块未被发布或标记&#xff1a; 确保 xxx/yyy/lib 模块的版本 v1.1.0 已经被正确地发布或标记。你可以在对应的 GitLab 仓库中查看是否存在 v1.1.0 标签…

2024-2-29-网络编程作业

1>TCP 源代码: 服务器端&#xff1a; #include <myhead.h> #define SER_IP "10.168.1.111" #define SER_PORT 8888 #define MAXSIZE 128 int main(int argc, char const *argv[]) {int sfd socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in sin;sin…

代码随想录算法训练营|day47

第九章 动态规划 198.打家劫舍213.打家劫舍II337.打家劫舍III代码随想录文章详解 198.打家劫舍 dp[i]表示偷第i家及之前所能获取的最大金额 偷第i家&#xff1a;dp[i] dp[i-2]nums[i]&#xff0c;不偷第i家&#xff1a;dp[i] dp[i-1] func rob(nums []int) int {if len(num…

RDD简介与基础编程

1. 什么是RDD&#xff1f; RDD&#xff08;Resilient Distributed Dataset&#xff09;叫做弹性分布式数据集&#xff0c;是Spark中最基本的数据处理模型。在代码中&#xff0c;RDD是一个抽象类&#xff0c;他代表着一个弹性的、不可变的、可分区的、里面的元素可并行计算的集…