Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >PHP 服务实现性能剖析、跟踪和可观察性最佳实践

PHP 服务实现性能剖析、跟踪和可观察性最佳实践

作者头像
Tinywan
发布于 2024-06-18 07:38:48
发布于 2024-06-18 07:38:48
30300
代码可运行
举报
文章被收录于专栏:开源技术小栈开源技术小栈
运行总次数:0
代码可运行

简介

链路追踪Tracing Analysis为分布式应用的开发者提供了完整的调用链路还原、调用请求量统计、链路拓扑、应用依赖分析等工具,可以帮助开发者快速分析和诊断分布式应用架构下的性能瓶颈,提高微服务时代下的开发诊断效率。

官方地址:https://github.com/openzipkin/zipkin

Zipkin运行架构

产品架构(链路追踪)

链路追踪的主要工作流程如下

  1. 客户侧的应用程序通过集成链路追踪的多语言客户端SDK上报服务调用数据。链路追踪支持多种开源社区的SDK,且支持OpenTracing标准。
  2. 数据上报至链路追踪控制台后,链路追踪组件进行实时聚合计算和持久化,形成链路明细、性能总览、实时拓扑等监控数据。您可以据此进行问题排查与诊断。
  3. 调用链数据可对接下游阿里云产品,例如LogSearch、CloudMonitor、MaxCompute等,用于离线分析、报警等场景。

业务场景

随着业务越来越复杂,系统也随之进行各种拆分,特别是随着微服务架构容器技术的兴起,看似简单的一个应用,后台可能有几十个甚至几百个服务在支撑;一个前端的请求可能需要多次的服务调用最后才能完成;当请求变慢或者不可用时,我们无法得知是哪个后台服务引起的,这时就需要解决如何快速定位服务故障点,zipkin分布式跟踪系统就能很好的解决这样的问题。

请求&响应

微服务架构下,一次请求后端会经历多个服务调用(所有请求链有相同的traceId和不同的spanId),都会沿着traceText带到每一个服务中。

数据是如何上报的?

直接上报数据

不通过Agent而直接上报数据的原理(传统框架。PHP-FPM + Nginx模式)

  • ThinkPHP6.0
  • Laravel
  • Yii2.0

通过Agent上报数据

通过Agent上报数据的原理(现代化框架。命令行模式)

  • webman
  • Swoole

安装

通过composer安装

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
composer require openzipkin/zipkin

使用

创建Tracer

Tracer对象可以用来创建Span对象(记录分布式操作时间)。Tracer对象还配置了上报数据的网关地址、本机IP、采样频率等数据,您可以通过调整采样率来减少因上报数据产生的开销。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function create_tracing($endpointName, $ipv4)
{
    $endpoint = Endpoint::create($endpointName, $ipv4, null, 2555);
    /* Do not copy this logger into production.
     * Read https://github.com/Seldaek/monolog/blob/master/doc/01-usage.md#log-levels
     */
    $logger = new \Monolog\Logger('log');
    $logger->pushHandler(new \Monolog\Handler\ErrorLogHandler());
    $reporter = new Zipkin\Reporters\Http(\Zipkin\Reporters\Http\CurlFactory::create());
    $sampler = BinarySampler::createAsAlwaysSample();
    $tracing = TracingBuilder::create()
        ->havingLocalEndpoint($endpoint)
        ->havingSampler($sampler)
        ->havingReporter($reporter)
        ->build();
    return $tracing;
}   

记录请求数据

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$rootSpan = $tracer->newTrace();
$rootSpan->setName('encode');
$rootSpan->start();

try {
  doSomethingExpensive();
} finally {
  $rootSpan->finish();
}

以上代码用于记录请求的根操作,如果需要记录请求的上一步和下一步操作,则需要传入上下文。示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$span = $tracer->newChild($parentSpan->getContext());
$span->setName('encode');
$span->start();
try {
  doSomethingExpensive();
} finally {
  $span->finish();
}

