SkyWalking入门之Agent原理初步分析

news2024/11/14 3:01:31

一、简介

        当前稍微上点体量的互联网公司已经逐渐采用微服务的开发模式,将之前早期的单体架构系统拆分为很多的子系统,子系统封装为微服务,彼此间通过HTTP协议RESET API的方式进行相互调用或者gRPC协议进行数据协作。

        早期微服务只有几个的情况下,我们遇到问题可以直接简单、快速地通过采集日志进行分析,是A服务存在问题还是B服务存在问题,可以快速恢复服务。但是,如果微服务数量已经到达了几十个、甚至上百个,这些微服务之间的调用关系会变得错综复杂。如果某个API接口的业务逻辑很复杂、调用链路长,涉及的微服务较多,那么一旦其中一环出现问题,想要快速定位问题和解决问题,如果还是按照早期一一查看日志的方式进行排查,无疑对运维和开发人员是一场噩梦....., 等把问题定位出来再恢复,影响至少都是几个小时,几个小时对于大型互联网企业的损失不言而喻,可能今年部门年终奖都得凉凉~

        所以作为开发以及运维团队, 我们急需一套APM(应用性能管理(Application Performance Management))系统,将我们业务开发与运维制定规范嵌入APM系统,通过可视化UI面板+告警就可以很快速地通过例如服务调用链的拓扑图进行问题定位,最后解决问题,实现服务的短时间恢复。

        APM系统开源的其实有很多产品,例如韩国主导的Pinpoint、大众点评的CAT、推特的ZipKin、CNCF的Jaeger以及本文重点介绍的Apache SkyWalking. 感兴趣的同学都可以一一了解和使用。

        APM重点关注三个指标或者说三个维度数据: 1、metrics  2、logging  3、tracing

        metrics:  服务指标, 例如Prometheus暴露出来的metrics,我们可以知道服务运行状态、报错数量、异常数量等等

        logging:  日志采集,这个也是APM中重要的维度信息,因为通过metrics我们只是知道某些服务出现了问题,但是具体问题详情,需要靠日志进一步分析具体原因

        tracing:  调用链追踪,我们可以通过将这些服务之间的调用信息记录下来,最终形成调用链有向无循环图,方便我们查看是哪个链路上出现了问题以及也可以看到链路的性能情况

        Aapache SkyWakling目前在tracing方面关注度和擅长度较高,其他2个维度也有在慢慢做起来。

  二、SkyWalking

        SkyWalking 是基于 Apache 开源生态的分布式应用性能监控系统。它提供了面向云原生架构的 APM(Application Performance Management)解决方案,支持多种语言的应用和多种方式的部署,具有以下特点:

                分布式追踪:支持多种语言、多种协议的应用追踪,可获取全链路的请求数据。
                应用拓扑图:根据追踪数据自动生成应用程序拓扑,便于系统管理员快速定位故障。
                监控告警:具有丰富的监控指标和告警规则,支持第三方告警接口。
                插件化体系:可通过插件模块实现对不同类型服务的监控和数据收集。


        SkyWalking 的设计理念是高度灵活和可扩展的,可以自定义仪表板、告警规则、数据接口等。它可以帮助用户诊断系统性能问题、提高系统的可用性和吞吐量,在企业级系统的性能管理、调优和问题排查中发挥重要作用。

        SkyWalking 由中国华为和 Apache 开源社区共同开发,目前已成为 Apache 基金会下的顶级项目之一,作者吴晟。

        SkyWalking 于2017年11月进入 Apache 孵化器(Apache Incubator),成为 Apache 软件基金会的一个开源项目。经过一段时间的发展和孵化,SkyWalking 在2019年2月毕业,成为 Apache 软件基金会的顶级项目。成为顶级项目意味着 SkyWalking 已经发展成熟并受到广泛认可,具有良好的社区治理和持续的技术发展。同时,作为顶级项目,SkyWalking 继续在 Apache 的指导下发展,并得到了更多的关注和支持。

        项目Github地址: https://github.com/apache/skywalking

        官网地址: https://skywalking.apache.org/

       SkyWalking的主要特点和优点,我认为相对其他开源项目是:

       SkyWalking Agent采集调用链信息的客户端对业务是无感的、非侵入式的。 那也就意味着,你的项目代码无须修改一行代码就能加入SkyWalking的采集、监控、调用链追踪。

        这个特点真的很牛逼🐂,那也就意味着你原来的项目接入SkyWalking很轻松、门槛很低。 底层大概得原理是, JAVA本身就提供JAVAAGENT的机制以及采用动态修改字节码技术的方式,Agent在JVM底层帮我们把调用链采集上报的过程透明化了,开发人员作为业务层写代码是无感的。

        我们先记住这个大概的原理,下面我会在入门案例先也会简单做个初步分析和验证。

  三、SpringBoot+SkyWalking+PHP简单入门与分析

