热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Jaeger链路追踪在项目中的应用

前言随着公司内部项目交互越来越多,一个请求的调用链路也会变长,如何快速定位接口问题也成为了项目中需要考虑的因素,链路追踪工具就是为了解决这个问题而生。常见的链路追踪工具:APM这是






前言

随着公司内部项目交互越来越多,一个请求的调用链路也会变长,如何快速定位接口问题也成为了项目中需要考虑的因素,链路追踪工具就是为了解决这个问题而生。常见的链路追踪工具:



  • APM
    这是Elasticsearch内置的一个链路追踪工具,支持主流的语言,如果你的应用是fpm的架构,并且想要最小的改动在项目中接入链路的话,这是一个不错的选择,只需要加一个扩展就行了。但由于我们的项目使用的大多数都是Hyperf框架,APM扩展会和Swoole冲突,所以放弃。


  • Jaeger
    这是Uber推出的一款比较成熟的链路追踪工具,关于它的介绍自己百度一下就行了,我们这里就选用的是jaegerHyperf框架已经有了jaeger的包,可以直接使用,这里主要是记录如何在传统框架接入jaeger


效果图:


一、接入


网上几乎搜不到php接入jaeger的有用的文章,全是长篇大论的理论知识,但对于php开发人员来讲,他只想直接精通,最好把代码扔脸上,所以,我就是来干这个事情的。


