【微服务】skywalking自定义链路追踪与日志采集

目录

一、前言

二、自定义链路追踪简介

2.1 自定义链路追踪应用场景

2.2 链路追踪几个关键概念

三、skywalking 自定义链路追踪实现

3.1 环境准备

3.2 集成过程

3.2.1 导入核心依赖

3.2.2 几个常用注解

3.2.3 方法集成

3.2.4 上报追踪信息

四、skywalking 自定义日志采集

4.1 概述

4.2 集成过程

4.2.1 引入核心依赖

4.2.2 配置logback文件

4.2.2 接口测试

五、写在文末


一、前言

在前面的分享中,详细了解了在微服务中集成skywalking进行服务链路追踪的过程,不管是使用dubbo还是springcloud做微服务治理,在集成skywalking时,往往关注的更多是不同服务之间的调用情况,但是在实际应用中,如果服务内部的链路调用比较复杂,跨度很长的情况下,是否也可以使用skywalking进行追踪呢?接下来将详细介绍下。

二、自定义链路追踪简介

2.1 自定义链路追踪应用场景

 在下面的场景下,可能需要在单应用内进行追踪:

  • 接口业务逻辑复杂,内含一些关键的远程接口调用;
  • 业务调用链路较长,内部方法调用栈比较深;
  • 需要监控某些关键执行业务逻辑的执行耗时,它们可能是性能瓶颈点;
  • ...

比如下面的一个接口,内部的逻辑调用链路比较深的情况下就需要自定义链路追踪

2.2 链路追踪几个关键概念

在具体学习自定义链路追踪之前,有下面几个概念需要了解

Trace

Trace就是链路,指一个请求经过所有服务的路径,服务间经过的局部链路构成了一条完整的链路,其中每一条局部链路都用一个全局唯一的traceid来标识。

Span

Span用于表示上下层父子关系,同一层级parent id相同,span id不同,span id从小到大表示请求的顺序。通过事先在日志中埋点,找出相同traceId的日志,再加上parent id和span id就可以将一条完整的请求调用链串联起来。

采样

由于每一个请求都会生成一个链路,为了减少性能消耗,避免存储资源的浪费,采集器并不会上报所有的span数据,而是使用采样的方式。举个例子,每秒有1000个请求访问系统,如果设置采样率为1/1000,那么只会上报一个请求到存储端。

存储

链路中的span数据经过收集和上报后会集中存储在一个地方,常用的存储有Mysql,ElasticSearch, HBase, In-memory DB等。

三、skywalking 自定义链路追踪实现

3.1 环境准备

  • 参照之前的文章提前搭建完skywalking 服务,并能访问web-ui界面;
  • 搭建一个springboot工程;
  • 启动nacos服务;

3.2 集成过程

下面演示如何在springboot工程中集成方法级的链路追踪信息并上报skywalking 。

3.2.1 导入核心依赖

在方法中记录追踪信息主要用到apm-toolkit-trace这个依赖,其提供了丰富的注解可供方法使用。

<dependencies><dependency><groupId>org.apache.skywalking</groupId><artifactId>apm-toolkit-trace</artifactId><version>8.14.0</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>

3.2.2 几个常用注解

在使用apm-toolkit-trace时,通常使用其提供的注解用于标准方法和参数,下面来看看常用的几个注解使用。

使用方式

@Trace
@Tag(key = "tag1", value = "arg[0]")
@Tag(key = "tag2", value = "arg[1]")
@Tag(key = "username", value = "returnedObj.username")
@Tag(key = "age", value = "returnedObj.age")
public User getUser(String param1, String param2) {// ActiveSpan.setOperationName("Customize your own operation name, if this is an entry span, this would be an endpoint name");// ...
}

参数说明:

@Trace

用在方法上,表名这是一个方法级的trace,@Trace也可以定义名称,比如@Trace(operationName = "getUserInfo"),@Trace注解其只能在方法上进行注解,使用operationName属性指定Span的名字,若不指定,会使用方法名;

@Tags/ @Tag

使用@Tags/ @Tag注解添加Span的属性

1)key 属性名

2)value 属性值会是一个表达式,具体可以参考官方文档,具体可参考,参考文档

3)arg[0]代表入参的第一个对象,returnedObj即当前方法返回的对象;

3.2.3 方法集成

在工程中创建一个接口

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {@Autowiredprivate UserService userService;@GetMapping("/get")public Object getUserInfo(String userId){Map userInfo = userService.getUserInfo(userId);return userInfo;}
}

业务实现

