百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

基于Skywalking实现全链路追踪的万字攻略(有手就能操作版)

toyiye 2024-05-09 18:41 25 浏览 0 评论

本文将重点介绍基于Skywalking的全链路实现,包括Skywalking的整体架构和基本概念原理、Skywalking环境部署、SpringBoot和Python集成Skywalking监控实现等。


一、Skywalking基本介绍


1.Skywalking整体架构


Skywalking 8.x版本架构图


SkyWalking整体架构在逻辑上分为四部分:探针Agent、平台后端OAP、存储和UI界面。


  • 探针Agent:负责从应用中收集链路信息,并发送给SkyWalking的OAP服务器。它会收集Tracing和Metrics数据,将数据格式化为SkyWalking适用的格式。探针安装在服务所在的服务器上,以方便数据的获取。
  • 平台后端OAP:接收探针发送的数据,并在内存中使用分析引擎进行数据的整合运算,然后将数据存储到对应的存储介质上。OAP支持数据聚合、数据分析以及驱动数据流从探针到用户界面的流程。分析包括Skywalking原生链路跟踪和性能指标以及第三方来源,包括Istio及 Envoy telemetry、Zipkin链路跟踪格式化等。
  • 存储:通过开放的插件化的接口存放SkyWalking数据,目前支持的存储器有Elasticsearch、MySQL、ShardingSphere、TiDB、H2等。
  • 用户界面UI:负责提供控制台,查看链路、服务指标等。UI是一个基于接口高度定制化的Web系统,用户可以可视化查看和管理SkyWalking数据。


2.Skywalking基本概念


1)Skywalking中的核心概念


与Prometheus不同,SkyWalking的度量机制是围绕以下具有层次结构的核心概念构建的:


  • 层(Layer):表示计算机科学中的一个抽象框架,如 Operating System(OS_LINUX 层)、Kubernetes(k8s层)。该层将是从不同技术检测到的不同服务的所有者。
  • 服务:表示一组或一组工作负载,它为传入请求提供相同的行为。
  • 服务实例(Service Instance):服务组中的单个工作负载。
  • 端点(Endpoint):传入请求的服务路径。
  • 进程:操作系统进程。在某些场景下,service instance不是一个进程,比如一个 Kubernetes Pod可能包含多个进程。


2)Skywalking中的指标流


Metric名称和属性(标签)由SkyWalking OAP服务器根据数据源以及OAL和MAL配置。SkyWalking 提供了对时间序列指标进行下采样(down-sampling),并生成不同时间段数据(分钟、小时、天)的能力。SkyWalking指标流如下:



二、Skywalking原理解析


1.Skywalking中Trace实现


Skywalking中实现了OpenTracing中的Trace、Span、Tags、Logs等核心概念,不同之处是在
Trace级别和Span级别之间加了一个Segment概念,用于表示一个服务实例内的Span集合。


1)Trace ID


在Skywalking中,全局ID由三个 long 类型的字段(part1、part2、part3)构成,分别记录了ServiceInstanceId、Thread ID和Context生成序列,格式如下所示:


${ServiceInstanceId}.${Thread ID}.(${时间戳} * 10000 + 线程自增序列([0, 9999]))


2) TraceSegment


在SkyWalking中,TraceSegment是一个介于Trace与Span之间的概念,它是一条Trace的一段,可以包含多个Span。在微服务架构中,一个请求基本都会涉及跨进程(以及跨线程)的操作,例如,RPC调用、通过MQ异步执行、HTTP请求远端资源等,处理一个请求就需要涉及到多个服务的多个线程。TraceSegment记录了一个请求在一个线程中的执行流程(即Trace信息)。将该请求关联的TraceSegment串联起来,就能得到该请求对应的完整Trace。



TraceSegment的核心结构如图所示,包括以下核心字段:


  • traceSegmentId(ID类型):TraceSegment的全局唯一标识
  • refs(List<TraceSegmentRef> 类型):它指向父TraceSegment
  • relatedGlobalTraces(DistributedTraceIds类型):记录当前TraceSegment所属Trace的Trace ID。
  • spans(List<AbstractTracingSpan>类型):当前TraceSegment包含的所有Span。
  • ignore(boolean类型):ignore字段表示当前TraceSegment是否被忽略。


3)Context


SkyWalking中的每个TraceSegment都与一个Context上下文对象一对一绑定,Context上下文不仅记录了TraceSegment的上下文信息,还提供了管理TraceSegment生命周期、创建Span以及跨进程(跨线程)传播相关的功能。


2.Trace的收集和发送


1)Context的生成与采样