明确一点,一个请求有一个rootSpan(根),在上图中就是最开始的那个request,后续的所有需要记录的操作,比如dbredis都是requestchildSpan,他们是request的子级,而dbredis是同级fllowSpan,他们是兄弟关系,先用最简单的示例看一下(startActiveSpan这种方式不太好直接应用到服务中,这里只用作演示):



  • 安装包
    composer require jonahgeorge/jaeger-client-php


  • 测试代码

    // 初始化全局配置(可以放到框架启动的时候执行)
    $config = new Config(
    [
    'sampler' => [
    'type' => Jaeger\SAMPLER_TYPE_CONST,
    'param' => true,
    ],
    'logging' => true,
    // tags记录需要记录的参数有哪些,自定义
    "tags" => [
    'http.url' => 'http.url',
    'http.method' => 'http.method',
    'http.status_code' => 'http.status_code',
    'db.query' => 'db.query',
    'db.statement' => 'db.statement',
    'db.query_time' => 'db.query_time',
    'path' => 'request.path',
    'method' => 'request.method',
    'header' => 'request.header',
    'status_code' => 'response.status_code',
    ],
    // jaeger的地址,这个需要你提交搭建好jaeger服务
    "local_agent" => [
    "reporting_host" => "web-jaeger.your-domain.com",
    "reporting_port" => 5775
    ],
    // 使用udp协议传输数据
    'dispatch_mode' => Config::ZIPKIN_OVER_COMPACT_UDP,
    ],
    // 服务的名字,比如订单中心
    'order-center'
    );
    // 初始化配置
    $config->initializeTracer();
    // 全局的trancer对象,这是一个单例对象
    $tracer = GlobalTracer::get();
    // 创建一个根时间分段,startActiveSpan第一个参数是自定义当前操作的名称,这里定义成
    // request,代表一个请求,注意scope的代码结构,是一个包含的关系
    // 每一个span对应一个start和一个close,它们是成对出现。
    $scope = $tracer->startActiveSpan('request', []);
    // tag记录一些短参数,比如header头,请求方法等
    $scope->getSpan()->setTag("tag1", "value1");
    $scope->getSpan()->setTag("tag2", "value2");
    $scope->getSpan()->setTag("tag3", "value2");
    // log记录一些大的参数,比如请求的json
    $scope->getSpan()->log([
    "key1" => "value1",
    "key2" => 2,
    "key3" => true
    ]);
    // 创建$scope子分段
    $nestedSpanScope1= $tracer->startActiveSpan("db.query");
    $nestedSpanScope1->getSpan()->setTag("tag1", "value1");
    $nestedSpanScope1->getSpan()->setTag("tag2", "value2");
    $nestedSpanScope1->getSpan()->setTag("tag3", "value2");
    $nestedSpanScope1->getSpan()->log([
    "key1" => "value1",
    "key2" => 2,
    "key3" => true
    ]);
    // 创建$nestedSpanScope1的子分段
    $nestedSpanScope11 = $tracer->startActiveSpan("redis.get");
    $nestedSpanScope11->getSpan()->setTag("tag1", "value1");
    $nestedSpanScope11->getSpan()->setTag("tag2", "value2");
    $nestedSpanScope11->getSpan()->setTag("tag3", "value2");
    $nestedSpanScope11->getSpan()->log([
    "key1" => "value1",
    "key2" => 2,
    "key3" => true
    ]);
    $nestedSpanScope11->close();
    $nestedSpanScope12= $tracer->startActiveSpan("oa");
    // 假设oa接口返回的数据是这样的
    $oaResponseData = [];
    $nestedSpanScope12->getSpan()->setTag("http.url", "xxx.oa.com");
    $nestedSpanScope12->getSpan()->setTag("http.method", "POST");
    $nestedSpanScope12->getSpan()->setTag("http.status_code", 200);
    $nestedSpanScope12->getSpan()->log($oaResponseData);
    $nestedSpanScope12->close();
    $nestedSpanScope1->close();
    // 创建$scope的子分段
    $nestedSpanScope2 = $tracer->startActiveSpan("db.insert");
    $nestedSpanScope2->getSpan()->setTag("tag1", "value1");
    $nestedSpanScope2->getSpan()->setTag("tag2", "value2");
    $nestedSpanScope2->getSpan()->setTag("tag3", "value2");
    $nestedSpanScope2->getSpan()->log([
    "key1" => "value1",
    "key2" => 2,
    "key3" => true
    ]);
    // 创建$nestedSpanScope2的子分段
    $nestedSpanScope21 = $tracer->startActiveSpan("redis.hget");
    $nestedSpanScope21->getSpan()->setTag("tag1", "value1");
    $nestedSpanScope21->getSpan()->setTag("tag2", "value2");
    $nestedSpanScope21->getSpan()->setTag("tag3", "value2");
    $nestedSpanScope21->getSpan()->log([
    "key1" => "value1",
    "key2" => 2,
    "key3" => true
    ]);
    $nestedSpanScope21->close();
    $nestedSpanScope2->close();
    $scope->close();
    // 一个请求最终只有一个flush,表示把之前记录的span关系全部写入jaeger服务中
    $tracer->flush();

  • 层级结构

    order-center request
    |--- order-center db.query
    |--- order-center redis.get
    order-center db.insert
    |--- order-center redis.hge


二、项目应用

先不写了,过会儿再写




laravel
分布式事务
swoole
hyperf
php


