云原生为传统监控带来挑战。云原生场景下,企业大规模地部署容器,应用节点呈指数级增长,故障可能发生在任意节点,无法感知与预测的因素越来越多。业界将“可观测性”能力划分为5个层级,其中告警(Alerting)与应用概览(Overview)属于传统监控的概念范畴。腾讯云“应用性能观测”则补齐主动发现的能力。构建简单易用,高性能的全链路监控系统。如何做到简单易用,满足用户拿来即用的需求?构建标准化,完善的探针能力是关键。
- 监控与可观测性的关系
1.1 “监控”是“可观测性”能力的一部分。
业界将“可观测性”能力划分为5个层级,其中告警(Alerting)与应用概览(Overview)属于传统监控的概念范畴。由于触发告警的往往是明显的症状与表象,但随着架构与应用部署方式的转变,不告警并非意味着一切正常,因此,获取系统内部的信息就显得尤为重要,而这些信息则须借助“可观测性”能力的另一大组成部分——主动发现(Preactive)。
如上图所示,告警和应用概览属于传统监控。加上主动发现,才能组成可观测系统。
“主动发现”,由排错、剖析与依赖分析三部分组成:
- 排错(Degugging),即运用数据和信息去诊断故障出现的原因;
- 剖析(Profiling),即运用数据和信息进行性能分析;
- 依赖分析(Dependency Analysis),即运用数据信息厘清系统之前的模块,并进行关联分析。
1.2 面向的核心用户不同。
监控是以运维为核⼼的系统,它通过各项指标数据来定义整体的运⾏状态、失败情况等;
观测则是以开发为核⼼的系统,除了监控,它还会对整个系统进⾏分析。
很多时候,运维给出的错误数据,只能算是提出了问题,但可观测性除了提出问题,还可以清晰地给出根因分析和故障预测等。
1.3 维度不同
监控是从外围的⻆度,通过各种指标(机器CPU、负载、⽹络的维度等)来判断整个系统的执⾏情况;⽽可观测性则在这种外部指标的基础上,以应⽤内的各个维度来展开推测, 最后,通过⼆者结合的数据更加真实地反映出我们应⽤的运⾏情况。
1.4 展现的信息不同
有些系统在正常运⾏时⼗分稳定,但是⼀到⾼并发的时候就会出现问题。此时,监控只能汇报问题出现的状况,但可观测性就可以很好地通过图形化的⽅式告知我们问题的原因,⽽不是由我们⽤经验来猜测。它可以将未知或者不确定的信息展现出来,使我们可以更好地了解系统的整体情况。
- 可观测性三大核心概念
Traces:分布式链路跟踪,提供了一个请求从接收到处理完成整个生命周期的跟踪路径
Metrics:提供cpu、请求延迟、用户访问数等Counter、Gauge、Histogram指标
Logs:传统的日志,提供精确的系统记录
很长一段时间内,这三者是独立存在的,随着时间的推移,发现这三者是相互关联,相辅相成。
- 基于Metrics告警发现异常
- 通过Tracing定位到具体的系统和方法
- 根据模块的日志最终定位到错误详情和根源
- 调整Metrics等设置,更精确的告警/发现问题
- 为什么基于OpenTelemetry构建探针能力?
3.1 OpenTelemetry是什么?
OpenTelemetry 是 CNCF 的一个可观测性项目,旨在提供可观测性领域的标准化方案,解决观测数据的数据模型、采集、处理、导出等的标准化问题,提供与三方 vendor 无关的服务。
OpenTelemetry是云原生软件的可观察性框架。架构图如下图所示,由API,SDK和Collector三部分组成。您可以使用它来生成,收集和导出遥测数据(指标,日志和跟踪),然后进行分析,方便了解软件的性能和行为。
3.2 APM探针技术选型和开发
探针开发的目标:
- 满足大客户定探针制化需求
- 降低接入门槛;降低部署成本
- 完善语言生态。完善各个语言组件生态环境;Java语言方法栈、堆栈快照能力等
- 组件维度协议标准化,降低接入定制化成本
JAVA开源框架对比:
探针的开发其实就是对语言所含的生态组件的开发,在java语言上就是通过字节码增强对技术,对组建的接口进行增强,在接口的头尾进行埋点的操作。
生态完善度统计了自动插桩支持的组件数量。
开源框架 | 埋点方式 | 支持协议 | 生态完善度 | 方法栈 | 堆栈快照 | 厂商/是否商用 |
---|---|---|---|---|---|---|
skywalking | 自动埋点(字节码增强) | 私有协议(兼容opentracing) | 57 | 注解 | 不支持 | skywalking/开源/无 |
pinpoint | 自动埋点(字节码增强) | 私有协议 | 63 | 包名通配符配置文件 | 支持 | pinpoint/开源/无 |
datadog | 自动埋点(字节码增强) | 私有协议(兼容opentracing) | 75 | 包名通配符配置文件 | 支持 | datadog/开源/商用 |
newrelic | 自动埋点(字节码增强) | 私有协议(兼容opentracing) | 56 | 包名通配符配置文件 | 支持 | newrelic/开源/商用 |
opentelemetry | 自动埋点(字节码增强) | opentelemtry | 63 | 注解 | 不支持 | opentelemetry开源/无 |
听云 | 自动埋点(字节码增强) | 私有协议 | * | 网络请求类所属函数默认埋点 | 支持 | 听云/闭源/商用 |
Node开源框架对比:
底层原理及本质区别:
自动插桩:实现原理没有本质区别,都是基于AOP, 面向切面的编程实现,javascript的apply函数。实现方式,通过swapper函数进行封装,对每个层面的IO进行监控。
生态完善度统计了自动插桩支持的组件数量。
开源框架 | 埋点方式 | 支持协议 | 生态完善度 | 自定义实现的难度 | 厂商/是否商用 |
---|---|---|---|---|---|
skywalking | 自动插桩(instrumentation)手动接入 | 兼容opentracing | 13 | skywalking/开源/无Apache基金会顶级项目。skywalking完全由国人主导开发,在国内社区相当活跃。 | |
OpenTelemetry | 自动插桩(instrumentation)手动接入 | 支持opentracing | 33官方: 28自研: 5 | 抽离了api和core库,自定义实现更简单 | OpenTelemetry/开源/商用云原生计算基金会(CNCF) |
pinpoint | 自动插桩(instrumentation)手动接入 | 私有协议 | 6 | pinpoint/开源/无韩国公司开发 | |
datadog | 自动插桩(instrumentation)手动接入 | 兼容opentracing | 46 | datadog/开源/商用 | |
newrelic | 自动插桩(instrumentation)手动接入 | 兼容opentracing | 9 | newrelic/开源/商用 | |
听云 | 自动插桩(instrumentation)手动接入 | 私有协议 | * | 听云/闭源/商用 | |
zipkin | 手动接入 | 兼容 OpenTracing | * | Twitter/开源/商用Twitter开源的调用链工具。国外主流。 | |
CAT | 手动接入 | 兼容 OpenTracing | * | 大众点评/开源/商用大众点评开源的, 主要在国内 | |
Jaeger | 自动插桩(instrumentation)手动接入 | 兼容 OpenTracing | 该库已弃用,并建议使用OpenTelemetry | Uber/开源/商用云原生计算基金会(CNCF)nodejs探针已被废弃 |
通过对比分析,OpenTelemetry支持标准化的SDK + 数据接入能力,支持的插件也比较丰富。同时具有如下优势:
- 完全中立的厂商,不收费
- 统一协议。现在与未来链路的标准协议,一套系统,数据关联。
- 完善探针和组件
- 易扩展
- 兼容性好。兼容OpenTracing,OpenCensus,Promethus...
另外,在OpenTelemetry方面,腾讯有“云原生可观测性 Oteam", 更利于协同打造完备的可观测生态系统。所以我们决定采用OpenTelemetry进行探针开发。
- NodeJS SDK 探针实践
4.1 OpenTelemetry JS 项目概况
OpenTelemetry 社区拆分为了三个仓库:
opentelemetry-js: 区分 Node 和 Web 等不同的场景,提供了 OpenTelemetry 的核心 SDK ,包含了 OpenTelemetry 的基础能力。
opentelemetry-js-api: 为用户提供了使用 OpenTelemetry 所需的 API ,但默认不提供任何具体的实现。可以理解为,该仓库仅提供了 interface ,然后通过 SDK 来注册具体的实现方式。也由于 API 不涉及具体实现,因此它在 Node 和 Web 等场景下都是通用的,只是需要在不同场景下使用不同的 SDK 进行注册。
opentelemetry-js-contrib: 区分 Node 和 Web 等不同的场景,提供了 OpenTelemetry 的非核心 SDK ,为 JS 生态下的常用库提供 OpenTelemetry 的能力,如 koa 、 ioredis 等。
Tencent OpenTelemetry Oteam 补充提供了公司内部生态:
opentelemetry-js-ecosystem(腾讯git地址): 区分 Node 和 Web 等不同的场景,为腾讯内部 JS 生态下的常用库提供 OpenTelemetry 的能力,如 hippy 、 trpc-node 等。
4.2 NodeJS项目如何接入自动插桩的能力
首先对 OpenTelemetry Trace SDK 进行初始化
在 Node 端使用 @opentelemetry/sdk-trace-node 。但 @opentelemetry/sdk-trace-node 集成了很多包作为依赖,其中大部分我们可能并不会用到。因此我们建议使用 @opentelemetry/sdk-trace-base ,然后按需安装所需要的依赖:
import { BasicTracerProvider } from '@opentelemetry/sdk-trace-base';
// 创建 tracerProvider
const tracerProvider = new BasicTracerProvider(/* 创建选项 /)
// 添加 Span 上报方式
tracerProvider.addSpanProcessor(/ Span 处理器,上报器 /)
// 全局注册 tracerProvider
tracerProvider.register(/ 注册选项 /)
初始化后,上报到"应用性能观测APM", 只需要三步:
1)获取接入点和 Token
(获取地址:https://console.cloud.tencent.com/apm/monitor/access)
接入点:grpc://ap-guangzhou.apm.tencentcs.com
Token:Vds***********CrKck
2)在创建 tracerProvider 时添加APM的额外 attributes :
import { Resource } from '@opentelemetry/resources';
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
import { ApmResourceAttributes } from './ApmResourceAttributes';
/**
获取上报的服务资源标签
/
export const getResource = async (): Promise<Resource> => {
// 如果要上报apm,请添加这些字段。
// 服务名称等基础字段。更多字段可参考 @opentelemetry/semantic-conventions
return new Resource({
// 必填,服务名称(在“应用列表”或“调用链”等地方显示对应的服务)
[SemanticResourceAttributes.SERVICE_NAME]: 'node_simple_server',
// 必填,token(上报鉴权 ApmResourceAttributes.APM_TOKEN = token)
[ApmResourceAttributes.APM_TOKEN]: 'oSmwaUrjLIbBiTZiNtSv',
// 可选
[ApmResourceAttributes.APP_ID]: 'node_simple_server',
// 可选
[ApmResourceAttributes.SERVER_ID]: 'node_simple_server',
// 可选
[ApmResourceAttributes.SERVER_OWNER]: 'foo;bar',
})
};
APM 约束常量定义类:
/
*
APM约定的 ResourceAttributes
@see 暂时没有对外文档
/
export const ApmResourceAttributes = {
/*
- (必选)APM的token
- 在APM创建一个实例后,APM会给这个实例创建一个对应的“上报地址”和“token”
- @see https://console.cloud.tencent.com/apm/monitor/access
*/
APM_TOKEN: 'token',
/**
- (可选)模块 ID
- @example 'bigdata'
*/
APP_ID: 'app.id',
/**
- (可选)模块名称
- @example '大数据模块'
*/
APP_NAME: 'app.name',
/**
- (可选)server ID
- @example 'collector'
*/
SERVER_ID: 'server.id',
/**
- (可选)server 名称
- @example '收集服务'
*/
SERVER_NAME: 'server.name',
/**
- (可选)server 负责人
- 多个负责人用英文分号分隔
*/
SERVER_OWNER: 'server.owner',
};
3)通过 addSpanProcessor 添加对应的上报方式:
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
// 如果要将 trace 信息上报apm,请使用 grpc OTLPTraceExporter 上报至对应 URL
tracerProvider.addSpanProcessor(
new SimpleSpanProcessor(
new OTLPTraceExporter({
// apm-collector URL(配置上报的实例地址)
url: 'grpc://ap-guangzhou.apm.tencentcs.com',
concurrencyLimit: 200,
}),
),
);
4.3 OpenTelemetry nodejs探针支持的插件
OpenTelemetry支持丰富自动检测插件,使用比较简单。唯一要注意的是,需要认真查看插件client支持的版本号。
插件 | 说明 |
---|---|
@opentelemetry/instrumentation-aws-lambda | AWS Lambda ,无需考虑服务器或集群即可运行代码。 类似腾讯的“云函数“ |
@opentelemetry/instrumentation-aws-sdk | 此模块为 aws-sdk v2 和 @aws-sdk v3 提供自动检测。类似于腾讯的“云API” |
@opentelemetry/instrumentation-bunyan | Nodejs的日志处理 |
@opentelemetry/instrumentation-pino | 开销非常低的 Node.js 日志处理。 |
@opentelemetry/instrumentation-winston | 日志处理 |
@opentelemetry/instrumentation-cassandra-driver | Cassandra是一套开源分布式NoSQL数据库系统 |
@opentelemetry/instrumentation-connect | Connect 是一个简单的框架,可以将各种“中间件”粘合在一起来处理请求。 |
@opentelemetry/instrumentation-dns | Node.js DNS 模块用于解析域名。 |
@opentelemetry/instrumentation-http | 该模块为 http 和 https 提供自动检测。 |
@opentelemetry/instrumentation-grpc | Node.js gRPC 库 |
@opentelemetry/instrumentation-hapi | Nodejs 的框架 |
@opentelemetry/instrumentation-express | Nodejs 的框架 |
@opentelemetry/instrumentation-koa | Nodejs 的框架 |
@opentelemetry/instrumentation-fastify | Nodejs 的框架 |
@opentelemetry/instrumentation-nestjs-core | Nodejs 的框架 |
@opentelemetry/instrumentation-generic-pool | 数据库链接池 |
@opentelemetry/instrumentation-graphql | GraphQL |
@opentelemetry/instrumentation-ioredis | Redis客户端 |
@opentelemetry/instrumentation-redis | Redis |
@opentelemetry/instrumentation-pg | PostgreSQL 客户端 |
@opentelemetry/instrumentation-knex | SQL 查询生成器 |
@opentelemetry/instrumentation-memcached | Memcached 客户端。Memcached是一个自由开源的,高性能,分布式内存对象缓存系统。 |
@opentelemetry/instrumentation-mongodb | Node.js 的官方 MongoDB 驱动程序 |
@opentelemetry/instrumentation-mysql2 | MySQL 2客户端 |
@opentelemetry/instrumentation-mysql | MySQL 客户端 |
@opentelemetry/instrumentation-net | Node.js Net 模块提供了一些用于底层的网络通信的小工具,包含了创建服务器/客户端的方法 |
@opentelemetry/instrumentation-restify | restify 是一个框架,利用连接风格的中间件来构建 REST API |
- 应用性能观测的架构和优势
5.1 应用性能观测的架构:
红色字体模块代表APM模块
蓝色背景色区域代表监控中台模块
5.2 应用性能监控的优势:
- APM基于OpenTelemetry探针进行了二次开发,给用户提供使用简单,功能强大的探针能力。用户拿来即用。
- 提供监控中台计算、存储,查询和告警能力
- 高性能自研可视化图表库,提供高性能,差异化的调用链拓扑图。
- 未来云原生下可观测性展望
可观察性与AIOps(Artificial Intelligence for IT Operations 智能运维)结合,可以把可观测性分为6个等级。
目前我们已实现智能告警的能力(Level 1)。相比较传统阈值监控:无需考虑阈值设置,基于算法自动生成动态边界;业务变更智能策略依然有效。
等级 0:手工分析,依靠基础的 Dashboard、告警、日志查询、分布式链路追踪等方式进行手动告警、分析,也是目前绝大部分公司使用的场景。
等级 1:智能告警,能够自动去扫描所有的可观察性数据,利用机器学习的方式去识别一些异常并进行自动告警,免去人工设置 / 调整各种基线告警的工作。
等级 2:异常关联 + 统一视图,对于自动识别的异常,能够进行上下文的关联,形成一个统一的业务视图,便于快速的定位问题
等级 3:根因分析 + 问题自愈,自动根据异常以及系统的 CMDB 信息直接定位问题的根因,根因定位准确后那边可以去做问题的自愈。这一阶段相当于是一次质的飞跃,在某些场景下可以在人不用参与的情况下实现问题的自愈。
等级 4:故障预测,故障发生总会有损失,所以最好的情况是避免故障的发生,因此故障预测技术可以更好的来保证系统的可靠性,利用之前积累的一些故障先兆信息做到 “未卜先知”
等级 5:变更影响预测,我们知道绝大部分的故障都是由变更引起的,因此如果能够模拟出每个变更对系统带来的影响以及可能产生的问题,我们就能够提前评估出是否能够允许此次变更。