1、安装SkyWalking的OAP系统安装包

下载:  SkyWalking的OAP压缩包

下载页面: Downloads | Apache SkyWalking

2、运行OAP

1、解压 apache-skywalking-apm-9.3.0.tar.gz

tar -zxvf apache-skywalking-apm-9.3.0.tar.gz

2、进入apache-skywalking-apm-9.3.0

进入bin目录有启动脚本,我们先启动oapService.sh(服务端)、再启动webappService.sh(UI客户端)

启动完毕,执行jps程序查看进程有没有正常拉起来:

正常会出现上面两个进程,如果没有拉起来在logs目录可以查看错误信息进行排查:

3、访问SkyWalking 8080 UI界面

http://$ip:8080

        目前刚开始服务列表这些是空的, SkyWalking支持多种数据存储介质例如默认内存、MySQL、ES等等,一般生产环境使用ES集群进行存储,我们测试直接不用改什么配置,默认采用内存的形式。那就意味着如果服务重启,则之前的测试数据会丢失

4、Trace调用链追踪的基本原理介绍

        Trace调用链追踪,例如A->B->C->D  存在4个微服务的调用链关系。 假设我们通过HTTP协议进行交互,该怎么把调用链信息拿到呢? 

        Google的Dapper论文中提到了一种分布式调用链追踪的实现方式, 市面上的APM系统调用链追踪大部分是参考这篇论文实现的。 每个调用链可以使用TraceId进行标识,每个服务被调用称为一个Span会伴随一个SpanId, 每当父服务调用子服务的时候会将TraceId以及父层的SpanId往子服务传递,子服务收到后,记录父层传递的SpanId作为自己Span的父id,  最后2个服务都会把调用信息上报到APM的服务端,例如SkyWalking的某个端口.

        最后SkyWalking因为采集到了这些Span的信息,Span信息记录着父子关系、调用时间信息、TraceId等等,经过UI绘制,就能把这一次调用的TraceId的所有Span进行串联,最终形成调用链拓扑图。

        接下来我们部署一个SpringBoot项目和一个PHP项目,很简单的链路,SpringBoot调用PHP项目的HTTP接口,我们来看下SkyWalking的UI界面以及分析原理验证。

5、部署一个PHP项目

代码很简单,一个PHP文件即可, index.php。大家自行安装php环境

<?php

$headers = $_SERVER;
$http_sw8 = !empty($headers['HTTP_SW8']) ? $headers['HTTP_SW8'] : '';
// 解析HTTP请求头, SkyWalking在SpringBoot底层字节码做了手脚, 往HTTP Header注入了这么几个Header
// HTTP_SW8_CORRELATION
// HTTP_SW8_X
// HTTP_SW8  一个以 - 分隔的字符串, 每个字符串是base64编码,所以需要解码就能看到明文信息
$params = explode('-', $http_sw8);

$vals = [];
foreach ($params as $param) {
    if (strlen($param) <=1 ) {
        $vals[] = $param;
    }else{
        $decode_val = base64_decode($param);
        if($decode_val === false) {
            $vals[] = $param;
        }else{
            $vals[] = $decode_val;
        }
    }
}
$data = [
    'raw_header' => $headers,
    'http_sw8_decode' => [
        'HTTP_SW8_CORRELATION' => !empty($headers['HTTP_SW8_CORRELATION']) ? $headers['HTTP_SW8_CORRELATION'] : '',
        'HTTP_SW8_X' => !empty($headers['HTTP_SW8_X']) ? $headers['HTTP_SW8_X'] : '',
        'HTTP_SW8' => $vals
    ]
];

header("Content-type: application/json;charset=utf-8");
echo json_encode($data);

很简单,大家看下基本就知道,提供的这个index.php做了一件事就是从HTTP请求头拿到一些信息,针对这些信息做一个分析,最终返回给客户端仅此而已。

运行服务: 

php -S 0.0.0.0:8090 index.php

浏览器访问服务看下是否正常: http://$ip:8090 

6、部署一个SpringBoot项目

写了一个简单的Controller, 就是调用PHP项目的index.php URL,拿到数据后返回给用户显示, controller代码如下:

package com.example.controllers;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping(path = "/user")
public class User {

