基于Skywalking实现全链路追踪的万字攻略(有手就能操作版) | 您所在的位置:网站首页 › 项目跟踪与监控的主要方式有 › 基于Skywalking实现全链路追踪的万字攻略(有手就能操作版) |
作者丨大唐小少 来源丨公众号:牧羊人的方向(ID:solihawk1024) 本文将重点介绍基于Skywalking的全链路实现,包括Skywalking的整体架构和基本概念原理、Skywalking环境部署、SpringBoot和Python集成Skywalking监控实现等。 一、Skywalking基本介绍 1.Skywalking整体架构 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指标流如下: 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生成序列,格式如下所示: S e r v i c e I n s t a n c e I d . {ServiceInstanceId}. 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 类型):它指向父TraceSegment relatedGlobalTraces(DistributedTraceIds类型):记录当前TraceSegment所属Trace的Trace ID。 spans(List类型):当前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信息。 当TracingContext通过stopSpan()方法关闭最后一个Span时,会调用finish()方法关闭相应的TraceSegment,与此同时,还会通知所有监听TracingContext关闭事件的监听器TracingContextListener。TraceSegmentServiceClient主要功能就是在TraceSegment结束时对其进行收集,并发送到后端的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.ymlserverPort: ${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 -pmysql> 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的依赖包: org.apache.skywalking apm-toolkit-trace 8.3.0 org.apache.skywalking apm-toolkit-log4j-2.x 8.3.0
org.springframework.boot spring-boot-starter-log4j2 配置trace: 使用apm-toolkit-trace输出traceid信息,并修改log4j2.xml配置日志格式。这样会将traceid信息写入日志,用于后续的日志采集和集中分析。 控制程序如下: 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 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=.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功能强大,还具备拓扑关联分析、分布式跟踪和上下文传播、告警等功能,值得深入研究。 |
CopyRight 2018-2019 实验室设备网 版权所有 |