searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

应用全链路追踪实现方案及关键组件技术选型

2023-05-29 06:20:10
30
0

可. 概述       

      随着微服务的普及,应用多节点部署和请求跨服务调用越来越常见,开发人员定位问题的成本越来越高。例如当一个订单出现问题的时候,传统的处理方式是挨个看每个服务节点的日志,找到发生问题的节点再针对性的分析,但是这种方式既耗时,又不直观,效率很慢,于是统一日志中心应运而生。但是有了日志中心后,怎样在一次查询结果中,把某个请求流经的所有服务节点日志按照时间先后顺序一次性展示,又引出了链路追踪的需求。

 

. 链路追踪工具构成

      一般的链路追踪工具主要包含三种组件,客户端,收集器,性能分析服务端,各种框架略有差异的,但是基本都是一样的套路:

      1. 客户端是集成在应用内部或是随应用一起启动的代理进程,主要负责应用数据收集和上报;

      2. 收集器是负责统一收集各个客户端上报的数据,持久化,供服务端进行分析;

      3. 性能分析服务端负责对数据进行拼装,分析,UI展示

 

. 链路追踪工具原理

      链路追踪工具采集的数据,除了运用性能分析的指标,例如接口时间,请求参数等之外,链路本身的数据一般是通过三个ID来串联:traceId,spanId,parentId。

      traceId在整个请求链路中都不会变,我们进行全链路日志查询的时候,也是用的traceId;

      spanId在某个代码块中不会变,这个代码块的范围可以自定义,也可以由框架自主划定,框架一般默认的spanId共享范围是一个方法内部,比如A方法调用B方法,则A方法日志打印出来的spanId都是xxx,B方法日志打印出来的spanId都是yyy。parentId是连接两个相邻的span的id,比如A方法调用B方法,B方法调用C方法,A,B,C的spanId分别是xxx, yyy, zzz,则B方法内的parentId是xxx,C方法内的parentId是yyy.

      性能分析服务端就是通过spanId和parentId将一条条小线段串联为一整条链路,所以服务端的UI界面上一般都能展示出服务topo图。

      开源的链路追踪工具很多,比如zipkin,SkyWalking,pinpoint,jaeger等。以下就以jaeger为例,介绍一下springcloud服务集成和搭建的过程以及效果。

 

. jaeger安装

      jaeger分为jaeger-agent, jaeger-collector, jaeger-query,分别为客户端,收集器,性能分析服务端。可以按照官网文档依次安装,也可以直接运行all-in-one这个容器(https://www.jaegertracing.io/docs/1.45/getting-started/)。

 

. springcloud集成jaeger客户端方式

1. pom文件添加依赖

<dependency>
    <groupId>io.opentracing.contrib</groupId>
    <artifactId>opentracing-spring-jaeger-cloud-starter</artifactId>
    <version>3.3.1</version>
</dependency>

2. 配置文件添加jaeger服务端配置

opentracing:
  jaeger:
    http-sender:
      url: http://localhost:14268/api/traces

3. logback配置文件修改日志格式:

%d{yyyy-MM-dd HH:mm:ss.SSS}#-#%X{X-B3-TraceId:-}#-#%-5level#-#%logger{35}#-#%msg%n

4. 线程池场景下,保证traceid能正常传递,需进行以下处理:

     a. 项目添加该jar包本地依赖:http://182.43.12.244:9090/offerFile/jaeger/opentracing-concurrent-0.4.1-SNAPSHOT.jar

     b. 添加这两个类到工程:

          http://182.43.12.244:9090/offerFile/jaeger/MDCScopeManager.java

          http://182.43.12.244:9090/offerFile/jaeger/TracingConfig.java

      c. 线程池的初始化方式改为类似这样:

import io.opentracing.Tracer;
import io.opentracing.contrib.concurrent.TracedExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

@Configuration
public class JaegerThreadExcutor {

    @Autowired
    private Tracer tracer;

    @Bean
    public Executor executor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(5);
        threadPoolTaskExecutor.setMaxPoolSize(10);
        threadPoolTaskExecutor.initialize();
        return new TracedExecutor(threadPoolTaskExecutor, tracer);
    }
}

      5. 消息队列场景

          opentracing-spring-jaeger-cloud-starter已经集成了对kafka和rabbitmq等消息中间件的支持,无需额外处理

 

. jaeger性能分析服务端效果图

点击后可以查看span详情:

 

. 其他语言的客户端及中间件支持

某些语言原生客户端支持不完善的,可以使用opentelemetry提供的相关集成方案。

opentelemetry是链路追踪的统一规范,提供了一套接口规范和配套工具。同样也是适配于jaeger工具。