应用访问时,如果不做任何限制,每个请求都会生成一条完整的Trace。在面对海量的业务请求时会同步产生海量的Trace数据,对网络和存储都带来巨大的压力,因此几乎所有的Trace系统都支持采样功能。在Skywalking Agent中是通过SamplingService服务实现的,SamplingService的trySampling()方法递增samplingFactorHolder字段,当增加到阈值(默认值为3,可以通过agent.sample_n_per_3_secs配置进行修改)时会返回false,表示采样失,这时就会生成IgnoredTracerContext,IgnoredTracerContext是个空Context实现,不会记录Trace信息。



2)Trace的收集


当TracingContext通过stopSpan()方法关闭最后一个Span时,会调用finish()方法关闭相应的TraceSegment,与此同时,还会通知所有监听TracingContext关闭事件的监听器TracingContextListener。TraceSegmentServiceClient主要功能就是在TraceSegment结束时对其进行收集,并发送到后端的OAP集群。



3.Skywalking OAP内核架构


Skywalking OAP采用微内核架构,使用ModuleManager(组件管理器)管理多个Module(组件),一个Module可以对应多个ModuleProvider(组件服务提供者),ModuleProvider是Module底层真正的实现。



在OAP服务启动时,一个Module只能选择使用一个ModuleProvider对外提供服务。一个ModuleProvider可能支撑了一个非常复杂的大功能,在一个ModuleProvider中,可以包含多个Service,一个Service实现了一个ModuleProvider中的一部分功能,通过将多个Service进行组装集成,可以得到ModuleProvider的完整功能。


三、Skywalking环境部署


Skywalking测试demo环境如下所示,分别测试SpringBoot应用和Python程序的监控实现。



1.解压安装包,使用9.3.0版本


# tar -xzvf apache-skywalking-apm-9.3.0.tar.gz
# mv apache-skywalking-apm-bin/ /usr/local/skywalking


2.修改OAP配置文件,指定存储类型为MySQL


# vi config/application.yml
cluster:
  selector: ${SW_CLUSTER:standalone}
storage:
  selector: ${SW_STORAGE:mysql}
  mysql:
    properties:
      jdbcUrl: ${SW_JDBC_URL:"jdbc:mysql://192.168.112.121:3306/swtest?rewriteBatchedStatements=true&allowMultiQueries=true"}
      dataSource.user: ${SW_DATA_SOURCE_USER:root}
      dataSource.password: ${SW_DATA_SOURCE_PASSWORD:123456}
      dataSource.cachePrepStmts: ${SW_DATA_SOURCE_CACHE_PREP_STMTS:true}
      dataSource.prepStmtCacheSize: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_SIZE:250}
      dataSource.prepStmtCacheSqlLimit: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_LIMIT:2048}
      dataSource.useServerPrepStmts: ${SW_DATA_SOURCE_USE_SERVER_PREP_STMTS:true}
    metadataQueryMaxSize: ${SW_STORAGE_MYSQL_QUERY_MAX_SIZE:5000}
    maxSizeOfBatchSql: ${SW_STORAGE_MAX_SIZE_OF_BATCH_SQL:2000}
    asyncBatchPersistentPoolSize: ${SW_STORAGE_ASYNC_BATCH_PERSISTENT_POOL_SIZE:4}


3.对Webapp进行配置


# vi webapp/application.yml
serverPort: ${SW_SERVER_PORT:-18080}
# Comma seperated list of OAP addresses.
oapServices: ${SW_OAP_ADDRESS:-http://192.168.112.121:12800}


默认使用8080端口访问,修改为18080。


4.下载MySQL连接jar并拷贝到oap-libs


#下载链接:mysql-connector-java-8.0.28.jar
https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.28/mysql-connector-java-8.0.28.jar
# cp mysql-connector-java-8.0.28.jar /usr/local/skywalking/oap-libs/


将jar包放在oap-libs目录下即可,如果没有连接jar包,会抛如下异常:


java.lang.RuntimeException: Failed to get driver instance for jdbcUrl=jdbc:mysql://localhost:3306/swtest?rewriteBatchedStatements=true&allowMultiQueries=true


5.连接mysql创建应用库swtest


# mysql -uroot -p
mysql> create database swtest;


在mysql中创建配置文件中的应用库swtest,否则会提示报错。


com.zaxxer.hikari.pool.HikariPool - 574 [main] ERROR [] - HikariPool-1 - Exception during pool initialization.java.sql.SQLSyntaxErrorException: Unknown database 'swtest'


6.启动Skywalking服务


进入bin目录执行startup.sh文件即可启动SkyWalking平台。


cd ../bin
./startup.sh


启动成功看log输出日志:


2023-11-04 16:06:18,455 - com.linecorp.armeria.common.util.SystemInfo - 237 [main] INFO  [] - hostname: tango-db01 (from /proc/sys/kernel/hostname)
2023-11-04 16:06:20,036 - com.linecorp.armeria.server.Server - 797 [armeria-boss-http-*:12800] INFO  [] - Serving HTTP at /0:0:0:0:0:0:0:0%0:12800 - http://127.0.0.1:12800/


再查看swtest库中,已经创建了很多表:


mysql> show tables;
+--------------------------------------------------------+
| Tables_in_swtest                                       |
+--------------------------------------------------------+
| alarm_record                                           |
| alarm_record_tag                                       |
| browser_app_error_rate                                 |


7.访问UI页面,端口为18080:http://192.168.112.121:18080/



四、Skywalking全链路监控实现


1.SpringBoot应用集成Skywalking监控


1)环境准备