    @GetMapping(value = "/list")
    public Map<String, Object> list() throws JsonProcessingException {
        RestTemplate restTemplate = new RestTemplate();
        String url = "http://192.168.30.15:8090/index.php";
        ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
        String responseBody = response.getBody();
        Map<String, Object> m = new HashMap<>();
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, Object> resp= objectMapper.readValue(responseBody, new TypeReference<HashMap<String, Object>>() {});
        m.put("resp", resp);
        return m;
    }
}

    代码逻辑很简单

7、运行Springboot+SkyWalking Agent

    SpringBoot项目倒是部署好了,但是如果只是简单运行,那肯定和我们的SkyWalking还没进行结合。那怎么结合起来呢?  那就是通过运行的时候,设置参数,和SkyWalking Agent进行结合。

     我们上面提到过,使用SkyWalking Agent最大的好处就是【无代码侵入】,那也就是意味着我们的源代码无须做任何变更, 只需要在运行java -jar JAR包的时候额外加入一下参数即可:

        下载Agent:

        

        解压skywalking-agent.jar:

        找到skywalking-agent.jar所处的绝对路径, 记录一下.

        运行SpringBoot项目需要加入参数如下:

-javaagent:/root/apache-skywalking-java-agent/skywalking-agent/skywalking-agent.jar
-DSW_AGENT_NAME=sw-springboot
-DSW_AGENT_COLLECTOR_BACKEND_SERVICES=192.168.30.15:11800


-javaagent:  这是 java运行命令可以添加的选项参数, :后面是agent jar包的绝对路径地址
-DSW_AGENT_NAME:  这是传递参数SW_AGENT_NAME, 可以理解为这个微服务的名称
-DSW_AGENT_COLLECTOR_BACKEND_SERVICES: 这个就是要将调用链信息上报的SkyWalking的服务端地址+端口

        运行完毕之后,服务正常启动, 和正常的SpringBoot除了加上面的参数,服务启动没任何区别, 我们多次访问部署SpringBoot服务IP:8080端口:

     可以看到 SpringBoot调用PHP的Web接口后返回了数据进行展示

8、查看SkyWakling的UI后台-服务拓扑图和调用链信息

服务列表信息已经有了数据:

查看调用service调用拓扑图:

查看Span调用链详细信息:

9、初步验证和分析调用链信息采集Agent原理

1、疑问

        通过上面我们就能看到调用链信息,真的好神奇,没改一行业务的Java代码就能做到查询调用链的拓扑图。这是到底是怎么实现的?

 2、非侵入式的原理

       我们没改一行代码,只是注入了javaagent和相关SW的参数,这个javaagent就是关键点。 Java本身就支持这种agent技术,可以在main()函数之前做一些钩子操作,例如对要加载到JVM的class字节码可以进行增强或者说修改吧,没错,就是对你的代码进行动态修改。   字节码都能修改了,Agent代码要做个线程或者进程把这些采集的数据进行上报那不是小case么.

        例如可以在某个class的方法前记录调用使用,在方法后记录时间,两者一减,你的调用时间就出来了,然后再进行上报等等,我理解有点像反射技术哈,不用反射的原因我看资料反馈的是性能较差。

3、Trace的上下文(Span信息)是怎么从父层传递到子层的?

        哈哈,这里就有点意思了。 非侵入式将信息上报给SkyWalking可以理解,那一个SpringBoot项目调用PHP项目,你咋知道这两个Span有啥关系? SpringBoot是怎么传递之前说的TraceId、SpanId传递到PHP服务的的? 毕竟这是在进程、跨服务器通信。

        答案:  就是在传输协议HTTP上做了手脚。  我们之前说了Agent有动态修改字节码的能力,那这个太简单了,我直接在HTTP协议的底层类进行拦截,一旦你进行HTTP请求,我就在你的请求之前,请求头Header注入Span信息,如果对端服务(下游服务)也是用了SkyWalking的Agent,那么它也会从HTTP请求的Header中获取Span信息,从而进行处理,最后上报。

        看下刚才调用SpringBoot的响应内容:

        PHP解析HTTP Header有个规则,都以HTTP_开头, 小写转大写,_下划线转-:

        所以Java SpringBoot那边在header里面传递的Header: HTTP_SW8, 实际是传的sw8作为key