@Service
@Slf4j
public class UserServiceImpl implements UserService {@Override@Trace(operationName = "getUserInfo")@Tags({@Tag(key = "userId", value = "arg[0]"),@Tag(key = "user", value = "returnedObj")})public Map getUserInfo(String userId) {//获取自定义的上下文中的追踪信息String traceId = TraceContext.traceId();log.info("准备获取用户信息 ,traceId : [{}]", traceId);Map resMap = new HashMap();UserInfo userInfo = new UserInfo(userId, "jerry");resMap.put("user", userInfo);//获取用户所属的组织机构log.info("准备获取组织机构信息 ,traceId : [{}]", traceId);Depart depart = getDepart(userId);resMap.put("depart", depart);return resMap;}@Trace(operationName = "getDepart")@Tags(@Tag(key = "depart", value = "returnedObj"))private Depart getDepart(String userId) {if (userId == null) {return null;}return new Depart("001", "运维部");}
}

在该方法中,我们要实现的逻辑是,根据用户ID获取用户,同时在获取用户信息时还需要拿到组织机构信息,为了使用自定义追踪,在方法上添加了相关的注解,在不接入skywalking 的agent时启动测试接口

3.2.4 上报追踪信息

在启动参数中添加如下信息

-javaagent:E:\code-self\skywalking-agent\skywalking-agent.jar -DSW_AGENT_NAME=sky-service -DSW_AGENT_COLLECTOR_BACKEND_SERVICES=skywalking IP:11800

再次启动服务,并调用上面的接口,从控制台可以看到此时当前接口请求就产生了一条追踪信息,可以看到输出的traceId;

同时在web-ui界面上,可以看到当前请求的处理方法中各个链路的详情,即从接口出发,到接口中处理的各个环节,包括调用的其他方法都能展示出来

点击到具体的方法中,比如点击getUserInfo这个方法中,能够看到追踪的该方法具体的信息,比如参数,返回值

四、skywalking 自定义日志采集

4.1 概述

在实际项目中,为了方便线上排查问题,尤其是微服务之间调用链路比较复杂的系统中,通过可视化日志的手段仍然是最直接也很方便的排查定位问题的手段,比如大家熟悉的ELK就是一种比较成熟的可视化日志展现方式,在skywalking UI界面上,在服务菜单栏中有Log一项,该项就是用于服务中集成日志,然后上报skywalking 进行链路的分析使用。

4.2 集成过程

微服务要通过skywalking 集成和上报日志信息,需要依赖logback日志,因此在集成过程中,需要按照规范定义logback的文件配置,整个过程分为下面几步:

  1. 引入logback依赖;

  2. 配置logback文件,按照规范输出日志信息;

  3. 导出日志并上报到skywalking ;

接下来以上一篇的springcloud接入skywalking 为例,在此基础上继续接入自定义的日志

4.2.1 引入核心依赖

在各个微服务模块中引入如下依赖

        <dependency><groupId>org.apache.skywalking</groupId><artifactId>apm-toolkit-logback-1.x</artifactId><version>8.14.0</version></dependency>

4.2.2 配置logback文件

参考下面的样例配置logback文件,核心配置说明:

  • 在第一个ConsoleAppender中,Pattern中定义的内容表示日志输出格式,其中最关键的就是tid,即通过日志追记录的traceId;

  • 第二个AsyncAppender使用的是异步方式追加,减少对主业务的性能影响;