opentelemetry官网提供了主流语言和框架的集成方案,可以参考:

https://opentelemetry.io/ecosystem/registry/?component=instrumentation

 

. 统一日志中心

链路追踪工具自带的客户端可以直观的看到服务topo图,追踪链路细节,甚至可以看到每个请求的报文,或者数据库查询sql,对于分析系统性能瓶颈比较有帮助。但是统一日志中心是对业务日志的统一管理和检索,可以协助开发人员根据业务标识快速定位问题。二者相辅相成。

 

. 统一日志中心组件技术选型

最流行的日志中心应该是ELK了,但是ELK的方案也有很多不如意的地方。比如logstash占用资源过多,elasticsearch也占用资源多,集群维护成本较高。logstash的替代方案比较多,对于轻量化的使用场景,可以使用filebeat代替,filebeat占用资源远少于logstash;对于业务深度定制化的场景,可以使用flume集成自定义的二开sink或者source组件。elasticsearch替代方案不多,但是近年来出了loki可以用于替代es,loki比es更轻量,占用资源远小于es,但是只能用配套的promtail作为日志采集客户端。

 

. promtail配置

对于以上的logback日志格式(%d{yyyy-MM-dd HH:mm:ss.SSS}#-#%X{X-B3-TraceId:-}#-#%-5level#-#%logger{35}#-#%msg%n),可参考使用以下promtail配置来完成日志采集:

server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://10.63.143.41:3100/loki/api/v1/push

- job_name: upms_business_logs
  static_configs:
  - targets:
      - localhost
    labels:
      service_name: upms
      logType: businessLog
      __path__: /mnt/logs/upms/cloud-upms.log
  pipeline_stages:
  - regex:
      expression: "^(?s)(?P<logTime>.*)#-#(?P<traceId>\\S*)#-#(?P<level>.*)#-#(?P<className>\\S+)#-#(?P<msg>.*)$"
  - labels:
      level: level

经过以上配置处理后,日志中的日志级别和服务名会作为label存储在loki中,grafana(和kibana类似)中可根据多维度进行日志检索

 

以上查询条件,可以查询出日志级别为INFO,服务名为upms,traceid=61da07451d521138的所有日志

 

 

0条评论
0 / 1000
袁****深
1文章数
0粉丝数
袁****深
1 文章 | 0 粉丝
袁****深
1文章数
0粉丝数
袁****深
1 文章 | 0 粉丝
原创

应用全链路追踪实现方案及关键组件技术选型

2023-05-29 06:20:10
30
0

可. 概述       

      随着微服务的普及,应用多节点部署和请求跨服务调用越来越常见,开发人员定位问题的成本越来越高。例如当一个订单出现问题的时候,传统的处理方式是挨个看每个服务节点的日志,找到发生问题的节点再针对性的分析,但是这种方式既耗时,又不直观,效率很慢,于是统一日志中心应运而生。但是有了日志中心后,怎样在一次查询结果中,把某个请求流经的所有服务节点日志按照时间先后顺序一次性展示,又引出了链路追踪的需求。

 

. 链路追踪工具构成

      一般的链路追踪工具主要包含三种组件,客户端,收集器,性能分析服务端,各种框架略有差异的,但是基本都是一样的套路:

      1. 客户端是集成在应用内部或是随应用一起启动的代理进程,主要负责应用数据收集和上报;

      2. 收集器是负责统一收集各个客户端上报的数据,持久化,供服务端进行分析;

      3. 性能分析服务端负责对数据进行拼装,分析,UI展示

 

. 链路追踪工具原理

      链路追踪工具采集的数据,除了运用性能分析的指标,例如接口时间,请求参数等之外,链路本身的数据一般是通过三个ID来串联:traceId,spanId,parentId。

      traceId在整个请求链路中都不会变,我们进行全链路日志查询的时候,也是用的traceId;

      spanId在某个代码块中不会变,这个代码块的范围可以自定义,也可以由框架自主划定,框架一般默认的spanId共享范围是一个方法内部,比如A方法调用B方法,则A方法日志打印出来的spanId都是xxx,B方法日志打印出来的spanId都是yyy。parentId是连接两个相邻的span的id,比如A方法调用B方法,B方法调用C方法,A,B,C的spanId分别是xxx, yyy, zzz,则B方法内的parentId是xxx,C方法内的parentId是yyy.

      性能分析服务端就是通过spanId和parentId将一条条小线段串联为一整条链路,所以服务端的UI界面上一般都能展示出服务topo图。

      开源的链路追踪工具很多,比如zipkin,SkyWalking,pinpoint,jaeger等。以下就以jaeger为例,介绍一下springcloud服务集成和搭建的过程以及效果。

 

. jaeger安装

      jaeger分为jaeger-agent, jaeger-collector, jaeger-query,分别为客户端,收集器,性能分析服务端。可以按照官网文档依次安装,也可以直接运行all-in-one这个容器(https://www.jaegertracing.io/docs/1.45/getting-started/)。

 

. springcloud集成jaeger客户端方式

1. pom文件添加依赖

<dependency>
    <groupId>io.opentracing.contrib</groupId>
    <artifactId>opentracing-spring-jaeger-cloud-starter</artifactId>
    <version>3.3.1</version>
</dependency>

2. 配置文件添加jaeger服务端配置

opentracing:
  jaeger:
    http-sender:
      url: http://localhost:14268/api/traces

3. logback配置文件修改日志格式:

%d{yyyy-MM-dd HH:mm:ss.SSS}#-#%X{X-B3-TraceId:-}#-#%-5level#-#%logger{35}#-#%msg%n

4. 线程池场景下,保证traceid能正常传递,需进行以下处理:

     a. 项目添加该jar包本地依赖:http://182.43.12.244:9090/offerFile/jaeger/opentracing-concurrent-0.4.1-SNAPSHOT.jar

     b. 添加这两个类到工程:

          http://182.43.12.244:9090/offerFile/jaeger/MDCScopeManager.java

          http://182.43.12.244:9090/offerFile/jaeger/TracingConfig.java

      c. 线程池的初始化方式改为类似这样:

import io.opentracing.Tracer;
import io.opentracing.contrib.concurrent.TracedExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

@Configuration
public class JaegerThreadExcutor {

    @Autowired
    private Tracer tracer;

    @Bean
    public Executor executor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(5);
        threadPoolTaskExecutor.setMaxPoolSize(10);
        threadPoolTaskExecutor.initialize();
        return new TracedExecutor(threadPoolTaskExecutor, tracer);
    }
}

      5. 消息队列场景

          opentracing-spring-jaeger-cloud-starter已经集成了对kafka和rabbitmq等消息中间件的支持,无需额外处理

 

. jaeger性能分析服务端效果图

点击后可以查看span详情:

 

. 其他语言的客户端及中间件支持

某些语言原生客户端支持不完善的,可以使用opentelemetry提供的相关集成方案。

opentelemetry是链路追踪的统一规范,提供了一套接口规范和配套工具。同样也是适配于jaeger工具。

opentelemetry官网提供了主流语言和框架的集成方案,可以参考:

https://opentelemetry.io/ecosystem/registry/?component=instrumentation

 

. 统一日志中心

链路追踪工具自带的客户端可以直观的看到服务topo图,追踪链路细节,甚至可以看到每个请求的报文,或者数据库查询sql,对于分析系统性能瓶颈比较有帮助。但是统一日志中心是对业务日志的统一管理和检索,可以协助开发人员根据业务标识快速定位问题。二者相辅相成。

 

. 统一日志中心组件技术选型

最流行的日志中心应该是ELK了,但是ELK的方案也有很多不如意的地方。比如logstash占用资源过多,elasticsearch也占用资源多,集群维护成本较高。logstash的替代方案比较多,对于轻量化的使用场景,可以使用filebeat代替,filebeat占用资源远少于logstash;对于业务深度定制化的场景,可以使用flume集成自定义的二开sink或者source组件。elasticsearch替代方案不多,但是近年来出了loki可以用于替代es,loki比es更轻量,占用资源远小于es,但是只能用配套的promtail作为日志采集客户端。

 

. promtail配置

对于以上的logback日志格式(%d{yyyy-MM-dd HH:mm:ss.SSS}#-#%X{X-B3-TraceId:-}#-#%-5level#-#%logger{35}#-#%msg%n),可参考使用以下promtail配置来完成日志采集:

server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://10.63.143.41:3100/loki/api/v1/push

- job_name: upms_business_logs
  static_configs:
  - targets:
      - localhost
    labels:
      service_name: upms
      logType: businessLog
      __path__: /mnt/logs/upms/cloud-upms.log
  pipeline_stages:
  - regex:
      expression: "^(?s)(?P<logTime>.*)#-#(?P<traceId>\\S*)#-#(?P<level>.*)#-#(?P<className>\\S+)#-#(?P<msg>.*)$"
  - labels:
      level: level

经过以上配置处理后,日志中的日志级别和服务名会作为label存储在loki中,grafana(和kibana类似)中可根据多维度进行日志检索

 

以上查询条件,可以查询出日志级别为INFO,服务名为upms,traceid=61da07451d521138的所有日志

 

 

文章来自个人专栏
软件开发专栏
1 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0