总体流程如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   Client Span                                                Server Span
┌──────────────────┐                                       ┌──────────────────┐
│                  │                                       │                  │
│   TraceContext   │           Http Request Headers        │   TraceContext   │
│ ┌──────────────┐ │          ┌───────────────────┐        │ ┌──────────────┐ │
│ │ TraceId      │ │          │ X-B3-TraceId      │        │ │ TraceId      │ │
│ │              │ │          │                   │        │ │              │ │
│ │ ParentSpanId │ │ Inject   │ X-B3-ParentSpanId │Extract │ │ ParentSpanId │ │
│ │              ├─┼─────────>│                   ├────────┼>│              │ │
│ │ SpanId       │ │          │ X-B3-SpanId       │        │ │ SpanId       │ │
│ │              │ │          │                   │        │ │              │ │
│ │ Sampled      │ │          │ X-B3-Sampled      │        │ │ Sampled      │ │
│ └──────────────┘ │          └───────────────────┘        │ └──────────────┘ │
│                  │                                       │                  │
└──────────────────┘                                       └──────────────────┘

webman应用

1. 开通ARMS

开通ARMS地址 https://arms.console.aliyun.com/ (一般有15天试用)

2. 获得数据上报接入点url

进入 https://tracing.console.aliyun.com/#/globalSetting/cn-hangzhou/process 按照图示获得接入点url地址。

如果你的服务器在阿里云上可以用阿里云vpc网络接入点,本示例用的是阿里云公网接入点

安装

通过composer安装:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
composer require openzipkin/zipkin

使用

1. 编写中间件

链路监控中间件 app\middleware\ArmsMiddleware.php

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?php
/**
 * @desc 全链路监控中间件
 * @author Tinywan(ShaoBo Wan)
 * @date 2021/12/6 14:06
 */
declare(strict_types=1);

namespace app\middleware;

use Monolog\Handler\ErrorLogHandler;
use Monolog\Logger;
use support\Log;
use think\facade\Db;
use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;
use Zipkin\Reporters\Http;
use Zipkin\TracingBuilder;
use Zipkin\Samplers\BinarySampler;
use Zipkin\Endpoint;
use Workerman\Timer;
use const Zipkin\Tags\SQL_QUERY;

class ArmsMiddleware implements MiddlewareInterface
{
    /**
     * @desc: 方法描述
     * @param Request $request
     * @param callable $next
     * @return Response
     * @author Tinywan(ShaoBo Wan)
     */
    public function process(Request $request, callable $next) : Response
    {
        static $tracing = null, $tracer = null;
        if (!$tracing) {
            $endpoint = Endpoint::create('开源技术小栈', $request->getRealIp(), null, 2555);
            $logger = new Logger('log');
            $logger->pushHandler(new ErrorLogHandler());
            $reporter = new Http(['endpoint_url' => config('security')['endpoint_url']]);
            $sampler = BinarySampler::createAsAlwaysSample();
            $tracing = TracingBuilder::create()
                ->havingLocalEndpoint($endpoint)
                ->havingSampler($sampler)
                ->havingReporter($reporter)
                ->build();
            $tracer = $tracing->getTracer();
            // 55秒上报一次,尽量将上报对业务的影响减少到最低
            Timer::add(55, function () use ($tracer) {
                $tracer->flush();
            });
            register_shutdown_function(function () use ($tracer) {
                $tracer->flush();
            });
        }

        $rootSpan = $tracer->newTrace();
        $rootSpan->setName($request->controller."::".$request->action);
        $rootSpan->start();
        $request->rootSpan = $rootSpan;
        $request->tracer = $tracer;
        $result = $next($request);

        // 统计sql(日志在内存)
        if (class_exists(Db::class)) {
            $logs = Db::getDbLog(true);
            if (!empty($logs['sql'])) {
                foreach ($logs['sql'] as $sql) {
                    $sqlSpan = $tracer->newChild($rootSpan->getContext());
                    $sqlSpan->setName(SQL_QUERY);
                    $sqlSpan->start();
                    $sqlSpan->tag('db.statement', $sql);
                    $sqlSpan->finish();
                }
            }
        }

        $rootSpan->finish();

        return $result;
    }
}

2. 配置中间件

config/middleware.php 中添加全局中间件如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
return [
    '' => [
        \app\middleware\ArmsMiddleware::class,
    ],
    ...
];

3. 查看监控

访问地址 https://tracing.console.aliyun.com/ ,效果类似如下

