目录
引言
与前篇谈到的MCP协议类似,OpenTelemetry也是一套标准协议。每一套协议的诞生一定是为了解决已存在的某难题的,就好比得先有四通八达的马路和满街的汽车,交通规则的诞生才有意义,如果只是三三两两的车流,似乎交通规则就没那么大的价值。
OpenTelemetry 的前身是 OpenTracing 和 OpenCensus 两个项目。OpenTracing 主要关注分布式追踪,而 OpenCensus 则侧重于指标和跨语言的统计信息收集。 2019年,这两个社区决定合作并融合各自的特性,形成了新的开源项目——OpenTelemetry。这一举措旨在提供一个全面的解决方案,能够同时处理追踪、指标和其他形式的遥测数据,并且支持多种编程语言和框架。OpenTelemetry 在之后的时间里不断完善和扩展其功能,并于2020年正式发布了首个稳定版本。
OpenTelemetry 的诞生是为了应对现代软件系统架构中日益增长的监控和追踪需求,特别是分布式系统和云原生环境的复杂性。它的出现是为了解决多个监控工具之间的互操作性问题,以及提供一种统一的方式来收集、处理和分析遥测数据,从而帮助开发和运维团队更有效地理解和优化他们的服务。
一、OpenTelemetry是一套可观测性标准协议
OpenTelemetry是一套由CNCF主导的云原生可观测性标准协议,全称:OpenTelemetry Protocol,简称OTLP,旨在提供一种统一的方式来收集、处理和分析 分布式追踪(trace)、日志(logging)和度量(metrics) 数据。
OpenTelemetry定义了可观测性的几个方面的标准:trace、logs、metrics、resources。
-
追踪(Tracing):
提供了分布式追踪的功能,可以跟踪请求在分布式系统中的完整路径,帮助识别性能瓶颈和故障点。 -
指标(Metrics):
收集系统的各种性能指标,如请求速率、错误率、资源使用情况等,用于监控系统的健康状况和性能。 -
日志(Logs):
虽然 OpenTelemetry 主要关注追踪和指标,但它也支持与日志系统的集成,以便于将日志数据与其他类型的遥测数据关联起来。
二、分布式追踪(Trace)是OpenTelemetry的核心功能之一
OpenTelemetry与trace的关系主要体现在OpenTelemetry是用于分布式追踪的标准和工具集,而trace是分布式追踪的基本单位。
分布式追踪(Trace)是OpenTelemetry的核心功能之一,用于监控和分析微服务架构中的请求传播路径和性能问题。Trace在分布式系统中扮演着关键角色。它记录了一个请求在多个服务之间传播的完整路径,帮助开发者理解请求在系统中的行为和性能表现。一个trace由多个span组成,每个span代表请求中的一个操作或工作单元,记录了操作的具体信息,如开始和结束时间、操作类型、结果状态等。通过这些信息,开发者可以重构事务的完整旅程,定位和解决性能问题和故障。
可观测性一个很重要的领域 Trace 有两个业界标杆:一个是OpenTracing,另一个OpenCensus。
OpenTracing其实是一个规范,jaeger就是基于opentracing实现的开源工具;
OpenCensus则是由google开源的度量工具;
简单来说,这两者在可观测性领域功能高度重合,因此,在CNCF主导下进行了合并形成opentelemetry项目,OpenTracing跟penCensus共同推进opentelemetry,两者的官网也赫赫表达基本不再维护。同时OpenTelemetry也致力于trace、logging、metrics间的关联性。
三、OpenTelemetry的架构原理
我们重点先来看数据收集管道。
Data Collection Pipeline(数据收集管道)包含:
- Collector:OpenTelemetry Collector是一个开源的组件,用于接收、处理和导出遥测数据。它可以部署在各个服务节点上,也可以作为一个集中式的处理层。
- Receiver:接收来自不同来源的遥测数据。
- Processor:处理和转换数据,例如过滤、聚合等。
- Exporter:将处理后的数据导出到各种后端系统,如Jaeger、Prometheus、Zipkin等。
可不要小看这些概念,在写代码的时候处理问题可有用了。从上面的图可以看出数据整个流向的过程,当数据经过Collector采集器之后,就可以Exporter到各种存储介质上了。细心的小伙伴们发现了,OpenTelemetry并未直接实现Exporter之后的数据存储,而是交给遵循了OpenTelemetry协议的Jaeger、Prometheus、Zipkin等存储平台。通俗理解就是只要数据格式是遵循OpenTelemetry的上报,都可以进行数据标准化等处理,并被上报到任意遵循了OpenTelemetry协议的存储介质平台上进行下一步的遥测观察和统计。
OpenTelemetry内心OS:“我只是个协议而已,存储就交给别人来做吧,要实现存储这得是另外的价钱~~”。
四、OpenTelemetry的分布式追踪(Trace)实践
我们知道OpenTelemetry有几个方面的标准:分布式追踪(trace)、日志(logging)和度量(metrics)。这就意味着他可以用来做很多不仅仅是分布式追踪(trace)之外的事,比如K8s的监控,服务的监控等等。我们这里之所以当独讲分布式追踪(trace),主要是因为其不仅是OpenTelemetry的核心功能,在监控和分析微服务架构中的请求传播路径和性能问题上目前也是普遍流行的解决方案。
那么我们如何基于OpenTelemetry实现链路追踪呢?
我们先来看OpenTelemetry官网的介绍。
光说不练假把式。于是我们以PHP为例来一步一步详细操作下来简单demo实践一下。其他语言同理。
1、准备PHP环境
它说PHP版本要求至少7.4+,而如果希望0代码非入侵式的接入PHP版本至少要8.0+。
OpenTelemetry部分是支持无缝接入的,也就是非入侵式的服务监控和分布式追踪,当然如果你需要个性化地“埋点”自己的服务调用链路情况,那就可以自己手动用代码实现了(代码侵入式)。
由于小马的本地已经安装了PHP相关环境,特意检查了下版本号符合条件,环境准备完毕。
2、下载SDK
参考官网案例,我们进入代码目录下,运行composer命令安装SDK依赖,composer.json文件需要安装的依赖包配置参考如下。
但这里需要注意,市面上开源SDK实现可能会有很多,不管你依赖于哪个SDK,只要遵循OpenTelemetry协议即可。
{
"name": "vendor/m.server3",
"description": "description",
"minimum-stability": "stable",
"license": "proprietary",
"authors": [
{
"name": "小马过河R",
"email": "email@example.com"
}
],
"require": {
"slim/slim": "^4",
"slim/psr7":"^1",
"nyholm/psr7": "^1",
"open-telemetry/opentelemetry": "*",
"open-telemetry/api": "*",
"open-telemetry/sdk": "*",
"symfony/http-client": "^5.4",
"guzzlehttp/promises": "^2.2",
"php-http/message-factory": "^1.1",
"php-http/httplug": "^2.4"
},
"config": {
"allow-plugins": {
"php-http/discovery": true
}
}
}
3、编写实例代码
进入代码目录下,创建index.php文件。
为了验证,我们先将TRACES输出到console查看。
putenv('OTEL_SERVICE_NAME=demo1');
putenv('OTEL_PHP_AUTOLOAD_ENABLED=true');
putenv('OTEL_TRACES_EXPORTER=console');//console otlp
putenv('OTEL_METRICS_EXPORTER=none');
putenv('OTEL_LOGS_EXPORTER=console');
#putenv('OTEL_EXPORTER_OTLP_PROTOCOL=grpc');
#putenv('OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318');//http:4318,grpc:4317
#putenv('OTEL_EXPORTER_OTLP_HEADERS=');
#putenv('OTEL_PROPAGATORS=b3,baggage,tracecontext');
use OpenTelemetry\API\Globals;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require_once __DIR__ . '/vendor/autoload.php';
$tracer = Globals::tracerProvider()->getTracer('demo-tracer-name');
$app = AppFactory::create();
$app->get('/rolldice', function (Request $request, Response $response) use ($tracer) {
$span = $tracer->spanBuilder('manual-span')->startSpan();
try {
$span->setAttribute('user_id', 12345);
$result = random_int(1, 6);
$response->getBody()->write(strval($result));
$span->addEvent('rolled dice', ['result' => $result])->end();
return $response;
} catch (Exception $e) {
$span->setStatus($e->getCode(), $e->getMessage());
$span->end();
$response->getBody()->write('exception');
return $response;
}
});
$app->run();
4、run起来
我们在代码目录下执行php -S localhost:8080
命令,让程序监听8080端口。
回到浏览器访问路由http://localhost:8080/rolldice
。我们看到了响应返回。
而console如约打出了日志信息。
好了,我们的demo实现完毕了,看起来超级简单,对吧。
5、otlp协议上报到存储介质平台
我们刚刚为了方便演示,把日志输出在console,但是实际生产场景中肯定不是这样的,那如果我要上报到诸如Jaeger、Prometheus、Zipkin等的后端系统或存储平台,要如何处理?很简单,修改配置即可。详细的可以参看官方的配置介绍文档。小马这里主要拎几个重要的配置项来介绍。
//something todo...
putenv('OTEL_TRACES_EXPORTER=otlp');//改成otlp
#putenv('OTEL_EXPORTER_OTLP_PROTOCOL=grpc');//默认http
putenv('OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318');//填写ENDPOINT上报地址,http:4318,grpc:4317
putenv('OTEL_EXPORTER_OTLP_HEADERS=');//如果有些平台是要求传鉴权token,可以通过HEADERS透传
//something todo...
好了,这就改完了,重新run起来。
在平台你将看到如下类似效果(由于信息敏感小马就不贴自己实验的截图啦),日志信息将比console展示更完整和丰富。
当然,至于TRACES相关的知识点以及如何合理规划设置span不是本文重点,小马这里就不再赘述啦。