在mysql中创建表并插入数据:


mysql> use sw_mysql;
Database changed
mysql> CREATE TABLE `sw_tb` ( 
    -> `id` int(11) NOT NULL AUTO_INCREMENT, 
    -> `username` varchar(50) DEFAULT NULL, 
    -> `password` varchar(50) DEFAULT NULL,
    -> PRIMARY KEY (`id`) 
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8
    -> ;
Query OK, 0 rows affected, 2 warnings (0.03 sec)


mysql> insert into sw_mysql.sw_tb(`username`,`password`) values('张三','AAA'),('李四','BBB'),('王五','CCC');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0


mysql> select * from sw_mysql.sw_tb;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | 张三     | AAA      |
|  2 | 李四     | BBB      |
|  3 | 王五     | CCC      |
+----+----------+----------+
3 rows in set (0.00 sec)


2)在Eclipse中创建SpringBoot项目


在pom.xml文件中添加引入Skywalking的依赖包:


  <dependency>
            <groupId>org.apache.skywalking</groupId>
            <artifactId>apm-toolkit-trace</artifactId>
            <version>8.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.skywalking</groupId>
            <artifactId>apm-toolkit-log4j-2.x</artifactId>
            <version>8.3.0</version>
        </dependency>
  <dependency> <!-- 引入log4j2依赖 -->
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-log4j2</artifactId>
  </dependency>


配置trace:


使用apm-toolkit-trace输出traceid信息,并修改log4j2.xml配置日志格式。这样会将traceid信息写入日志,用于后续的日志采集和集中分析。


    <Properties>
        <!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符 %logger{36} 表示 Logger 名字最长36个字符-->
        <!--1.文件输出格式-->
        <property name="file_pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%traceId] [%thread] [%-5level]  %msg %l%n" />
        <!--2.控制台显示日志格式-->
        <!--[%traceId]:追踪id-->
        <!--[%sw_ctx]:打印为[$serviceName,$instanceName,$traceId,$traceSegmentId,$spanId]:服务名,实例名,追踪id,追踪片段id,跨度id-->
        <property name="console_pattern" value="%red{%d{yyyy-MM-dd HH:mm:ss}} [%traceId] %green{[%thread]} %magenta{[%-5level]} %cyan{%msg} %l%n"/>
        <!--3.skyWalking收集格式-->
        <property name="skyWalking_pattern" value="%msg %l%n"/>
        <!-- 定义日志存储的路径 -->
        <property name="FILE_PATH" value="./log/spring-skywalking/" />
        <property name="FILE_NAME" value="spring-skywalking" />
    </Properties>


控制程序如下:


package com.tango.skywalking_mysql.controller;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


import com.tango.skywalking_mysql.SkywalkingMysqlApplication;


import org.apache.logging.log4j.LogManager;  
import org.apache.logging.log4j.Logger;  


@RestController
@RequestMapping("/demo")
public class DemoController {


    private static final Logger logger = LogManager.getLogger(SkywalkingMysqlApplication.class); 
    @Autowired
    private JdbcTemplate template;


    @GetMapping("/mysql")
    public String mysql() {
      String result="";
      try {
        this.selectById(1);
        System.out.println("skywalking-test!");
        logger.info("skywalking-test!");
        result="MySQL查询正常";
      } catch(Exception e) {
        System.out.println(e);
        logger.error(e);
        result="MySQL查询异常";
      }
      
        return result;
    }


    public Object selectById(Integer id) {
        return template.queryForObject("SELECT id, username, password FROM sw_tb WHERE id = ?",new BeanPropertyRowMapper<>(Object.class), id);
    }
}


在IDE配置中添加如下选项,配置Skywalking agent和服务的地址。