4、查看Agent源码,验证下是不是上面说的在HTTP协议做的手脚

       项目地址:  https://github.com/apache/skywalking-java

        全文搜索一下关键词: sw8可以看到定义了这个header信息的类:

        

      发现了关键字样,看起来是SW8携带数据Item class的定义.  OK, 那我们再搜索关键词: HttpURLConnection, 为啥搜索这个词?  你上层HTTP封装再牛逼,也逃不了调用底层HTTP请求吧?

        发现了关键代码, 嘿嘿:

     

      咱们对这段代码不太懂是吧? ChatGPT给我上, 看下GPT是怎么理解这段代码的:

    嗖嘎,和猜想的一模一样, Agent就是在底层HTTP请求的时候搞了钩子手脚,每次HTTP请求都是给我把SkyWalking的header加上,方便给下游服务传递Span和Trace上下文,搞定收工

  四、总结

     经过上面的入门和简单分析验证:

     1、我们知道了原来SkyWalking是通过动态修改字节码的方式来达到无侵入式的调用链追踪上报

     2、并且通过分析各种协议例如GRPC、HTTP等常见协议, 通过底层设置钩子,如一旦发现HTTP请求,在Header上注入调用链Span上下文信息到下游服务,最后将这些Span信息上报到SkyWalking的server端,最后经过SkyWalking整理,通过UI界面就能查看到service的调用链拓扑图。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三种方式部署单机版Minio,10行命令干就完了~

必要步骤&#xff1a;安装MinIO 拉取MinIO镜像 docker pull quay.io/minio/minio 创建文件挂载点 mkdir /home/docker/MinIO/data &#xff08;文件挂载点映射&#xff0c;默认是/mydata/minio/data&#xff0c;修改为/home/docker/MinIO&#xff0c;文件存储位置自行修改&…

随笔-嗨,中奖了

好久没有动笔了&#xff0c;都懒惰了。 前段时间&#xff0c;老妹凑着暑假带着双胞胎的一个和老妈来了北京&#xff0c;听着小家伙叫舅舅&#xff0c;还是挺稀奇的。周末带着他们去了北戴河&#xff0c;全家人都是第一次见大海&#xff0c;感觉&#xff0c;&#xff0c;&#…

qiankun 乾坤主应用访问微应用css静态图片资源报404

发现static前没有加我指定的前缀 只有加了后才会出来 解决方案: env定义前缀 .env.development文件中 # static前缀 VUE_APP_PUBLIC_PREFIX"" .env.production文件中 # static前缀 VUE_APP_PUBLIC_PREFIX"/szgl" settings文件是封了一下src\settings…

测试平台前端部署

这里写目录标题 一、前端代码打包1、打包命令2、打包完成后,将dist文件夹拷贝到nginx文件夹中3、重新编写default.conf4、将之前启动的容器进行停止并且删除,再重新创建容器5、制作Dockerfile二、编写Dockerfile一、前端代码打包 1、打包命令 npm run build2、打包完成后,…

Kubernetes学习篇之组件

Kubernetes学习篇之组件 文章目录 Kubernetes学习篇之组件前言概述控制平面组件(Control Plane Components)kube-apiserveretcdkube-schedulerkube-controller-managercloud-controller-manager Node 组件kubeletkube-proxy容器运行时(Container Runtime) 插件(Addons)DNSWeb界…

驱动开发,IO多路复用实现过程,epoll方式

1.框架图 被称为当前时代最好用的io多路复用方式&#xff1b; 核心操作&#xff1a;一棵树&#xff08;红黑树&#xff09;、一张表&#xff08;内核链表&#xff09;以及三个接口&#xff1b; 思想&#xff1a;&#xff08;fd代表文件描述符&#xff09; epoll要把检测的事件…

Ubuntu安装深度学习环境相关(yolov8-python部署)

Ubuntu安装深度学习环境相关(yolov8-python部署) 本文将从如下几个方面总结相关的工作过程&#xff1a; Ubuntu系统安装(联想小新pro16) 2.显卡驱动安装3.测试深度学习模型 1. Ubunut 系统安装 之前在台式机上安装过Ubuntu&#xff0c;以为再在笔记本上安装会是小菜一碟&…

Linux内核源码分析 (B.x)Linux内存布局

一、32位系统的内存布局 为什么要将进程地址空间划分成内核空间和用户空间&#xff1f; 这个和处理器的体系结构有关。比如X86分为ring0~ring3级别&#xff0c;ring0给内核空间使用&#xff0c;ring3给用户空间使用&#xff1b;同样的&#xff0c;ARMv7也是如此&#xff0c;svc…

openGauss学习笔记-70 openGauss 数据库管理-创建和管理普通表-查看表数据

