链路追踪Tracing Analysis为分布式应用的开发者提供了完整的调用链路还原、调用请求量统计、链路拓扑、应用依赖分析等工具,可以帮助开发者快速分析和诊断分布式应用架构下的性能瓶颈,提高微服务时代下的开发诊断效率。
官方地址:https://github.com/openzipkin/zipkin
图片
图片
随着业务越来越复杂,系统也随之进行各种拆分,特别是随着微服务架构和容器技术的兴起,看似简单的一个应用,后台可能有几十个甚至几百个服务在支撑;一个前端的请求可能需要多次的服务调用最后才能完成;当请求变慢或者不可用时,我们无法得知是哪个后台服务引起的,这时就需要解决如何快速定位服务故障点,zipkin分布式跟踪系统就能很好的解决这样的问题。
图片
微服务架构下,一次请求后端会经历多个服务调用(所有请求链有相同的traceId和不同的spanId),都会沿着traceText带到每一个服务中。
图片
“
不通过Agent而直接上报数据的原理(传统框架。PHP-FPM + Nginx模式)
图片
通过Agent上报数据的原理(现代化框架。命令行模式)。
通过composer安装:
composer require openzipkin/zipkin
Tracer对象可以用来创建Span对象(记录分布式操作时间)。Tracer对象还配置了上报数据的网关地址、本机IP、采样频率等数据,您可以通过调整采样率来减少因上报数据产生的开销。
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;}
$rootSpan = $tracer->newTrace();$rootSpan->setName('encode');$rootSpan->start();try { doSomethingExpensive();} finally { $rootSpan->finish();}
以上代码用于记录请求的根操作,如果需要记录请求的上一步和下一步操作,则需要传入上下文。示例:
$span = $tracer->newChild($parentSpan->getContext());$span->setName('encode');$span->start();try { doSomethingExpensive();} finally { $span->finish();}
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 │ ││ └──────────────┘ │ └───────────────────┘ │ └──────────────┘ ││ │ │ │└──────────────────┘ └──────────────────┘
开通ARMS地址 https://arms.console.aliyun.com/ (一般有15天试用)
进入 https://tracing.console.aliyun.com/#/globalSetting/cn-hangzhou/process 按照图示获得接入点url地址。
图片
如果你的服务器在阿里云上可以用阿里云vpc网络接入点,本示例用的是阿里云公网接入点。
通过composer安装:
composer require openzipkin/zipkin
链路监控中间件 app/middleware/ArmsMiddleware.php
<?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; }}
在 config/middleware.php 中添加全局中间件如下:
return [ '' => [ /app/middleware/ArmsMiddleware::class, ], ...];
访问地址 https://tracing.console.aliyun.com/ ,效果类似如下:
图片
图片
本文链接://www.dmpip.com//www.dmpip.com/showinfo-26-93091-0.htmlPHP 服务实现性能剖析、跟踪和可观察性14444444444444】=102102102102102102102102102102102102102102102102实践
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com