接口监控
数据库监控
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-06-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 开源技术小栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
可观测性之Micrometer Tracing
使用微服务框架的同学不知道有没有遇到过这样的问题,有业务同学投诉说未收到消息或者系统提示500状态码错误,然后App服务端同学开始根据业务反馈过来的用户信息查询日志,发现当前系统没有问题,然后将下游系统的负责人拉进群里协助排查问题,下游系统的同学又排查发现自己的系统也没问题又会将他的下游系统的同学拉进群,大家重复着这样的循环,群里面的人也越来越多,排查的链路也越来越长,业务同学也很着急催了一次又一次,直到达到循环的终止条件:链路中有一个同学发现系统日志里面抛出了一个异常,终于定位到了问题。
宋小生
2022/12/12
1.9K0
可观测性之Micrometer Tracing
分布式链路追踪系统原来是这么一回事
分布式系统变得日趋复杂,越来越多的组件开始走向分布式化,如微服务、分布式数据库、分布式缓存等,使得后台服务构成了一种复杂的分布式网络。在服务能力提升的同时,复杂的网络结构也使问题定位更加困难。在一个请求在经过诸多服务过程中,出现了某一个调用失败的情况,查询具体的异常由哪一个服务引起的就变得十分抓狂,问题定位和处理效率是也会非常低。
Bug开发工程师
2019/05/04
3.8K0
快速了解分布式链路追踪系统 zipkin
和市面上其它分布式链路追踪系统一样,Zipkin 也是根据 Google 论文《Dapper,大规模分布式系统的跟踪系统》(https://bigbully.github.io/Dapper-translation/) 作为理论,进行设计。
高楼Zee
2021/10/14
1.5K0
快速了解分布式链路追踪系统 zipkin
PHP 中使用 opentelemetry-auto-laravel 进行链路追踪时间片段不连续的问题
seth-shi
2024/03/29
5080
PHP 中使用 opentelemetry-auto-laravel 进行链路追踪时间片段不连续的问题
Istio最佳实践系列:如何实现方法级调用跟踪?
赵化冰,腾讯云高级工程师,Istio Member,ServiceMesher 管理委员,Istio 项目贡献者,热衷于开源、网络和云计算。目前主要从事服务网格的开源和研发工作。 引言 TCM(Tencent Cloud Mesh)是腾讯云上提供的基于Istio 进行增强,和 Istio API 完全兼容的 Service Mesh 托管服务,可以帮助用户以较小的迁移成本和维护代价快速利用到 Service Mesh 提供的流量管理和服务治理能力。本系列文章将介绍 TCM 上的最佳实践,本文将介绍如何利用
腾讯云原生
2021/04/12
1.3K0
spring-cloud-sleuth源码学习二
- spring-cloud-sleuth快速上手(https://cloud.tencent.com/developer/article/1884423)
eeaters
2021/09/30
1.5K0
spring-cloud-sleuth源码学习二
研究调用链跟踪技术之jaeger
最近在做微服务构架里有关调用链跟踪(也有叫分布式追踪)的部分,有一些心得,这里总结一些。
jeremyxu
2019/03/13
3.4K0
研究调用链跟踪技术之jaeger
Zipkin — 微服务链路跟踪.
 Zipkin是一款开源的分布式实时数据追踪系统(Distributed Tracking System),基于 Google Dapper的论文设计而来,由 Twitter 公司开发贡献。其主要功能是聚集来自各个异构系统的实时监控数据。分布式跟踪系统还有其他比较成熟的实现,例如:Naver的Pinpoint、Apache的HTrace、阿里的鹰眼Tracing、京东的Hydra、新浪的Watchman,美团点评的CAT,skywalking等。
JMCui
2019/06/03
11.9K0
Istio多集群链路追踪实践
为了实现多集群的流量治理,我们采用Istio官方提供的多主集群进行Istio的部署,这样就出现一个问题,对于多主集群的Istio治理,如何进行跨集群的流量监控,实现跨集群的服务链路追踪。
CNCF
2022/11/28
1.1K0
Istio多集群链路追踪实践
聊聊 SpringBoot3 的 Micrometer Tracing
这是个很尴尬的话题,为什么这么说呢?当我们在讨论卷和造轮子两个事情的时候,SpringBoot 的开发人员也正在做着同样的事情…
磊叔的技术博客
2025/06/07
3350
聊聊 SpringBoot3 的 Micrometer Tracing
[业界方案]用Jaeger来学习分布式追踪系统Opentracing
笔者之前有过zipkin的经验,希望扩展到Opentracing,于是在学习Jaeger基础上总结出此文,与大家分享。
罗西的思考
2020/09/16
2.3K0
基于 Jaeger 进行微服务链路追踪
基于解决不同行业、业务应用的可扩展性、可用性等一系列问题,由此而生的微服务架构得到了各大厂商的、组织以及个人的青睐,随之而来便广泛应用于各种行业场景应用中。然而,随着时间的推移,越来越多的问题慢慢地呈现在大众的视野中。
Luga Lee
2021/11/19
1.5K0
基于 Jaeger 进行微服务链路追踪
Skywalking Tracing 的接入和使用 —— Trace 之 OpenTelemetry 系列第三弹
导读 然后我们就进入标准的实操阶段,市面上有3个非常受欢迎的包含tracing的项目,skywalking,zipkin和jaeger。这篇文章希望通过解释skywalking的接入流程,让读者了解产品的设计,交互体验和提出一些自己的想法。如果有什么想法和建议,欢迎在评论区告诉我们。 作者介绍 徐为 腾讯云微服务团队高级解决方案构架师 毕业于欧盟 Erasmus Mundus IMMIT,获得经济和IT管理硕士学位 自2006年以来,曾就职于SonyEricsson、SAP等多家公司,历任软件
腾讯云中间件团队
2021/04/21
5.2K0
技术阅读摘要-3.Jaeger技术分析
通过上一次技术阅读摘要,我们了解了分布式链路追踪这项技术,Jaeger是其主流的实现方案。
junedayday
2021/10/27
5620
Zipkin客户端链路追踪源码解析
在spring-cloud-sleuth的spring.factories文件中注入的很多类中包含了一个类:TraceWebServletAutoConfiguration,一看就知道,这是为Servlet环境量身定制的一个自动装配类
Java学习录
2019/11/20
1.4K0
Zipkin客户端链路追踪源码解析
微服务难点剖析 | 服务拆的挺爽,问题是日志该怎么串联起来呢?
现在微服务架构盛行,很多以前的单体应用服务都被拆成了多个分布式的微服务,以解决应用系统发展壮大后的开发周期长、难以扩展、故障隔离等挑战。
KevinYan
2022/02/09
6700
微服务难点剖析 | 服务拆的挺爽,问题是日志该怎么串联起来呢?
微服务全链路跟踪:jaeger集成istio,并兼容uber-trace-id与b3
在基于HTTP协议的分布式调用中,通常会使用HTTP Header来传递SpanContext的内容。常见的Wire Protocol包含Zipkin使用的b3 HTTP header,Jaeger使用的uber-trace-id HTTP Header,LightStep使用的"x-ot-span-context" HTTP Header等。Istio1.0支持b3 header和x-ot-span-context header,可以和Zipkin,Jaeger及LightStep对接;istio1.4以上支持uber-trace-id,请参考github官方说明:https://github.com/istio/istio/issues/12400 现在我们我们接入非istio服务都是默认配置uber-trace-id
一笠风雨任生平
2020/04/30
3.7K1
微服务全链路跟踪:jaeger集成istio,并兼容uber-trace-id与b3
一文详解|Go 分布式链路追踪实现原理
在分布式、微服务架构下,应用一个请求往往贯穿多个分布式服务,这给应用的故障排查、性能优化带来新的挑战。分布式链路追踪作为解决分布式应用可观测问题的重要技术,愈发成为分布式应用不可缺少的基础设施。本文将详细介绍分布式链路的核心概念、架构原理和相关开源标准协议,并分享我们在实现无侵入 Go 采集 Sdk 方面的一些实践。
开源小E
2022/06/20
1.6K0
一文详解|Go 分布式链路追踪实现原理
微服务线上问题排查困难?不知道问题出在哪一环?那是你还不会分布式链路追踪
咱们以前单体应用里面有很多的应用和功能,依赖各个功能之间相互调用,使用公共的代码包等等,排查问题,使用类似于 gdb/dlv 工具或者直接查看代码日志,进行定位和分析
阿兵云原生
2023/09/28
4620
微服务线上问题排查困难?不知道问题出在哪一环?那是你还不会分布式链路追踪
从架构角度来看 Java 分布式日志如何收集
本文来自作者 张振华 在 GitChat 上分享 「从架构角度来看 Java 分布式日志如何收集」
CSDN技术头条
2018/07/30
3.6K0
从架构角度来看 Java 分布式日志如何收集
推荐阅读
相关推荐
可观测性之Micrometer Tracing
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档