文章目录 openGauss学习笔记-70 openGauss 数据库管理-创建和管理普通表-查看表数据70.1 查询数据库所有表的信息70.2 查询表的属性70.3 查询表的数据量70.4 查询表的所有数据70.5 查询字段的数据70.6 过滤字段的重复数据70.7 查询字段为某某的所有数据70.8 按照字段进行排序 o…

C++之unordered_map,unordered_set模拟实现

unordered_map&#xff0c;unordered_set模拟实现 哈希表源代码哈希表模板参数的控制仿函数增加正向迭代器实现*运算符重载->运算符重载运算符重载! 和 运算符重载begin()与end()实现 unordered_set实现unordered_map实现map/set 与 unordered_map/unordered_set对比哈希表…

python 自(3)1使用urlencode多个参数请求使用 2百度翻译post请求post无法添加路径 3百度翻译全部数据获取 4豆瓣get请

1 使用urlencode 多个参数请求使用 # 使用urlencode 多个参数请求使用 # https://www.baidu.com/s?wd周杰伦&sex男 网页 import urllib.request import urllib.parsebase_url https://www.baidu.com/s?data {wd: 周杰伦,sex: 男,sing:歌曲 }new_data urllib.par…

牛客: BM3 链表中的节点每k个一组翻转

牛客: BM3 链表中的节点每k个一组翻转 文章目录 牛客: BM3 链表中的节点每k个一组翻转题目描述题解思路题解代码 题目描述 题解思路 用一个[]int保存一组节点的val,一个快节点先遍历k个节点将节点的val顺序保存在[]int中,然后慢节点再遍历k个节点,逆序将[]int的val设置给节点的…

北斗导航 | 基于奇异值分解的接收机自主完好性监测算法

===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== 基于奇异值分解的接收机自主完好性监测算法 摘 要:基于最小二乘法残差…

Python Opencv实践 - 视频文件操作

参考资料&#xff1a; 视频处理VideoCapture类---OpenCV-Python开发指南&#xff08;38&#xff09;_python opencv videocapture_李元静的博客-CSDN博客 OpenCV VideoCapture.get()参数详解 - 简书FOURCC四字符码对照表_4fvcc_Kellybook的博客-CSDN博客 import cv2 as cv im…

【计算机网络】传输层协议——TCP(下)

文章目录 1. 三次握手三次握手的本质是建立链接&#xff0c;什么是链接&#xff1f;整体过程三次握手过程中报文丢失问题为什么2次握手不可以&#xff1f;为什么要三次握手&#xff1f; 2. 四次挥手整体过程为什么要等待2MSL 3. 流量控制4. 滑动窗口共识滑动窗口的一般情况理解…

星际争霸之小霸王之小蜜蜂(十三)--接着奏乐接着舞

系列文章目录 星际争霸之小霸王之小蜜蜂&#xff08;十二&#xff09;--猫有九条命 星际争霸之小霸王之小蜜蜂&#xff08;十一&#xff09;--杀杀杀 星际争霸之小霸王之小蜜蜂&#xff08;十&#xff09;--鼠道 星际争霸之小霸王之小蜜蜂&#xff08;九&#xff09;--狂鼠之…

国家网络安全周 | 天空卫士荣获“2023网络安全优秀创新成果大赛优胜奖”

9月11日上午&#xff0c;四川省2023年国家网络安全宣传周在泸州开幕。在开幕式上&#xff0c;为2023年网络安全优秀创新成果大赛——成都分站赛暨四川省“熊猫杯”网络安全优秀作品大赛中获奖企业颁奖&#xff0c;天空卫士银行数据安全方案获得优秀解决方案奖。 本次比赛由四川…

免费好用的天翎bpm流程引擎,实现生产管理系统

1.什么是生产管理系统 针对中小型制造企业的生产应用而开发&#xff0c;能够帮助企业建立一个规范准确即时的生产数据库&#xff0c;同时实现轻松、规范、细致的生产业务、库存业务一体化管理工作。提高管理效率&#xff08;企业管理的科学方法&#xff09;、掌握及时、准确、全…

Mysql高级——索引创建和使用

索引的创建 1. 索引的声明与使用 1.1 索引的分类 MySQL的索引包括普通索引、唯一性索引、全文索引、单列索引、多列索引和空间索引等。 从功能逻辑上说&#xff0c;索引主要有 4 种&#xff0c;分别是普通索引、唯一索引、主键索引、全文索引。 按照物理实现方式&#xff…

Spring之IOC容器(依赖注入)基本介绍基本配置多模块化

标题一&#xff1a;什么是spring&#xff0c;它能够做什么? Spring是一个开源框架&#xff0c;它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而&#xff0c;Spring的用途不仅限于服务器端的…