推荐阅读
  • Python 数据可视化实战指南
    本文详细介绍如何使用 Python 进行数据可视化,涵盖从环境搭建到具体实例的全过程。 ... [详细]
  • 从0到1搭建大数据平台
    从0到1搭建大数据平台 ... [详细]
  • 秒建一个后台管理系统?用这5个开源免费的Java项目就够了
    秒建一个后台管理系统?用这5个开源免费的Java项目就够了 ... [详细]
  • ### 优化后的摘要本学习指南旨在帮助读者全面掌握 Bootstrap 前端框架的核心知识点与实战技巧。内容涵盖基础入门、核心功能和高级应用。第一章通过一个简单的“Hello World”示例,介绍 Bootstrap 的基本用法和快速上手方法。第二章深入探讨 Bootstrap 与 JSP 集成的细节,揭示两者结合的优势和应用场景。第三章则进一步讲解 Bootstrap 的高级特性,如响应式设计和组件定制,为开发者提供全方位的技术支持。 ... [详细]
  • 本文深入探讨了NoSQL数据库的四大主要类型:键值对存储、文档存储、列式存储和图数据库。NoSQL(Not Only SQL)是指一系列非关系型数据库系统,它们不依赖于固定模式的数据存储方式,能够灵活处理大规模、高并发的数据需求。键值对存储适用于简单的数据结构;文档存储支持复杂的数据对象;列式存储优化了大数据量的读写性能;而图数据库则擅长处理复杂的关系网络。每种类型的NoSQL数据库都有其独特的优势和应用场景,本文将详细分析它们的特点及应用实例。 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 本文详细介绍了在 CentOS 7 系统中配置 fstab 文件以实现开机自动挂载 NFS 共享目录的方法,并解决了常见的配置失败问题。 ... [详细]
  • 在 Ubuntu 中遇到 Samba 服务器故障时,尝试卸载并重新安装 Samba 发现配置文件未重新生成。本文介绍了解决该问题的方法。 ... [详细]
  • 在CentOS 7环境中安装配置Redis及使用Redis Desktop Manager连接时的注意事项与技巧
    在 CentOS 7 环境中安装和配置 Redis 时,需要注意一些关键步骤和最佳实践。本文详细介绍了从安装 Redis 到配置其基本参数的全过程,并提供了使用 Redis Desktop Manager 连接 Redis 服务器的技巧和注意事项。此外,还探讨了如何优化性能和确保数据安全,帮助用户在生产环境中高效地管理和使用 Redis。 ... [详细]
  • 浏览器作为我们日常不可或缺的软件工具,其背后的运作机制却鲜为人知。本文将深入探讨浏览器内核及其版本的演变历程,帮助读者更好地理解这一关键技术组件,揭示其内部运作的奥秘。 ... [详细]
  • 帝国CMS中的信息归档功能详解及其重要性
    本文详细解析了帝国CMS中的信息归档功能,并探讨了其在内容管理中的重要性。通过归档功能,用户可以有效地管理和组织大量内容,提高网站的运行效率和用户体验。此外,文章还介绍了如何利用该功能进行数据备份和恢复,确保网站数据的安全性和完整性。 ... [详细]
  • Spring框架中枚举参数的正确使用方法与技巧
    本文详细阐述了在Spring Boot框架中正确使用枚举参数的方法与技巧,旨在帮助开发者更高效地掌握和应用枚举类型的数据传递,适合对Spring Boot感兴趣的读者深入学习。 ... [详细]
  • 为了在Hadoop 2.7.2中实现对Snappy压缩和解压功能的原生支持,本文详细介绍了如何重新编译Hadoop源代码,并优化其Native编译过程。通过这一优化,可以显著提升数据处理的效率和性能。此外,还探讨了编译过程中可能遇到的问题及其解决方案,为用户提供了一套完整的操作指南。 ... [详细]
  • 在当今的软件开发领域,分布式技术已成为程序员不可或缺的核心技能之一,尤其在面试中更是考察的重点。无论是小微企业还是大型企业,掌握分布式技术对于提升工作效率和解决实际问题都至关重要。本周的Java架构师实战训练营中,我们深入探讨了Kafka这一高效的分布式消息系统,它不仅支持发布订阅模式,还能在高并发场景下保持高性能和高可靠性。通过实际案例和代码演练,学员们对Kafka的应用有了更加深刻的理解。 ... [详细]
  • 本文详细介绍了批处理技术的基本概念及其在实际应用中的重要性。首先,对简单的批处理内部命令进行了概述,重点讲解了Echo命令的功能,包括如何打开或关闭回显功能以及显示消息。如果没有指定任何参数,Echo命令会显示当前的回显设置。此外,文章还探讨了批处理技术在自动化任务执行、系统管理等领域的广泛应用,为读者提供了丰富的实践案例和技术指导。 ... [详细]
author-avatar
江西小毒i哈
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有