-javaagent:D:\Skywalking-demo\skywalking-agent\skywalking-agent.jar
-Dskywalking.agent.service_name=skywalking-demo-service
-Dskywalking.collector.backend_service=192.168.112.121:11800



3)运行SpringBoot服务程序


运行应用后输出以下信息,表示agent启动成功。


INFO 2023-11-04 17:11:44.918 main SkyWalkingAgent : Skywalking agent begin to install transformer ... 
Starting application skywalking_mysql
[31m2023-11-04 17:11:52[m [TID: N/A] [32m[main][m [35m[INFO ][m [36mStarting application skywalking_mysql[m com.tango.skywalking_mysql.SkywalkingMysqlApplication.main(SkywalkingMysqlApplication.java:13)


同时能够查看到日志中的traceid信息:


[31m2023-11-04 17:17:43[m [TID: e6978740bf3e41bfa6a53760e2d64b8a.44.16988302617370001] [32m[http-nio-18079-exec-1][m [35m[INFO ][m [36mskywalking-test![m com.tango.skywalking_mysql.controller.DemoController.mysql(DemoController.java:29)
skywalking-test!
[31m2023-11-04 17:20:39[m [TID: e6978740bf3e41bfa6a53760e2d64b8a.47.16988304392400001] [32m[http-nio-18079-exec-4][m [35m[INFO ][m [36mskywalking-test![m com.tango.skywalking_mysql.controller.DemoController.mysql(DemoController.java:29)
skywalking-test!


查看服务端的11800端口,已经有服务。


[root@tango-DB01 config]# netstat -an|grep 11800
tcp6       0      0 :::11800                :::*                    LISTEN     
tcp6       0      0 192.168.112.121:11800   192.168.112.1:49590     ESTABLISHED


访问SpringBoot应用服务:


每查询一次发起一笔业务访问:http://192.168.112.1:18079/demo/mysql


4)登录Skywalking监控服务运行情况


在Skywalking界面看到新的Service:skywalking-demo-service



查看服务的运行性能指标情况:



查看服务的拓扑结构,这是一个访问mysql数据库的应用。



查看trace信息:



查看具体的SQL语句执行情况:



2.Python应用集成Skywalking监控


1)Python程序中Agent配置


在Python程序中引入Skywalking Agent:


from skywalking import agent,config


#配置OAP服务信息
config.init(agent_collector_backend_services='192.168.112.121:11800', agent_name='skywalking-demo-python')
agent.start()


2)运行Python程序,在Skywalking监控服务运行情况


拓扑图如下所示,包括服务和mysql数据库:



查看Trace信息:



查看具体执行的SQL信息:



3)代码实现


完整代码实现如下:


# -*- coding: utf-8 -*-
import pymysql
import sys
import time
import codecs
import logging
import base64




from skywalking import agent,config 
# 配置logging模块  
logging.basicConfig(filename='test.log', level=logging.INFO)  


def getInfo(sql):
  ip="192.168.112.121"
  port=3306
  user="root"
  pwd=base64.decodebytes(b"MTIzNDU2Cg==").strip().decode('utf-8')
  dbname="sw_mysql"
  info = []
  conn = pymysql.connect(host=ip,port=port,user=user,passwd=pwd,database=dbname,charset='utf8')
  cursor = conn.cursor()
  try:
    cursor.execute(sql)
    info = cursor.fetchall()
  except Exception as e:
    print(e)
  conn.commit()
  cursor.close()
  conn.close()
  return info


if __name__ == '__main__':
    if sys.version[0] == "2":
        reload(sys)
        sys.setdefaultcoding("utf8")
    
    config.init(agent_collector_backend_services='192.168.112.121:11800', agent_name='skywalking-demo-python')
    agent.start()
    
    exec_sql = "select id,username,password from sw_mysql.sw_tb"
    
    while True:
        get_info = getInfo(exec_sql)
        
        if len(get_info) > 0:
            print(get_info[0])
            print("Success!")
        else:
            print("Error!")        
        time.sleep(5)
    agent.stop()


以上是基于Skywalking的全链路跟踪的简单指标采集实现。Skywalking功能强大,还具备拓扑关联分析、分布式跟踪和上下文传播、告警等功能,值得深入研究。


>>>>参考资料

  • https://github.com/apache/skywalking
  • https://github.com/SkyAPM/document-cn-translation-of-skywalking
  • https://skywalking.apache.org/docs/skywalking-python
  • https://blog.csdn.net/weixin_42073629/article/details/106775584


作者丨大唐小少

来源丨公众号:牧羊人的方向(ID:solihawk1024)

dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码