背景
目前公司的项目日志虽然是有traceId的,但是只能去kibana里查询,不能清晰的表达出这个traceId经过了哪几个节点(包括redis,mysql及其它组件)以及对应的耗时,只能拿着traceId一个个筛选索引模式然后去搜索,并且目前这个traceId是后端用uuid生成的。
目标
接入skywalking,根据traceId查看具体请求的调用链路。
根据traceId查看具体请求在链路上的日志。
同一个请求在skywalking上显示的traceId要和ELK上的traceId要一样。
skywalking
1. 安装jdk11稳定版的
稳定版带jps,好用点。 因为我安装的skywalking版本有点新,依赖jdk11.
bash
代码解读
复制代码
sudo yum install -y java-11-openjdk-devel
2. 下载skywalking
如果用的是jdk8,那么别下载这个skywalking-apm。最新的要jdk11才能运行。
bash
代码解读
复制代码
wget https://archive.apache.org/dist/skywalking/9.4.0/apache-skywalking-apm-9.4.0.tar.gz
3. 下载探针
bash
代码解读
复制代码
wget https://dlcdn.apache.org/skywalking/java-agent/9.3.0/apache-skywalking-java-agent-9.3.0.tgz
4. 分别解压
bash
代码解读
复制代码
tar -zxvf apache-skywalking-apm-9.4.0.tar.gz tar -zxvf apache-skywalking-java-agent-9.3.0.tgz
5. 修改skywaking的配置文件
如果没有存储数据的需求或者说只是想临时看下效果,这一步可以忽略。
bash
代码解读
复制代码
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
python
代码解读
复制代码
/root/apache-skywalking-apm-bin/bin/startup.sh
mysql 8.x (可忽略)
安装mysql 8.x数据库。这里有数据库的就不用装,我是没有,所以装一下,主要目的是为了让等会测试的调用链长一点,调用链路不需要走到mysql的直接跳过
1. 下载 mysql 源安装包
sql
代码解读
复制代码
wget http://dev.mysql.com/get/mysql80-community-release-el7-8.noarch.rpm
2. 安装mysql源
arduino
代码解读
复制代码
yum localinstall -y mysql80-community-release-el7-8.noarch.rpm
3. 安装mysql
css
代码解读
复制代码
yum -y install mysql-community-server --nogpgcheck
4. 启动mysql
bash
代码解读
复制代码
sudo systemctl start mysqld sudo systemctl enable mysqld
5. 查看 MySQL 生成的临时密码
c
代码解读
复制代码
sudo grep 'temporary password' /var/log/mysqld.log
6. 使用临时密码登录 MySQL
bash
代码解读
复制代码
mysql -uroot -p'临时密码'
7. 设置新密码 & 刷新权限
lua
代码解读
复制代码
ALTER USER 'root'@'localhost' IDENTIFIED BY 'rootA1234;'; flush privileges; exit;
8. 开启远程访问
sql
代码解读
复制代码
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
项目中引入依赖
xml
代码解读
复制代码
<!--德鲁伊数据源连接池依赖--> <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
代码解读
复制代码
<?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:
bash
代码解读
复制代码
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:
bash
代码解读
复制代码
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
主要代码如下:
java
代码解读
复制代码
@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里查询日志
如果对ELK搭建和日志收集有兴趣的话可以看我前面的文章:ELK 搭建 & 日志集成
总结
- 接入skywalking,根据traceId查看具体请求的调用链路。
- 根据traceId查看具体请求在链路上的日志。
- 同一个请求在skywalking上显示的traceId要和ELK上的traceId要一样。