  • GRPCLogClientAppender,以grpc的方式上报日志到skywalking 的oap服务;

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod=" 5 seconds"><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout"><Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%msg%n</Pattern></layout></encoder></appender><appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender"><discardingThreshold>0</discardingThreshold><queueSize>1024</queueSize><neverBlock>true</neverBlock><appender-ref ref="STDOUT"/></appender><appender name="grpc-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>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%msg%n</Pattern></layout></encoder></appender><root level="INFO"><appender-ref ref="ASYNC"/><appender-ref ref="grpc-log"/></root>
</configuration>

4.2.2 接口测试

启动几个模块的微服务,nacos中可以看到服务已经注册进去

通过网关调用接口:localhost:9001/os/order/getById?id=001,可以看到接口能够响应数据

观察控制台的输出日志,不难发现,接口从order中发起,然后远程调用user服务中查询用户的逻辑,观察order服务的日志输出,产生了一个TID,即上午所说的traceId;

再检查user服务的控制台日志输出,同样输出了TID,细心的同学会发现,这个TID与上面的TID相同,因为是同一条链路的唯一ID;

此时再去WEB-UI界面,可以看到在Log这一栏中,就产生了相关的日志信息

可以在服务下拉框里面选择某个服务进行过滤,比如选择order服务之后点击某条日志进去检查,就能看到这条日志的详细信息

五、写在文末

通过上面的演示过程,演示了如何在微服务中自定义方法级的链路追踪,以及通过自定义输出格式的日志上报到skywalking的完整过程,在实际项目使用中,还需要结合实际需求进行细节上的调整,希望对看到的同学有用,本篇到此结束,感谢观看。

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

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

相关文章

一文讲完Jetpack常用修饰符

Jetpack Compose系列(4) - 修饰符 修饰符 Modifier&#xff0c;即JetpackCompose中的修饰符&#xff0c;可以用来修饰以下内容&#xff1a; 更改可组合项的大小、布局、行为和外观 添加信息&#xff0c;如无障碍标签 处理用户输入 添加高级互动&#xff0c;如使元素可…

2024年【低压电工】复审考试及低压电工作业考试题库

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 低压电工复审考试参考答案及低压电工考试试题解析是安全生产模拟考试一点通题库老师及低压电工操作证已考过的学员汇总&#xff0c;相对有效帮助低压电工作业考试题库学员顺利通过考试。 1、【单选题】()是保证电气作…

第二十四天| 77. 组合

Leetcode 77. 组合 题目链接&#xff1a;77 组合 题干&#xff1a;给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。你可以按 任何顺序 返回答案。 思考&#xff1a;回溯法。把回溯法的搜索过程抽象为树形结构。 每次从集合中选取元素&#xff0…

【开源】基于JAVA+Vue+SpringBoot的河南软件客服系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统管理人员2.2 业务操作人员 三、系统展示四、核心代码4.1 查询客户4.2 新增客户跟进情况4.3 查询客户历史4.4 新增服务派单4.5 新增客户服务费 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的河…

【Python小游戏】五子棋小游戏(完整代码)

文章目录 写在前面Tkinter简介五子棋小游戏游戏介绍程序设计运行结果注意事项写在后面写在前面 本期内容:基于tkinter开发一个五子棋小游戏 实验环境 python3.11及以上pycharmtkinterTkinter简介 Tkinter是Python中最常用的图形用户界面(GUI)库之一,用于创建窗口、对话框…

Map和Set的封装

目录 一、底层原理 二、红黑树的节点 三、仿函数 四、迭代器 4.1、迭代器的定义&#xff1a; 4.2、*:解引用操作 4.3、->:成员访问操作符 4.4、!、 4.5、迭代器的&#xff1a; 4.6、迭代器的-- 五、Map 六、Set 七、红黑树源码 一、底层原理 我们要知道&#…

vue 阿里图标库引入分享

上篇文章分享了element-ui icon 组件的实现原理&#xff0c;文章当中有涉及到了阿里图标库的使用&#xff0c;当时未做详细使用说明&#xff0c;此篇文章是对上篇文章的补充哈。 本篇文章主要分为以下两部分&#xff1a; 一、阿里图标库使用 1.1 阿里图标库地址&#xff1a;…

029 命令行传递参数

1.循环输出args字符串数组 public class D001 {public static void main(String[] args) {for (String arg : args) {System.out.println(arg);}} } 2.找打这个类的路径&#xff0c;打开cmd cmd C:\Users\Admin\IdeaProjects\JavaSE学习之路\scanner\src\com\yxm\demo 3. 编译…

华为机考入门python3--(7)牛客7-取近似值

分类&#xff1a;数字 知识点&#xff1a; str转float float(str) 向上取整 math.ceil(float_num) 向下取整 math.floor(float_num) 题目来自【牛客】 import math def round_to_int(float_num): # 如果小数点后的数值大于等于0.5&#xff0c;则向上取整&#xf…

Unity 读取指定目录所占内存大小

public static class TxxTool{#region 读取文件大小private static List<string> DirList new List<string>();public static long GetFileSize(string path){DirList new List<string>();DirList.Add(path);GetAllDirecotries(path);long fileSize 0;for…

c语言--求第n个斐波那契数列(递归、迭代)

目录 一、概念二、用迭代求第n个斐波那契数1.分析2.完整代码3.运行结果4.如果求第50个斐波那契数呢&#xff1f;看看会怎么样。4.1运行结果&#xff1a;4.2画图解释 三、用迭代的方式求第n个斐波那契数列1.分析2.完整代码3.运行结果4.求第50个斐波那契数4.1运行结果4.2运行结果…

MySQL进阶之锁(表级锁,元数据锁,意向锁)

表级锁 介绍 表级锁&#xff0c;每次操作锁住整张表。锁定粒度大&#xff0c;发生锁冲突的概率最高&#xff0c;并发度最低。应用在MyISAM、 InnoDB、BDB等存储引擎中。 对于表级锁&#xff0c;主要分为以下三类&#xff1a; 表锁 元数据锁&#xff08;meta data lock&…