Skywalking 调用链路 & 集成日志背景 目标 skywalking 1. 安装jdk11稳定版的 稳定版带jp
背景
目前公司的项目日志虽然是有traceId的,但是只能去kibana里查询,不能清晰的表达出这个traceId经过了哪几个节点(包括redis,mysql及其它组件)以及对应的耗时,只能拿着traceId一个个筛选索引模式然后去搜索,并且目前这个traceId是后端用uuid生成的。
目标
接入skywalking,根据traceId查看具体请求的调用链路。
根据traceId查看具体请求在链路上的日志。
同一个请求在skywalking上显示的traceId要和ELK上的traceId要一样。
skywalking
1. 安装jdk11稳定版的
稳定版带jps,好用点。 因为我安装的skywalking版本有点新,依赖jdk11.
sudo yum install -y java-11-openjdk-devel
2. 下载skywalking
如果用的是jdk8,那么别下载这个skywalking-apm。最新的要jdk11才能运行。
wget https://archive.apache.org/dist/skywalking/9.4.0/apache-skywalking-apm-9.4.0.tar.gz
3. 下载探针
wget https://dlcdn.apache.org/skywalking/java-agent/9.3.0/apache-skywalking-java-agent-9.3.0.tgz
4. 分别解压
tar -zxvf apache-skywalking-apm-9.4.0.tar.gz
tar -zxvf apache-skywalking-java-agent-9.3.0.tgz
5. 修改skywaking的配置文件
如果没有存储数据的需求或者说只是想临时看下效果,这一步可以忽略。
vim /root/apache-skywalking-apm-bin/config/application.yml # 根据自己下载的路径来,不一定是这个
# 和下面这段配置对齐(也可以不配,默认是h2内存数据库来存储,但是我这边已经启动了es了就配置一下)
storage:
selector: ${SW_STORAGE:elasticsearch}
elasticsearch:
namespace: ${SW_NAMESPACE:"my_elasticsearch_cluster"} # 这里的name可以方法问elasticsearch9200页面进行查看
6.启动skywalking
/root/apache-skywalking-apm-bin/bin/startup.sh
mysql 8.x (可忽略)
安装mysql 8.x数据库。这里有数据库的就不用装,我是没有,所以装一下,主要目的是为了让等会测试的调用链长一点,调用链路不需要走到mysql的直接跳过
1. 下载 mysql 源安装包
wget http://dev.mysql.com/get/mysql80-community-release-el7-8.noarch.rpm
2. 安装mysql源
yum localinstall -y mysql80-community-release-el7-8.noarch.rpm
3. 安装mysql
yum -y install mysql-community-server --nogpgcheck
4. 启动mysql
sudo systemctl start mysqld
sudo systemctl enable mysqld
5. 查看 MySQL 生成的临时密码
sudo grep 'temporary password' /var/log/mysqld.log
6. 使用临时密码登录 MySQL
mysql -uroot -p'临时密码'
7. 设置新密码 & 刷新权限
ALTER USER 'root'@'localhost' IDENTIFIED BY 'rootA1234;';
flush privileges;
exit;
8. 开启远程访问
create user 'root'@'%' identified with mysql_native_password by 'rootA1234;';
grant all privileges on *.* to 'root'@'%' with grant option;
flush privileges;
参考文章
- 最新 CentOS7 上使用 yum 安装 MySQL8 超详细教程_yum安装mysql8-CSDN博客
- /var/log/mysqld.log 但是执行命令后发现没有要找的密码,是个空的文件_mysqld.log为空-CSDN博客
测试
pom
项目中引入依赖
<!--德鲁伊数据源连接池依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
<!--要获取skywalking的traceId-->
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-trace</artifactId>
<version>9.3.0</version>
</dependency>
logback.xml
由于我测试项目用的日志框架是 logback
所以这里只贴 logback.xml的内容:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="LOG_HOME" value="/data/log/service/logs/app"/>
<property name="LOG_PATTERN"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{traceId}] [%thread] %-5level %logger{36} -%msg%n" />
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>${LOG_PATTERN}</Pattern>
</encoder>
</appender>
<!-- 输出到指定文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/fang.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件的命名规则 -->
<FileNamePattern>${LOG_HOME}/fang.%d{yyyy-MM-dd}.log</FileNamePattern>
</rollingPolicy>
<encoder>
<Pattern>${LOG_PATTERN}</Pattern>
</encoder>
</appender>
<!-- skyWalking日志采集 -->
<appender name="APM_LOG" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
<Pattern>${LOG_PATTERN}</Pattern>
</layout>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
<appender-ref ref="APM_LOG"/>
</root>
</configuration>
微服务调用链
我测试用的是两个微服务wl和fang,主要调用链是:wl -> fang -> 数据库,并且在请求走到对应节点上打印相应日志。
启动微服务
fang:
java -jar -javaagent:"/root/skywalking-agent/skywalking-agent.jar" -Dskywalking.agent.service_name=wl -Dskywalking.collector.backend_service=127.0.0.1:11800 wl-1.0.0-SNAPSHOT.jar
wl:
java -jar -javaagent:"/root/skywalking-agent/skywalking-agent.jar" -Dskywalking.agent.service_name=fang -Dskywalking.collector.backend_service=127.0.0.1:11800 fang-0.0.1-SNAPSHOT.jar
skywalking trace 界面
用traceId 查询具体请求调用链
skywalking log 界面
用traceId 查询具体请求调用链对应的日志
到这里为止我们其实已经完成了我们的目标1和目标2了。
接下来,我们继续来完成我们的目标3:同一个请求在skywalking上显示的traceId要和ELK上的traceId要一样。
项目里新增traceFilter
主要代码如下:
@Component
@Order(1)
public class TraceIdFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
String traceId = httpServletRequest.getHeader(LogConstant.TRACE_ID);
if (traceId != null) {
MDC.put(LogConstant.TRACE_ID, traceId);
} else {
MDC.put(LogConstant.TRACE_ID, TraceContext.traceId());
}
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
MDC.clear();
}
}
这个类的主要作用是:
- 如果请求头里没有traceId(说明这个服务是链路中的第一个服务节点),将skywalking的traceId放入当前线程的日志上下文中,这样在打印日志的时候就会自动打印出来(前面logback.xml中的traceId取的就是MDC中的traceId)。
- 如果请求头里有traceId(说明这个服务是链路中的非第一个服务节点,复用上个节点的traceId),那么直接用请求头里的traceId。
kibana 查询日志
用skywalking里的traceId去kibana里查询日志
总结
- 接入skywalking,根据traceId查看具体请求的调用链路。
- 根据traceId查看具体请求在链路上的日志。
- 同一个请求在skywalking上显示的traceId要和ELK上的traceId要一样。
转载自:https://juejin.cn/post/7419248237733249076