标签 可观测性 下的文章

观测云提供一站式云、云原生、应用及业务的可观测解决方案,日志监控器是其核心功能之一,它不仅仅是一个被动的日志收集和存储工具,更是一个主动、智能的日志分析与监控告警平台。它的设计目标是帮助开发、运维和业务团队从海量的日志数据中快速发现问题、定位根因并及时响应。日志监控器的核心价值在于将非结构化的日志数据转化为可观测的结构化信息,并通过监控和告警机制,使其成为保障系统稳定性和业务连续性的有力工具。

通知对象

观测云支持向钉钉、企业微信、飞书等渠道发送通知,使用时需要先创建通知对象。点击「监控」 -「通知对象管理」-「新建通知对象」。

图片

填写消息推送机器人的 Webhook 地址。

图片

告警策略

点击「监控」 -「告警策略管理」-「新建告警策略」。通过关联监控器与告警策略,系统可在异常发生时即时向指定对象发送通知。策略支持配置名称、描述、时区与操作权限等基础信息,并允许按告警等级、通知对象两个维度灵活定义通知规则。针对高紧急度场景可启用升级通知机制,同时支持自定义通知发送时段,以适配不同时段的业务需求。

图片

日志监控器

「监控」 -「监控器」-「新建监控器」,选择“日志检测”,依次配置“检测配置”、“事件通知”、“告警配置”。

检测配置

如下图是按主机和服务的维度,统计 5 分钟内 mall-admin 服务中状态是 error 的日志条数。

图片

当错误数大于等于 2 条时触发致命告警。

图片

事件内容

支持自定义事件通知的标题与内容。

插入日志变量

点击"变量"选择需要展示的变量名,比如 host、service。

图片

插入链接

点击“链接”插入日志查看地址,实现告警界面一键跳转到观测云。

图片

附加信息

点击"添加附加信息"选择日志字段(如 message),在告警内容中展示。

图片

点击“变量”插入 {{df_related_data.message}},建议截取前200字符避免超出告警工具长度限制。

图片

告警策略

配置告警策略后,系统将向对应对象发送通知。

图片

恢复事件

连续两个周期无异常触发恢复事件,留空则不发送。

图片

告警通知

告警触发后,事件中心关联事件的“通知”列显示企微图标即表示推送成功。

图片

在企微机器人群收到如下信息。

图片

问题排查

企微未收到告警时,请在“事件中心”查找对应事件:

  • 无事件:检查监控器DQL配置
  • 事件存在但通知列无企微图标:检查通知对象与静默期设置
  • 通知列有企微图标:可能因告警过于频繁触发Webhook限流

无事件排查

打开监控器,复制上方的 DQL。

图片

复制出来的 DQL 如下:

window("L('default')::RE(`.*`):(count(`*`)) { `service` = \"mall-admin\" AND `status` = \"error\" } BY `service`, `host`", '5m')

打开「快捷入口」 -「DQL 查询」,粘贴 DQL,去掉外层的 windows 函数,去掉转义,检测区间选择和监控器相同,点击“执行”。如果无数据则不会触发告警。

图片

前言

本节详细聊一下基于envoy的可观测性

日志

首先是日志,配置日志的方式也很简单

static_resources:
  listeners:
    - name: ingress_listener
      address:
        socket_address:
          address: 0.0.0.0
          port_value: 10000
      filter_chains:
        - filters:
            - name: envoy.filters.network.http_connection_manager
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                stat_prefix: ingress_http
                ...
                access_log:
                - name: envoy.access_loggers.stdout
                  typed_config:
                    "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
                    log_format:
                      text_format: "[%START_TIME%] \"%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\" %RESPONSE_CODE% %BYTES_SENT% %DURATION% %REQ(X-REQUEST-ID)% \"%REQ(USER-AGENT)%\" \"%REQ(X-FORWARDED-FOR)%\" %UPSTREAM_HOST% %UPSTREAM_CLUSTER% %RESPONSE_FLAGS%\n"
  • 该配置是将日志输出在控制台,也可以直接输出为文件,然后通过工具采集走path: /var/log/envoy/access.log
  • 也可以直接将日志输出至kafka,并且按比例采集、只采集4xx、5xx等都可以配置,这里就不在赘述了

admin管理页面

envoy有默认的admin页面,方便查看统计信息、打开某些功能的开关等

admin:
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 9901

打开9901页面:

watermarked-envoy_ob_1.png

可以查看相关的统计信息、也可以打开某些开关,功能还是很丰富的

merics接入prometheus

打开了admin之后,就默认提供了相关的prometheus stats http://10.105.148.194:9901/stats/prometheus

这时只需在k8s集群外弄一个prometheus,并且采集该envoy即可

prometheus.yml

global:
  scrape_interval: 5s
  evaluation_interval: 5s

rule_files:
  - /etc/prometheus/*.rules

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
    - targets: ['localhost:9090']

  - job_name: "envoy"
    metrics_path: /stats/prometheus
    static_configs:
    - targets: ["10.105.148.194:9901"]
docker run -d --name prometheus \
  -p 9090:9090 \
  -v ./prometheus.yml:/etc/prometheus/prometheus.yml \
  -v /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime \
  registry.cn-beijing.aliyuncs.com/wilsonchai/prometheus:v3.5.0

traces接入jaeger

jaeger的安装可以参考这里: opentelemetry全链路初探--埋点与jaeger

jaeger启动之后,改造一下envoy的配置,这里要特别注意,不同版本的配置不一样,我这里envoy的版本是:v1.32

static_resources:
  listeners:
    - name: ingress_listener
      filter_chains:
        - filters:
            - name: envoy.filters.network.http_connection_manager
              typed_config:
                ...

                tracing:

                  provider:
                    name: envoy.tracers.opentelemetry
                    typed_config:
                      "@type": type.googleapis.com/envoy.config.trace.v3.OpenTelemetryConfig
                      service_name: envoy-proxy
                      grpc_service:
                        envoy_grpc:
                          cluster_name: jaeger_otlp_collector
                ...

  clusters:
    ...
    - name: jaeger_otlp_collector
      type: LOGICAL_DNS
      connect_timeout: 5s
      lb_policy: ROUND_ROBIN
      http2_protocol_options: {}

      load_assignment:
        cluster_name: jaeger_otlp_collector
        endpoints:
        - lb_endpoints:
          - endpoint:
              address:
                socket_address:
                  address: 10.22.12.178
                  port_value: 4317
    ...

修改完成之后重启下envoy

jaeger成功接收到了来自envoy的trace

watermarked-envoy_ob_2.png
watermarked-envoy_ob_3.png

由于只在envoy配置了trace,没有和后端服务联动,所有只显示了envoy这一段的trace信息,如果要联动后端,可以参考这个系列的文章: 全链路监控配置

小结

至此,logs、metrics、traces三大可观测的指标建设完成,envoy可观测性的建设也结束了

联系我

  • 联系我,做深入的交流

 title=


至此,本文结束
在下才疏学浅,有撒汤漏水的,请各位不吝赐教...

阿里云 RocketMQ 4.0 介绍

阿里云 RocketMQ 4.0 产品是阿里云早期基于 Apache RocketMQ 构建的分布式消息中间件,主要面向企业级消息传递和异步解耦场景。RocketMQ 4.0 在发布时已具备高吞吐、低延迟、可扩展的核心特性,支持顺序消息、事务消息、定时/延时消息等多种能力,帮助开发者快速实现系统间的可靠通信。相比更高版本,RocketMQ 4.0 在弹性伸缩、可观测性和集成易用性方面能力有限,更多依赖人工运维和监控工具。但通过合理部署与监控,仍能够满足大多数分布式系统的消息传递需求,为业务提供基础的高可用性和可靠性保障。

观测云

观测云是一款专为 IT 工程师打造的全链路可观测产品,它集成了基础设施监控、应用程序性能监控和日志管理,为整个技术栈提供实时可观察性。这款产品能够帮助工程师全面了解端到端的用户体验追踪,了解应用内函数的每一次调用,以及全面监控云时代的基础设施。此外,观测云还具备快速发现系统安全风险的能力,为数字化时代提供安全保障。

采集方法

  1. 登录观测云控制台
  2. 点击【集成】菜单,选择【云账号管理】
  3. 点击【添加云账号】,选择【阿里云】,填写界面所需的信息,如之前已配置过云账号信息,则忽略此步骤
  4. 点击【测试】,测试成功后点击【保存】,如果测试失败,请检查相关配置信息是否正确,并重新测试
  5. 点击【云账号管理】列表上可以看到已添加的云账号,点击相应的云账号,进入详情页
  6. 点击云账号详情页的【集成】按钮,在未安装列表下,找到阿里云 RocketMQ 4.0,点击【安装】按钮,弹出安装界面安装即可。

图片

关键指标

Metric IdMetric NameDimensionsStatisticsUni
ReadyMessages已就绪消息量(Group)account_name,InstanceNameAverage,Maximumcount
ReadyMessagesPerGidTopic已就绪消息量(Group&Topic)account_name,InstanceNameAverage,Maximumcount
ReceiveMessageCountPerGid消费者每分钟接收消息数量(Group)account_name,InstanceNameAverage,Maximumcount/min
ReceiveMessageCountPerGidTopic消费者每分钟接收消息数量(Group&Topic)account_name,InstanceNameAverage,Maximumcount/min
ReceiveMessageCountPerInstance消费者每分钟接收消息数的数量(Instance)account_name,InstanceNameAverage,Maximumcount/min
ReceiveMessageCountPerTopic消费者每分钟接收消息的数量(Topic)account_name,InstanceNameAverage,Maximumcount/min
SendDLQMessageCountPerGid每分钟产生死信消息的数量(Group)account_name,InstanceNameAverage,Maximumcount/min
SendDLQMessageCountPerGidTopic每分钟产生死信消息的数量(Group&Topic)account_name,InstanceNameAverage,Maximumcount/min
SendMessageCountPerInstance生产者每分钟发送消息数量(Instance)account_name,InstanceNameAverage,Maximumcount/min
SendMessageCountPerTopic生产者每分钟发送消息数量(Topic)account_name,InstanceNameAverage,Maximumcount/min
ThrottledReceiveRequestsPerGid每分钟(GroupId)消费被限流次数account_name,InstanceNameAverage,Maximumcounts/min
ThrottledReceiveRequestsPerGidTopic每分钟(GroupId&Topic)消费被限流次数account_name,InstanceNameAverage,Maximumcounts/min
ThrottledReceiveRequestsPerInstance每分钟(Instance)消费被限流次数account_name,InstanceNameAverage,Maximumcounts/min
ThrottledSendRequestsPerInstance每分钟(Instance)发送被限流次数account_name,InstanceNameAverage,Maximumcounts/min
ThrottledSendRequestsPerTopic每分钟(Topic)发送被限流次数account_name,InstanceNameAverage,Maximumcounts/min

场景视图

登录观测云控制台,点击「场景」 -「新建仪表板」,输入 “阿里云 RocketMQ”, 选择 “阿里云 RocketMQ4监控视图”,点击 “确定” 即可添加视图。

图片

图片

监控器(告警)

ReadyMessagesPerGidTopic 消息堆积量异常

简要描述:消息堆积量异常通常表示某个 Group 或 Group&Topic 维度下的待消费消息数持续增加,说明消费者处理速度低于生产速度。这可能会导致消息延迟变大,甚至出现业务处理超时或丢弃风险。及时监控和处理堆积量异常,有助于发现消费性能瓶颈或消费者实例异常,保障消息系统的稳定性与业务的连续性。

图片

ReceiveMessageCountPerGid / PerTopic

简要描述:消费者接收消息速率异常通常表示某个 Group、Topic 或整个实例的消费吞吐量低于预期。这可能源于消费者宕机、线程不足、消费逻辑耗时过长或网络瓶颈。持续的消费速率下降会导致消息堆积增加,从而影响业务的实时性。监控该指标可帮助及时发现和定位消费环节的问题,确保生产与消费之间的速率平衡。

图片

总结

通过将阿里云 RocketMQ 4.0 的监控数据接入观测云,用户可实现更直观的运行监控与异常告警。观测云能够采集并展示消息堆积量、消费速率等关键指标,及时发现消费者性能瓶颈或消息延迟问题。借助智能告警与可视化视图,用户可快速定位异常、优化消费逻辑,从而提升系统稳定性与运维效率。整体而言,该方案帮助企业在传统 RocketMQ 4.0 环境下实现现代化可观测运维。

图片
伴随多智能体系统的规模化落地与技术迭代,其跨智能体交互的动态性与决策链路的黑箱特性,使AI协作的复杂度呈指数级攀升。传统可观测体系以指标、日志、链路等系统运行数据为核心,主要解答“系统发生了什么?”的问题。但当面对多个自主决策、动态交互的AI智能体时,我们更需要解答:“智能体为何这样决策?”、“协作是否高效合理?”以及“如何保证结果可靠与成本可控?”等难题。多智能体不仅改变了应用架构,更从根本上对可观测性的深度与广度提出了新的要求:如何打通从数据获取、分析到决策的完整价值链,形成高效闭环?当自动配置、智能见解等核心能力孤立运行时,如何实现它们的协同联动,以精准应对复杂运维场景?又该如何突破当前自动化诊断的瓶颈,稳步迈向预测性干预与系统自愈的高阶智能化阶段?Bonree精彩直播,码上预约为深入探讨这一命题,博睿数据特别推出【前瞻2026:可观测技术风向与趋势洞察】专题直播,直播分为上下两期。下期直播,我们聚焦于可观测性产品本身的演进路径:1月28日(周三)14:00,博睿数据产品中心高级产品经理马倩,将带来 《多智能体协同下的可观测产品体系化演进》主题分享。本次直播将从实际产品视角出发,聚焦可观测性产品的演进路径,从产品内核、协同逻辑到突破方向,展开全方位、深层次的拆解与分析。
图片
博睿宏远,将在01月28日 14:00 直播已预约多智能体协同下的可观测产品演进
图片
本次直播我们将深入探讨技术趋势,助力大家洞悉多智能体时代可观测性领域的全新挑战与技术走向。立即预约直播,解锁多智能体协同下可观测产品体系化演进,获取该领域关键认知与演进逻辑!

写在前面,本人目前处于求职中,如有合适内推岗位,请加:lpshiyue 感谢。同时还望大家一键三连,赚点奶粉钱。本系列已完结,完整版阅读课联系本人

现代分布式系统的可观测性不是简单的数据收集,而是基于业务目标的智能过滤与决策体系

在掌握了风险可控的发布策略后,我们需要解决一个更根本的问题:如何准确判断发布是否成功?如何在海量监控数据中识别真正重要的信号?全栈监控与告警设计正是连接系统状态与人工干预的关键桥梁。本文将从SLO定义出发,深入探讨监控指标体系构建、告警规则设计、分级抑制策略的全链路实践,帮助企业构建既敏感又精准的可观测体系。

1 监控体系的哲学转变:从数据收集到价值判断

1.1 传统监控的局限性:数据丰富而洞察匮乏

传统监控系统面临的核心矛盾是数据收集能力价值提取效率之间的巨大鸿沟。随着微服务和云原生架构的普及,单个系统产生的指标数量呈指数级增长,但运维团队能够有效处理的告警数量基本恒定。

监控数据的三个价值层次

  • 基础指标:CPU、内存、网络等资源消耗数据(容易收集但价值有限)
  • 应用性能:请求延迟、错误率、吞吐量等业务相关指标(需要业务埋点)
  • 用户体验:真实用户感知的可用性和性能(最难测量但最具价值)

根据行业数据,未经验证的监控告警中超过70%属于噪音或误报,导致团队产生"告警疲劳",反而忽略真正重要的异常信号。

1.2 SLO:监控价值的锚点

Service Level Objective(服务等级目标)为监控系统提供了价值判断的基准。SLO将模糊的"系统健康"概念转化为可量化的目标,成为区分信号与噪音的核心依据。

SLO的核心价值在于:

  • 目标一致性:使技术指标与业务目标对齐
  • 优先级判断:基于错误预算确定问题处理的紧急程度
  • 资源分配:根据SLO达成情况指导稳定性投入
# SLO定义示例:API服务可用性目标
api_service_slo:
  availability: 99.9%  # 每月最多43分钟不可用
  latency_p95: 200ms   # 95%请求延迟低于200ms
  error_rate: 0.1%     # 错误率低于0.1%
  rolling_period: 30d  # 滚动计算周期为30天

2 全栈监控体系构建:从基础设施到用户体验

2.1 监控数据的三位一体

现代监控体系需要整合指标(Metrics)、日志(Logs)、追踪(Traces) 三类数据,形成完整的可观测性能力。

指标监控提供系统量化度量,适合趋势分析和阈值告警:

  • 基础资源指标:CPU、内存、磁盘、网络(通过Node Exporter采集)
  • 应用性能指标:QPS、延迟、错误率(通过应用埋点暴露)
  • 业务指标:订单量、支付成功率、用户活跃度(自定义业务埋点)

日志分析记录系统详细行为,用于故障排查和审计:

  • 结构化日志收集(Filebeat/Fluentd)
  • 日志聚合与检索(Elasticsearch)
  • 模式识别与异常检测(机器学习分析)

分布式追踪提供请求全链路视角,优化性能诊断:

  • 请求级跟踪(Jaeger/SkyWalking)
  • 服务依赖拓扑自动发现
  • 瓶颈分析与链路优化

2.2 监控数据采集的技术选型

Prometheus生态已成为云原生监控的事实标准,其拉取模型多维数据模型特别适合动态环境。

# Prometheus配置示例
scrape_configs:
  - job_name: 'api-service'
    static_configs:
      - targets: ['api-service:8080']
    metrics_path: '/metrics'
    scrape_interval: 15s
    # 指标Relabeling,增强元数据
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: blackbox-exporter:9115

多数据源整合是大型系统的必然选择。Zabbix适合传统基础设施监控,Prometheus擅长云原生环境,商业方案如CloudWatch提供开箱即用体验。

2.3 监控数据建模与存储优化

监控数据的时序特性要求专用存储方案。Prometheus TSDB适合短期数据存储,长期存储需考虑Thanos、Cortex或M3DB等分布式方案。

数据降采样策略对成本控制至关重要:

  • 原始数据:保留2天,15秒精度
  • 5分钟聚合数据:保留30天
  • 1小时聚合数据:保留1年
  • 日级别聚合数据:永久保留

3 从SLO到告警规则:精准告警的数学基础

3.1 错误预算:SLO的可操作化表达

错误预算将SLO转化为可消耗的资源,为告警触发提供客观依据。例如,99.9%可用性目标意味着每月有43分钟错误预算。

错误预算消耗速率(Burn Rate)成为告警的关键指标:

  • 快速燃烧:高错误率短时间消耗大量预算(需要立即处理)
  • 慢速燃烧:低错误率持续消耗预算(需要计划性修复)
# 错误预算消耗计算
def calculate_burn_rate(slo_target, error_rate, time_window):
    """计算错误预算消耗速率"""
    error_budget = 1 - slo_target  # 错误预算比例
    actual_consumption = error_rate * time_window
    burn_rate = actual_consumption / (error_budget * time_window)
    return burn_rate

# 示例:99.9%可用性目标,1%错误率持续30分钟
burn_rate = calculate_burn_rate(0.999, 0.01, 30)
if burn_rate > 10:  # 消耗速率超过10倍
    trigger_critical_alert()

3.2 多维度SLO指标映射

不同服务需要不同的SLO定义方式,核心是建立技术指标与用户体验的直接关联。

API服务SLO映射

-- 基于SLI(服务等级指标)计算SLO达成率
SELECT 
    time_bucket('1 hour', timestamp) as hour,
    -- 可用性SLI
    SUM(CASE WHEN status_code < 500 THEN 1 ELSE 0 END) * 1.0 / COUNT(*) as availability,
    -- 延迟SLI 
    PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY latency) as latency_p95,
    -- 错误率SLI
    SUM(CASE WHEN status_code >= 500 THEN 1 ELSE 0 END) * 1.0 / COUNT(*) as error_rate
FROM api_requests 
WHERE timestamp >= NOW() - INTERVAL '30 days'
GROUP BY hour

批处理服务SLO特性

  • 完整性:数据处理是否100%成功
  • 及时性:作业是否在时间窗口内完成
  • 正确性:输出结果是否符合质量要求

3.3 告警规则的数学建模

有效的告警规则需要基于统计学原理而非简单阈值。

动态基线告警考虑历史模式和周期性:

-- 基于时间序列分析的异常检测
WITH baseline AS (
  SELECT
    AVG(latency) as historical_avg,
    STDDEV(latency) as historical_stddev
  FROM api_metrics
  WHERE time > NOW() - INTERVAL '4 weeks'
    AND hour_of_day = EXTRACT(HOUR FROM NOW())
)
SELECT 
  current.latency,
  (current.latency - baseline.historical_avg) / baseline.historical_stddev as z_score
FROM current_metrics current, baseline
WHERE ABS((current.latency - baseline.historical_avg) / baseline.historical_stddev) > 3

多指标复合告警提高准确性:

  • 条件1:错误率 > 2%(持续5分钟)
  • 条件2:P95延迟 > 基线200%
  • 条件3:流量下降 > 30%
  • 触发条件:条件1 AND (条件2 OR 条件3)

4 告警分级体系:避免雪崩的防御工事

4.1 分级原则:基于业务影响而非技术症状

告警分级的目标是确保重要告警得到及时处理,而非处理所有技术异常。分级应基于业务影响程度而非技术严重性。

四级分类体系在实践中证明有效:

  • P0(紧急):业务核心功能不可用,影响大量用户(立即呼叫)
  • P1(高):功能降级或部分用户受影响(2小时内处理)
  • P2(中):潜在问题或边缘功能异常(24小时内处理)
  • P3(低):轻微异常或需要观察(无需立即处理)

4.2 智能抑制与降噪策略

告警抑制是避免告警雪崩的关键技术。

层级抑制确保只收到根本原因告警:

# Alertmanager抑制规则示例
inhibit_rules:
  - source_match:  # 源告警(更严重)
      severity: 'critical' 
    target_match:  # 目标告警(被抑制)
      severity: 'warning'
    equal: ['cluster', 'alertname']  # 相同集群和告警名称

时间窗口聚合将相关告警合并发送:

# Alertmanager路由配置
route:
  group_by: ['cluster', 'alertname']
  group_wait: 10s  # 初始等待时间
  group_interval: 1m  # 同一组告警发送间隔
  repeat_interval: 4h  # 相同告警重复发送间隔

动态静默基于条件自动抑制已知问题:

-- 智能静默规则示例
CREATE RULE auto_silence_maintenance 
WHEN alert_name = 'NodeDown' 
AND description LIKE '%for maintenance%'
DO SILENCE FOR 2h;

4.3 分级通知渠道与升级策略

不同级别的告警需要不同的通知强度和升级路径

通知渠道矩阵

严重等级即时通知1小时内未确认4小时内未解决
P0电话+短信+钉钉升级主管升级总监+运维总监
P1钉钉+短信升级团队主管升级部门主管
P2钉钉每日站会同步周报汇总
P3工单系统每周评审月度优化

人性化通知内容提升响应效率:

{
  "alert_id": "API_HIGH_ERROR_RATE_20250115",
  "title": "【P1】订单服务错误率超过阈值",
  "summary": "订单服务错误率在5分钟内从1%上升到5%,已消耗15%错误预算",
  "impact": "可能导致0.1%用户下单失败,预计影响金额5万元/小时",
  "actions": [
    "1. 检查订单服务日志:https://logs.company.com/order-service",
    "2. 查看相关监控:https://grafana.company.com/d/order-overview",
    "3. 最近部署:订单服务v1.2.3(2小时前部署)"
  ],
  "runbook": "https://runbook.company.com/order-service-high-error-rate",
  "slo_impact": "错误预算消耗速率:3倍(正常阈值:1倍)"
}

5 全栈监控实战:从配置到优化的完整流程

5.1 监控即代码:声明式配置管理

将监控配置版本化,实现可重复、可审计的监控体系。

Prometheus规则即代码

# api_service_alerts.yml
groups:
- name: api_service
  rules:
  - alert: APIHighErrorRate
    expr: |
      # 基于错误预算的智能告警
      sum(rate(api_requests_total{status=~"5.."}[5m])) by (service)
      / 
      sum(rate(api_requests_total[5m])) by (service)
      > 0.05  # 5%错误率阈值
    for: 5m
    labels:
      severity: critical
      service: api-gateway
    annotations:
      summary: "{{ $labels.service }} 错误率超过5%"
      description: "服务 {{ $labels.service }} 当前错误率为 {{ $value }},已持续5分钟"
      runbook: "https://runbook.company.com/api-high-error-rate"

Dashboard即代码(JSON配置)确保监控视图一致性:

{
  "dashboard": {
    "title": "订单服务监控",
    "tags": ["microservice", "order"],
    "timezone": "browser",
    "panels": [
      {
        "title": "API成功率",
        "type": "graph",
        "targets": [
          {
            "expr": "sum(rate(orders_api_requests_total{status=~'2..'}[5m])) / sum(rate(orders_api_requests_total[5m]))",
            "legendFormat": "成功率"
          }
        ]
      }
    ]
  }
}

5.2 监控自愈与自动化响应

自动化响应逐步降低人工干预需求。

基于严重程度的自动化策略

def evaluate_autoremediation(alert):
    """评估是否适合自动修复"""
    if alert.severity == "critical":
        if alert.metric == "cpu_usage" and alert.value > 90:
            return scale_out(alert.service, factor=1.5)
        elif alert.metric == "memory_usage" and alert.value > 95:
            return restart_pod(alert.pod_name)
    return None

渐进式应急响应

  1. Level 1:自动扩容/重启(无状态服务)
  2. Level 2:流量切换/降级(有状态服务)
  3. Level 3:人工决策介入(数据敏感操作)

5.3 监控效能度量与持续优化

监控系统本身需要被监控和优化。

关键效能指标

  • 告警准确率:有效告警比例(目标>90%)
  • 平均检测时间(MTTD):异常发生到告警的时间(目标<1分钟)
  • 平均响应时间(MTTR):告警到修复的时间(目标<15分钟)
  • 告警疲劳指数:人均每日处理告警数(目标<5条)

定期健康度评估

-- 监控系统健康度SQL查询
SELECT
  DATE(timestamp) as day,
  COUNT(*) as total_alerts,
  SUM(CASE WHEN acknowledged = true THEN 1 ELSE 0 END) as acknowledged_alerts,
  AVG(acknowledge_time - trigger_time) as avg_ack_time,
  PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY acknowledge_time - trigger_time) as p95_ack_time
FROM alerts
WHERE timestamp >= NOW() - INTERVAL '30 days'
GROUP BY day
ORDER BY day;

6 组织协同与文化建设

6.1 监控责任共担模型

监控不是运维团队的独角戏,而需要全组织协同

三级责任模型

  • 平台团队:负责监控基础设施稳定性和通用指标
  • 业务团队:负责业务指标和SLO定义
  • SRE团队:负责SLO达标和错误预算管理

监控素养培养

  • 新员工监控工具培训
  • 定期监控案例分享会
  • 监控配置代码审查

6.2 监控质量内建流程

将监控要求嵌入开发流程,而非事后补丁。

开发阶段检查清单

  • [ ] 应用暴露必要的监控指标
  • [ ] 定义清晰的SLO和目标
  • [ ] 设计告警规则和响应流程
  • [ ] 准备运维手册和排查指南

部署流水线集成

# CI/CD中的监控校验
- name: Validate Monitoring
  steps:
    - name: Check Metrics Exposure
      run: |
        curl -s http://$APP_URL/metrics | grep -q "http_requests_total"
    - name: Validate SLO Definition
      run: |
        python scripts/validate_slo.py --manifest slo/manifest.yaml

总结

构建有效的全栈监控与告警体系是一个持续演进的过程,需要技术、流程和文化的协同发展。从SLO定义到告警规则,再到分级抑制策略,每一层都需要精心设计和不断优化。

成功监控体系的核心特征

  1. 业务对齐:监控指标与业务目标紧密关联
  2. 精准告警:基于SLO和错误预算的智能触发
  3. 分级处理:重要信号优先处理,噪音自动抑制
  4. 持续优化:定期评估效果并迭代改进

避免的常见反模式

  • 监控指标丰富但缺乏业务关联
  • 告警数量庞大但有效信号稀少
  • 响应流程冗长但解决效率低下
  • 工具堆砌但缺乏整体设计

监控的终极目标不是收集更多数据,而是提供更好的决策支持。通过本文介绍的方法论和实践,团队可以构建既能够及时发现真实问题,又避免告警雪崩的高效监控体系。


📚 下篇预告
《压力测试方法论——目标设计、场景建模、指标评估与容量规划的完整闭环》—— 我们将深入探讨:

  • 🎯 目标制定:基于业务目标的压测场景设计与成功标准定义
  • 📊 场景建模:真实流量模拟、异常场景构造与容量边界探测
  • 📈 指标体系:性能基线、瓶颈识别与容量规划的数据基础
  • 🔄 优化闭环:从性能测试到系统调优的持续改进机制
  • 🏗️ 容量规划:基于压测结果的资源预估与扩容策略

点击关注,掌握系统性能评估与容量规划的完整方法论!

今日行动建议

  1. 评估当前监控体系的告警准确率,识别主要噪音来源
  2. 为关键服务定义明确的SLO和错误预算消耗机制
  3. 实施告警分级策略,建立基于业务影响的分级体系
  4. 配置告警抑制规则,减少重复告警和告警雪崩
  5. 建立监控效能度量机制,持续优化告警质量

作者:杨易(青风)

在云原生可观测性领域,OpenTelemetry 已经成为事实上的标准。相比于 Java 拥有成熟的字节码增强技术,Go 语言作为静态编译型语言,长期以来缺乏一种成熟、低侵入的自动插桩方案。目前的现有方案主要有:

  1. eBPF:功能强大但主要偏向系统调用层面,对应用层上下文(如 HTTP Header 传播)的处理较为复杂。
  2. 手动埋点:代码改动大,维护成本高,不仅要改业务代码,还得改依赖库的调用方式,显式地在各个关键节点添加 Trace 和 Metrics 逻辑。

为此,阿里云可观测团队和程序语言团队探索了 Go 编译时插桩解决方案,并将其核心能力捐赠给 OpenTelemetry 社区,形成了 opentelemetry-go-compile-instrumentation [ 1] 项目。在和 Datadog、Quesma 等公司的共同努力下,我们发布了首个预览版本 v0.1.0 [ 2]

工作原理

自动插桩工具的核心在于利用 Go 编译器的 -toolexec 参数。-toolexec 会拦截 Go 编译命令,替换成我们的插桩工具。这样,在代码被编译之前,我们就有机会对它进行分析和修改。整个过程可以概括为两个阶段:

1. 依赖分析

在编译开始前,工具会分析应用的构建流程(go build -n),识别出项目中使用的第三方库如 net/http, grpcredis 等。然后,它会自动生成一个文件otel.runtime.go,将对应的 Hook 代码(监测逻辑,后面用 Hook 代码表示)引入到构建依赖中。

2. 代码注入

当编译器处理目标函数时,工具利用 -toolexec 拦截编译,然后修改该目标函数的代码,在函数入口插入一段蹦床代码(Trampoline Code),蹦床代码会跳转到预先写好的 Hook 函数中。

  • 进入函数前(Before):Hook 记录开始时间,提取上下文信息(如 HTTP Headers),启动 Span。
  • 函数执行:执行原有的业务逻辑。
  • 退出函数后(After):Hook 捕获返回值或 Panic,结束 Span,记录耗时。

这种方式的优点是零运行时开销(除了必要的监测逻辑执行时间),因为插桩是直接编译进二进制文件的,不需要像 eBPF 那样在内核态和用户态之间切换,也不需要像 Java Agent 那样在启动时加载。

HTTP 插桩示例

让我们通过一个简单的 HTTP 例子来看看它是如何使用的。

package main
import ...
func main() {
    http.HandleFunc("/greet", func(w http.ResponseWriter, r *http.Request) {
        w.Write([ ]byte("Hello, OpenTelemetry!"))
    })
    log.Fatal(http.ListenAndServe(":8080", nil))
}

手动插桩

需要手动引入 OpenTelemetry SDK,手动创建 Tracer,在 Handler 里手动 Start 和 End Span。

package main
import ...
func initTracer() func(context.Context) error { 
  /* ...几十行初始化代码... */
}
func main() {
    // 1. 初始化 Tracer
    shutdown := initTracer()
    defer shutdown(context.Background())
    // 2. 包装 Handler
    handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // 3. 手动提取 Context,开始 Span
        tracer := otel.Tracer("demo-server")
        ctx, span := tracer.Start(r.Context(), "GET /greet")
        // 4. 确保结束 Span
        defer span.End() 
        // 5. 可能还需要手动记录属性
        span.SetAttributes(attribute.String("http.method", "GET"))
        w.Write([]byte("Hello, OpenTelemetry!"))
    })
    // 6. ListenAndServe 也可能需要包装...
    log.Fatal(http.ListenAndServe(":8080", handler))
}

对于成百上千个接口的微服务,这种改造成本是灾难性的。

自动插桩

  1. 下载工具:到 Release 页面 [ 2] 下载
  2. 编译应用:./otel-linux-amd64 go build -o myapp
  3. 配置运行:export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317" export OTEL_SERVICE_NAME="my-app" ./myapp

编译器会默默地将 HTTP 请求的监测逻辑“织入”到应用二进制文件中。配置好 OpenTelemetry 的导出端点(如 Jaeger 或控制台),运行生成的 server。访问 /greet 接口时, Tracing 数据已经自动生成并上报了,包含了请求路径、耗时、状态码等信息。

从商业化到开源

我们在深度实践 eBPF 技术的过程中,虽然认可其强大,但也发现它难以完美处理应用层上下文。更重要的是,我们不断听到用户反馈,大家对繁琐的手动埋点和高昂的维护成本感到困扰。

为了解决这个痛点,我们开始探索 Go 编译时自动插桩方案,将其上线至阿里云可观测 ARMS 产品 [ 3] ,在这片最严苛的“试验田”里不断迭代,逐步演化成一套成熟的解决方案,不仅能实现零代码修改的链路追踪,还扩展支持了丰富的指标统计、Runtime 监控乃至持续剖析等高级功能,甚至还可以通过自定义扩展的功能完成对企业内部 sdk 的埋点 [ 4]

image

调用链分析

image

持续剖析

这套方案在电商、短剧、AI 视频、汽车等众多领域客户处得到了成功验证。在看到它为用户带来巨大价值、并验证了其稳定性和可行性后,我们决定将其核心能力贡献给 OpenTelemetry 社区,希望它能成为一个普惠的技术。同时,我们与可观测领域的顶尖厂商 Datadog 协作,共同推进,最终促成了这个官方项目 [ 1] 的诞生。

目前项目处于活跃开发阶段,欢迎大家试用、反馈并参与贡献,共同构建更美好的云原生可观测生态。

相关链接:

[1] OpenTelemetry Go 编译插桩项目

https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation

[2] Release 链接

https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/releases/tag/v0.1.0

[3] 阿里云 ARMS Go Agent 商业版

https://help.aliyun.com/zh/arms/application-monitoring/user-g...

[4] 自定义扩展

https://help.aliyun.com/zh/arms/application-monitoring/use-ca...

作者:望宸

每个时代基础设施的变革,都始于对“混乱”的优雅重组。19 世纪,钢铁把不可控的垂直空间变成工程秩序,城市才得以向上生长;20 世纪,电网将分散的能源重新编排,工业生产才不再被河流左右。而如今的 IT 领域,我们正面临一场新的秩序重建,即如何让海量、碎片化、动态变化的观测数据,不再是噪音,而成为可理解、可推理、可优化智能体行为的燃料?

要回答这个问题,我们先简单回溯下:IT 系统的可观测体系是如何走到今天的?

IT 系统中可观测体系的发展

最初,企业面向单一数据类型构建监控体系,CPU 使用率、内存占用、磁盘 I/O……一个个孤立的指标就像烽火台,只能通过局部视角告诉我们“什么地方出了问题”。

但随着微服务、容器技术的普及,系统复杂度呈指数级增长。企业开始意识到:单点指标无法解释全局。于是开始对孤立的数据进行抽象,抽象出 Metrics(指标)、Traces(链路追踪)和 Logs(日志),并进行关联分析:

  • Metrics: IT 系统是否有问题;
  • Traces: 哪里出了问题;
  • Logs: 问题是由什么原因导致的。

发展至今,成为观测体系的三大数据支柱。

image

但从海量、异构、动态变化的数据中准确推理并定位问题,本质上是一个极其困难的逆向工程。数据只是现象,而现象与本质之间往往存在巨大的认知鸿沟 [ 1]

image

Metrics、Traces 和 Logs 这看似完整的三角,实则仍停留在现象观测层面,是 L1 级智能体的典型工作流,人工设计流程节点、人工配置触发、人工调用 API,再把指标、链路、日志喂给 AI,期望它自己找出因果,结果往往是幻觉式归因:把时间上的巧合当作逻辑上的因果。为什么?因为在 AI 面前,缺少对系统本质的建模。

在 AI 时代,加剧了这种模式的挑战。一是 LLM 驱动的应用带来了上下文的碎片化。运维工程师每天要在不同的控制台之间切换,手动拼凑“发生了什么”。这就像在信息高速公路上骑自行车,工具很先进,但认知方式仍是人力驱动。二是相比由工程师写的代码定义的传统 IT 系统,AI 带来了更多的不确定性,指数级提升了原始数据自动化关联的难度,给准确推理并定位问题的挑战添了堵。

image

总结起来,原本的认知鸿沟,被进一步分化成三层新的鸿沟 [ 2]

  • 数据鸿沟:原始数据混杂、碎片化、噪声多,99% 以上可能是无效信息,难以从中有效提取信号。
  • 模型鸿沟:AI 模型存在“黑盒”特性,推理过程难以解释;还可能出现“幻觉”,生成看似合理但不符合事实的结果。
  • 工程鸿沟:每天数 PB 级的数据采集、清洗、存储、计算,对性能、成本、安全性提出极高要求。

数据到建模

让一个没见过电路图的人,从一堆电压表读数中定位并恢复故障服务器,是不现实的。

当前市面上大多数的 AI 运维助手,本质上仍是 L1 级智能体:它们被封装在一个封闭的对话框里,被动响应用户提问,背后是一连串预设的 if-else 规则或简单 RAG 检索。它们没有对系统结构的内生理解,无法主动推理依赖路径,更谈不上安全执行修复操作。

而要迈向 L2 甚至 L3 级智能体,即能自主感知、规划、行动并持续学习的数字员工,就必须为其构建一个结构化的运行时上下文,不然只能靠人的经验来排查、定位和解决问题。这个上下文是经过建模、带有语义、支持查询与推理的图谱。有了这张图,智能体就能避免在数据海洋中盲目打捞,而是在一个有路标、有规则、有边界的城市中穿行。

image

因此,出路不在更多的数据,而在更好的建模。先为 IT 系统建立一张认知地图。这张图要包含实体(主机、服务、数据库)、关系(调用、依赖、部署)、行为(日志事件、性能指标)以及它们之间的语义约束。只有在这张图上,智能体才能像经验丰富的老运维一样,快速定位故障并恢复生产。

image

UModel 正是这张图的建模语言。我们需要从“数据驱动”转向“建模驱动”,从面向现象的观测,转向面向本质的建模,构建一个统一的上下文图谱,这正是 UModel 的使命。

什么是 UModel

UModel(Universal Observability Model)是基于图模型的可观测数据建模方法。

又是图模型,又是建模,一听就很学术。通俗易懂的讲,就是用“画图”的方式,把一堆随机事件之间的概率关系理清楚,让复杂变简单,让模糊变清晰。因此,UModel 旨在通过标准化的数据建模方式,实现可观测数据的统一表示、数据建模与具体存储的解耦,从而实现智能分析。有了 UModel,智能体才能像经验丰富的老运维那样快速定位故障并恢复生产,成为可能。UModel 可以看成是阿里云可观测体系的数据建模基础。

image

总的来讲,UModel 的核心思想,是为可观测领域打造一个认知操作系统,是一套标准化的数据建模方法,旨在弥合前文所述的三重鸿沟,为 AIOps 提供可解释、可扩展、可自动化的基础。

接下来,我们从 UModel 的构成和使用方式来看看它是如何把零散、杂乱的可观测数据,画成一张结构清晰、智能体能理解的图。

UModel 的构成和使用方式

企业习惯于将系统中的每个组件,例如应用、容器、中间件、网关、数据库,视为独立的实体进行监控和管理,并为它们配置仪表盘,设置告警,追踪性能表现。传统的监控和查询工具,无论是基于 SQL 还是 SPL,其核心都是处理二维的、表格化的数据。它们擅长回答关于个体的问题(这个 Pod 的 CPU 使用率是多少?),但在回答关于关系的问题时却显得力不从心。

当面对“这个服务的故障会影响哪些下游业务?”或“要访问到核心数据库,需要经过哪些中间服务?”这类问题时,传统工具往往需要复杂的 JOIN 操作、多步查询,甚至需要工程师结合线下架构图进行人脑拼凑。这种方式不仅效率低下,而且在关系复杂、层级深的情况下几乎无法完成。我们拥有了所有“点”的数据,却失去了一张看清“线”的地图 [ 3]

因此,UModel 将要解决以下四个关键问题:

image

1. 重新定义系统里有什么

通过 Entity 来统一定义所有可观测实体的实例,包括容器实例、服务实例等,例如服务实例 "order-service"、Pod 实例 "web-pod-001"。

2. 对实例进行建模

通过 EntitySet 建立实体集,并进行实体建模。将系统组件抽象为 EntitySet,一个 EntitySet 可对应多个 Entity:

  • 基础设施实体:主机、容器、网络设备、存储系统;
  • 应用层实体:微服务、API 接口、数据库实例、消息队列;
  • 业务实体:用户会话、业务流程、交易订单;
  • 运维实体:部署环境、代码仓库、运维人员。

除了进行实体建模,还需要进行:

  • 数据集建模:将日志、指标、链路追踪、事件和性能剖析等多种可观测数据类型抽象为 TelemetryDataSet,由此衍生出 LogSet、TraceSet、EventSet、ProfileSet、MetricSet 等更具体的观测数据集。
  • 存储建模:Storage 是 UModel 中数据集底层存储的抽象,定义了数据的实际存储位置和访问方式。通过存储建模,UModel 能够统一对接多种存储后端,为用户提供一致的数据访问体验。

3. 对这些实体&实体集进行建联

通过 Link,连接不同的数据集:

  • EntitySetLink 定义 EntitySet 实体间的关系(如服务 A 调用服务 B);
  • DataLink 定义 EntitySet 与 DataSet 之间的关联(如某 Pod 产生哪些日志);
  • StorageLink 定义 DataSet 与 Storage 之间的关联。

在此基础之上,自动生成实体拓扑图和数据关系图。

4. 图查询

图查询可以认为是发挥 UModel 这一可观测基建的关键能力。因为系统的真实形态本就是一张图,那么对它的查询和分析,也应该使用最符合其本质的方式——图查询。

为了实现这一点,我们在 UModel 体系的核心构建了 EntityStore。它采用了创新的双存储架构,同时维护了 entity 日志库(存储实体的详细属性)和 topo 日志库(存储实体间的拓扑关系)。这相当于我们为整个可观测系统建立了一个实时更新的、可查询的数字孪生图谱 [ 3]

基于这个图谱,我们提供了从易到难、层层递进的三种图查询能力,以满足不同用户的需求:

  • graph-match: 为最常见的路径查询场景设计,语法直观,让用户能像描述一句话一样(“A 经过 B 调用了 C”)来快速查找特定链路。
  • graph-call: 封装了最高频的图算法(如邻居查找、直接关系查询),通过函数式接口提供,用户只需关心意图(“找 A 的 3 跳邻居”)而无需关心实现细节。
  • Cypher: 引入业界标准的图查询语言,提供最完整、最强大的图查询能力,支持任意复杂的模式匹配、多级跳跃、聚合分析,是处理复杂图问题的终极武器。

这一整套解决方案,旨在将强大的图分析能力,以一种低门槛、产品化的方式,让智能体实现自主发现、定位故障,并恢复生产成为可能。

过去,运维靠人脑串联孤立的数据和几十个工具;未来,UModel 希望能作为可观测的基础设施,支撑智能体在统一上下文图谱中工作。当可观测数据被建模为可理解、可行动的上下文图谱,AIOps 才真正拥有了落地的土壤。

相关阅读:

[1] UModel 数据治理:运维世界模型构建实践

[2] 从数据孤岛到智能洞察:构建面向未来的 Operation intelligence 体系

[2] 打通可观测性的“任督二脉”:实体与关系的终极融合

Zabbix 介绍

Zabbix 是一个开源的企业级监控解决方案,它可以监控各种网络参数,服务器健康状态,应用程序性能等,并提供灵活的告警机制和丰富的报表功能。

1、Zabbix Server

  • 核心组件,负责接收和处理所有监控数据,生成报警和报表。
  • 需要一个数据库来存储所有配置和监控数据。

2、Zabbix Agent

  • 部署在被监控的设备上,负责收集本地资源和应用数据,并发送给 Zabbix Server。
  • 支持多种操作系统,包括 Linux、Windows 和 Unix。
  • 其中 Agent 分为 Zabbix Agent 和 Zabbix Agent 2,后者是增强版 Agent,支持插件,适合大规模监控。

3、Zabbix Proxy

  • 用于分担 Zabbix Server 的负载,尤其适用于大规模分布式监控。
  • 可以在远程网络中收集数据并转发给 Zabbix Server。

4、Zabbix Web Interface

  • 基于 PHP 的 Web 界面,用于配置、管理和查看监控数据。
  • 提供用户管理、权限控制、仪表盘和报表等功能。

5、数据库

  • 存储所有的配置、监控数据、历史记录等。
  • 支持多种数据库,如 MySQL、PostgreSQL、Oracle、SQLite。

观测云

观测云是一款专为 IT 工程师打造的全链路可观测产品,它集成了基础设施监控、应用程序性能监控和日志管理,为整个技术栈提供实时可观察性。这款产品能够帮助工程师全面了解端到端的用户体验追踪,了解应用内函数的每一次调用,以及全面监控云时代的基础设施。此外,观测云还具备快速发现系统安全风险的能力,为数字化时代提供安全保障。

部署 DataKit

DataKit 是一个开源的、跨平台的数据收集和监控工具,由观测云开发并维护。它旨在帮助用户收集、处理和分析各种数据源,如日志、指标和事件,以便进行有效的监控和故障排查。DataKit 支持多种数据输入和输出格式,可以轻松集成到现有的监控系统中。(注意,请安装完整版 DataKit,Lite 版本 DataKit 没有 Zabbix 相关采集器。)

登录观测云控制台,在「集成」 - 「DataKit」选择对应安装方式。这里使用主机方式安装。

图片

复制一键安装命令,登陆到目标服务器执行该命令即可实现一键安装。

执行 datakit monitor 命令查看 DataKit 运行状态。

图片

指标数据采集

Zabbix API 方式(zabbix >= 5.0)

DataKit 方式

1、配置 pythond 配置文件

进入 DataKit 的配置文件目录 conf.d,进入 pythond 目录,复制 pythond.conf.samplepythond.conf, 修改如下配置:

[[inputs.pythond]]
  # Python input name
  name = 'zabbix_collect'  # required

  # System environments to run Python
  #envs = ['LD_LIBRARY_PATH=/path/to/lib:$LD_LIBRARY_PATH',]
  envs = ['ZABBIX_HOST=http://127.0.0.1/zabbix', 'ZABBIX_USER=Admin', 'ZABBIX_PASSWD=zabbix', 'ZABBIX_VERSION=7.0', 'COLLECT_TYPE=api']

  # Python path(recomment abstract Python path)
  cmd = "python3" # required. python3 is recommended.

  # Python scripts relative path
  dirs = ["zabbix"]

其中 ZABBIX_HOSTZABBIX_USERZABBIX_PASSWDZABBIX_VERSION 填写实际 Zabbix 的地址用户名密码和版本。

保存并退出。

2、复制脚本

进入 DataKit 目录,进入 python.d 目录,创建 zabbix 目录,点击下方链接下载脚本到 zabbix 目录下:

https://static.guance.com/integrations/zabbix/zabbix-collecto...

3、重启 DataKit

datakit service -R

4、检查采集任务,出现 zabbix_collect 任务则说明采集任务开启成功

datakit monitor

图片

Func 方式

1、安装采集脚本

登录 Func,点击「脚本市场」,选择预装脚本市场,点击管理按钮,进入预装脚本市场的脚本列表页。在过滤搜索框中输入 ,过滤出 zabbix 采集脚本。

图片

点击安装按钮,并在弹出的确认框点击确认按钮。点击确认后,在弹出的部署对话框中输入 zabbix 的地址,用户名,密码,以及版本号。确认信息无误后,点击部署启动脚本,即可完成脚本的部署以及采集任务的创建。

图片

2、查看采集结果

登录观测云,点击「指标」 - 「指标管理」,查找 zabbix 指标,看是否采集到。

图片

Streaming 方式(zabbix >= 6.4)

该方式类似于 Prometheus 的 Remote Write,由 zabbix server 主动将数据打给 DataKit,有较高的时效性。

HTTP Server

DataKit 方式

1、配置 pythond 配置文件

进入 DataKit 的配置文件目录 conf.d,进入 python.d 目录,复制 pythond.conf.samplepythond.conf,修改如下配置:

[[inputs.pythond]]
  # Python input name
  name = 'zabbix_collect'  # required

  # System environments to run Python
  #envs = ['LD_LIBRARY_PATH=/path/to/lib:$LD_LIBRARY_PATH',]
  envs = ['ZABBIX_HOST=http://127.0.0.1/zabbix', 'ZABBIX_USER=Admin', 'ZABBIX_PASSWD=zabbix', 'ZABBIX_VERSION=7.0', 'COLLECT_TYPE=stream', 'STREAM_LISTENER_PORT=8000']

  # Python path(recomment abstract Python path)
  cmd = "python3" # required. python3 is recommended.

  # Python scripts relative path
  dirs = ["zabbix"]

其中 ZABBIX_HOSTZABBIX_USERZABBIX_PASSWDZABBIX_VERSION 填写实际 Zabbix 的地址用户名密码和版本。

注意,COLLECT_TYPE 必须为 stream, 可根据需要调整 STREAM_LISTENER_PORT 的值。

保存并退出。

2、复制脚本

进入 DataKit 目录,进入 pythond 目录,创建 zabbix 目录,点击下方链接下载脚本到 zabbix 目录下:

https://static.guance.com/integrations/zabbix/zabbix-collecto...

3、重启 DataKit

datakit service -R

4、检查采集任务,出现 zabbix_collect 任务则说明采集任务开启成功

datakit monitor

图片

5、创建 Zabbix 连接器

登录 Zabbix,点击管理 -> 常规 -> 连接器,点击创建连接器,URL处输入 DataKit 的地址以及 zabbix stream 的监听端口(默认8000),信息类型选择数字和浮点数,点击添加。

图片

6、修改 zabbix_server.conf,修改 StartConnectors 为10,保存并重启 zabbix-server 服务

图片

7、验证指标采集结果

Func 方式

1、安装采集脚本

登录 Func,点击「脚本市场」,选择预装脚本市场,点击管理按钮,进入预装脚本市场的脚本列表页。在过滤搜索框中输入zabbix Stream ,过滤出zabbix Stream采集脚本。点击安装即可。

图片

2、创建URL

登录 Func,点击「管理」 - 「同步 API」(建议使用异步API)- 「新建」, 执行一栏选择刚导入脚本中的 Zabbix Receiver 方法,在参数指定中配置采集任务相关的配置,需要指定 zabbix_hostzabbix_userzabbix_passwdzabbix_version 为实际的值,base64 为 Zabbix 入参,此处填 INPUT_BY_CALLER,点击保存,并复制 url。

图片

3、创建 Zabbix 连接器

登录 Zabbix, 点击管理 -> 常规 -> 连接器,点击创建连接器,URL 处输入上一步创建的 url,信息类型选择数字和浮点数,点击添加。

图片

4、修改 zabbix_server.conf,修改 StartConnectors 为10,保存并重启 zabbix-server 服务

图片

5、验证指标采集结果

Kafka

该方式原理同 HTTP 方式消费指标数据,区别在于该方法引入了 Kafka 组件,需部署一个 HTTP 服务用于接收 Zabbix 的 stream 输出并将消息发送到 Kafka 中,详见https://git.zabbix.com/projects/ZT/repos/kafka-connector/browse,再由消费者订阅 Kafka,进行数据消费。

指标治理

Zabbix 指标数据结构

Zabbix 以主机为维度统计指标和告警。所以所有的指标必然包含主机信息。主机往往绑定一个或多个接口。

Zabbix 的指标(item key) 的形式为 key[param1,param2,param3]。其中 params 分为静态值和变量两种。

vfs.fs.size[{#FSNAME},pused]。其中 keyvfs.fs.size{#FSNAME} 是动态参数,指实际文件系统名,pused 为静态参数,指使用量。

上述采集方式中 zabbix apiStreamingZabbix Agent 2 三种采集方式均默认使用该规则进行指标映射。

建议的指标治理规则

由于 Zabbix 的数据结构跟观测云存在较大差异,为方便指标的使用与管理,结合实际企业用户的部署经验,对于 API 和 Streaming 的采集方式,我们建议 Zabbix 指标数据上传到观测云时按如下规则进行转换:

  • measurement (指标集):zabbix key 第一个 '.' 前的内容。
  • fields (指标):zabbix key + 所有静态参数。如 vfs.fs.size[{#FSNAME},pused],就会变成 vfs.fs.size.pusedsystem.cpu.load[all,avg1],就会变成system.cpu.load.all.avg1
  • tags (标签):zabbix item key 中的所有动态参数小写。同时会添加 hostip 以及 itemtags。如:vfs.fs.size[{#FSNAME},pused]tagfsname

Example:

Zabbix item keymeasurementFieldtags
vfs.dev.queue_size[{#DEVNAME}]vfsvfs.dev.queue_sizedevname
vfs.dev.read.await[{#DEVNAME}]vfsvfs.dev.read.awaitdevname
vfs.dev.read.rate[{#DEVNAME}]vfsvfs.dev.read.ratedevname
vfs.file.contents[/sys/block/{#DEVNAME}/stat]vfsvfs.file.contents._sys_blck__statdevname
vfs.file.contents["/sys/class/net/{#IFNAME}/type"]vfsvfs.file.contents._sys_class_net__typeifname
vfs.fs.inode[{#FSNAME},pfree]vfsvfs.fs.inode.pfreefsname
vfs.fs.size[{#FSNAME},pused]vfsvfs.fs.size.pusedfsname
net.if.in["{#IFNAME}",dropped]vfsnet.if.in.droppedifname
net.if.in["{#IFNAME}"]vfsnet.if.inifname

使用 Pipeline 的 reference table 实现自定义 Tag

场景:对于已有 CMDB 的客户,希望将主机的一些字段富足到指标 Tag 中。如应用、负责人信息等。

方式:使用 Pipeline 的 refertable 功能。

具体步骤:

1、使用 Func 创建一个脚本用于组装 reference table 数据,并发布。数据结构类似于:

{
"table_name": "zabbix-refer-table",
"column_name": ["itemid", "host", "ip", "itemkey"],
"column_type": ["string", "string", "string", "string"],
"row_data": [["1001", "host-1", "10.0.0.1", "vfs.fs.size"], 
    ["1002", "host-2", "10.0.0.2", "vfs.fs.size.pused"], 
    ["1003", "host-3", "10.0.0.3", "vfs.fs.size.pfree"]]
}

更多 reference table 用法,可参考:https://docs.guance.com/datakit/datakit-refer-table/

2、创建同步 API

登录 Func,点击「管理」 - 「同步 API」,点击 新建,在添加同步 API 对话框执行一栏中选择 zabbix-reference-table 获取脚本,点击确定保存脚本,并点击示例,获取请求 API。

图片

图片

3、编辑 DataKit 的配置文件

登录 DataKit 所在服务器(容器部署DataKit 参考官方文档),进入 DataKit 配置目录 /user/local/datakit/conf.d,编辑 datakit.conf 文件,修改 [pipeline] 选项下的 refer_table_url 的值为上一步复制的 Func 接口地址。DataKit 会将 refertable 数据预先加载到本地的 sqllite 中,可以根据 refer table 大小灵活选择是否使用内存模式的 sqllite。保存后重启 DataKit 生效。

图片

4、编辑 Pipeline

登录观测云,点击「管理」 - 「Pipelines」- 「新建 Pipeline」,这里给到一个参考 Pipeline,可根据实际业务情况和 refertable 数据结构灵活调整。

5、查看指标 Tag

超大数据量采集优化策略

  • 对于 Export Directory 方式,可以增加独立的高速 SSD 磁盘,增加单独的 zabbix server 用于数据导出(由于需要访问 zabbix API 和数据库,DataKit 采集 ExportDirectory 会比较占用 zabbix 资源)。调低 ExportFileSize 大小。
  • API 采集方式,可以通过分页查询,减少查询关联表,多线程查询等方式。
  • HTTP stream 方式,可以引入队列进行异步消费或使用异步方法。支持采样收集等方式。
  • 指标治理应先将映射关系生成后存入缓存或内存中,方便快速匹配。为减少 redis 读写压力可以考虑分片缓存或缓存压缩等方法。

各采集方式对比

采集方式采集原理优势劣势
Zabbix APIfunc/datakit使用python代码通过zabbix api获取指标数据。进行指标治理和映射后上传到观测云。可分布式采集,采集过程高可用便于灵活调整采集所需资源。便于指标的灵活治理和映射时效性不高,最大时延可达1minzabbix到func区间数据无法压缩,对该区间网路压力较大。通常需要在func维护采集代码,对采集代码质量要求较高,否则在进行大数据量采集时速度较慢导致时效变差或丢失数据,严重时会影响zabbix性能。
Streaming与zabbix建立网络长连接(HTTP server/Kafka)消费zabbix产生的history和event数据时效性高可分布式采集,采集过程高可用便于灵活调整采集所需资源。便于指标的灵活治理和映射zabbix到func区间数据无法压缩,对该区间网路压力较大。
Zabbix 转 Prometheus部署独立服务通过调用zabbix api将zabbix指标数据暴露成Prometheus metric接口供datakit采集集成简单,可以使用datakit现有能力。需要维护独立的转换服务。转换服务与zabbix间网络转发无压缩,对网络压力较大。无法灵活进行指标治理和映射。

总结

监控数据的集成是一个复杂的综合性工作,本文所展示方案所适用场景需相关运维工程师根据实际情况进行调整。

摘要
软件定义汽车(SDV)的时代,空中升级(OTA)能力已从“功能”演进为汽车的“生命线”。它承载着功能迭代、安全修复与用户体验提升的核心使命。然而,面对千万级的庞大车队、GB级的升级包体、跨洲际的网络环境以及绝对零容忍的升级安全要求,传统OTA架构在效率、可靠性与智能化方面面临严峻考验。本方案提出,以Redis企业版为核心实时数据引擎,构建新一代智能OTA平台。该平台不仅能够实现升级包的全球分钟级同步与智能边缘分发,更能支撑全链路可观测的灰度发布与秒级触达的安全回滚,将OTA从一项高风险运维活动,转变为稳定、高效、可运营的数字化服务。

一、OTA演进下的核心挑战
现代智能汽车OTA已超越简单的“推包安装”,成为一个复杂的分布式系统工程:

  • 挑战一:分发规模与成本的指数级增长:单一车型的软件版本可能超过100GB,而一次全量升级活动需覆盖百万辆汽车。采用中心化分发将产生天量的跨境带宽成本与漫长的下载时间,用户体验难以保障。
  • 挑战二:灰度发布与流量调控的精细化管理:为控制风险,升级必须遵循从1%到100%的精细化灰度节奏。平台需要实时、动态地管理海量车辆的分组、策略与状态,并能根据故障指标(如安装失败率、系统崩溃率)自动决策暂停或回滚,这对状态管理和决策实时性要求极高。
  • 挑战三:升级安全的“零信任”与“可追溯”:升级过程必须保证数据的完整性(包体未被篡改)、原子性(要么完全成功,要么完全回退)和可审计性(每一步操作皆有记录)。任何环节的纰漏都可能导致车辆“变砖”,引发大规模安全事故。

二、Redis企业版:OTA系统的智能数据中枢
Redis企业版凭借其独特的技术组合,成为化解OTA复杂性的战略性组件:

  • 全球智能分发网络基石:Active-Active地理分布式部署支持升级包元数据与任务指令在全球多个数据中心间实时同步,为构建私有化、低延迟的内容分发网络提供了数据层基础。结合自动分层(Auto Tiering) ,可将高频访问的最新升级包置于内存,将历史版本透明下沉至SSD,实现性能与成本的最佳平衡(存储成本降低约70%)。
  • 高性能、高可靠的任务编排引擎:Redis Stream 与 Sorted Set 数据结构是构建复杂任务队列的理想选择。它们能够以毫秒级延迟管理数百万车辆的升级状态流转(待推送、下载中、安装中、成功/失败),并支持基于优先级、区域、车型等多维度的灵活调度。
  • 全链路可观测性与自动化触发器:Redis TimeSeries 模块可高效存储和聚合全量升级过程的性能指标与日志。RedisGears 的函数功能允许在数据库内部设置复杂触发器,例如,当“安装失败率”在5分钟内超过0.1%时,自动暂停当前批次任务并告警,实现从“监控”到“动作”的闭环自动化。
  • 坚如磐石的数据持久化与高可用:通过同步持久化(AOF with fsync always) 与跨区域复制,确保每一次任务分配、每一条车辆状态更新都不会丢失。其99.999%的高可用性保障了OTA管理控制面自身7x24小时不间断服务。

架构方案:云边协同的智能OTA平台
以下架构描绘了以Redis企业版为“智能中枢”的下一代OTA平台,如何协同云端与边缘,完成从包管理到安全回滚的全流程。

核心工作流解析:

  1. 升级包全球同步与边缘预热:

    • 新的升级包在“包工厂”生成并完成签名后,其元数据(版本号、车型、依赖、哈希值)通过 Active-Active 同步至全球所有区域的Redis集群。
    • 智能调度器根据各区域车辆分布,将包体文件提前推送至各边缘节点Redis集群的SSD层。当车辆发起下载请求时,边缘节点可快速从本地SSD或内存提供服务,下载速度提升300% 以上。
  2. 精细化灰度发布与实时调控:

    • 运维人员在控制台创建升级任务,定义灰度批次(如:内部员工1% -> 先锋用户5% -> 全面推送)。该任务被转化为一个主任务Stream和多个批次Sorted Set(按车辆VIN分片)。
    • 智能调度器作为消费者,从Stream中读取任务,并根据规则从相应批次的Sorted Set中获取车辆列表,通过Pub/Sub或指令通道向车辆下发升级通知。
    • 车辆端上报的每一个状态(下载进度、安装结果)都实时更新到该车辆对应的状态Hash中。RedisGears 脚本持续监控聚合指标,一旦触发预设规则(如失败率超标),则自动修改任务状态或触发回滚流程。
  3. 安全回滚与全链路追溯:

    • 回滚被设计为一个标准的“升级任务”,其回滚包已在边缘节点就绪。当自动或手动触发回滚时,调度器会优先为受影响车辆创建高优先级的回滚任务。
    • 整个升级生命周期的所有事件(任务创建、指令下发、状态变更、异常告警)均作为时间序列数据存入 Redis TimeSeries,并与具体的车辆VIN、任务ID关联,提供毫秒级精度的全链路追溯能力,满足最高级别的审计要求。

    关键场景与价值量化
    image.png

结语
在软件定义汽车的竞赛中,OTA的效能直接决定了车企数字化运营的高度与速度。Redis企业版通过将实时数据同步、智能任务编排、多模型存储与边缘计算能力深度融合,为车企提供了一个不仅强大而且“聪慧”的OTA数据基座。这不仅仅是技术的升级,更是运营理念的革新——从被动的、高风险的手动操作,迈向主动的、数据驱动的、全球一体化的软件服务交付。选择Redis企业版,即是选择为未来十年海量车队的软件生命周期管理,构建一个可靠、高效且充满智能的“指挥中心”。

前言

在数字化运维与业务监控的实践中,仪表板(Dashboard)与汽车的仪表盘同等重要,它不仅是数据可视化的载体,更是团队快速定位问题、洞察数据趋势的核心工具。观测云在平台中内置了大量通用组件、云服务的仪表板模板。但如果你希望从零开始构建个性化的仪表板,又或者对自己绘制的仪表板不够满意,那么这篇文章将教授你几个小技巧,帮助你有效提升仪表板的质量。

观测云简介

观测云是一个统一实时监测平台,它提供全面的系统可观测性解决方案,帮助用户快速实现对云平台、云原生、应用及业务的监控需求。观测云的核心功能包括:基础设施监测,日志采集和分析,用户访问监测(RUM),应用性能监测(APM),服务可用性监测(拨测),安全监测,智能监控等等。这款产品能够帮助工程师全面了解端到端的用户体验追踪,了解应用服务的每一次调用,以及全面监控云时代的基础设施。此外,观测云还具备快速发现系统安全风险的能力,为数字化时代提供安全保障。更多信息可以访问观测云官网:https://www.guance.com

基础仪表板的绘制

让我们进入到观测云,创建一个属于您自己的仪表板。首先,你需要找到仪表板的入口「场景」-「仪表板」,点击「新建仪表板」-「新建空白仪表板」。

图片

其次,可以从侧滑窗口中选择适合展示数据的图表类型,拖拽到左边的空白画布中。

图片

以常用的「时序图」为例,拖动到画布中即可打开「新建图表」弹窗,此时通过数据筛选控件来选择需要展示的指标。

图片

如图所示,我们已经展示了一条指标曲线,它代表的含义为:指标集为 cpu,指标名为 usage_total,按照 host 进行分组并统计 Avg 平均值,只显示 host=DESKTOP-F9E75IG 的值(过滤条件),点击右下角的保存即可。

图片

此时你已经完成了第一张图表的制作,通过一张张图表的叠加,你很快能得到一个完整的仪表板,不过它看上去有些简陋,我们需要更多技巧对仪表板的美观程度和易读性进行优化。

图片

仪表板的优化

新增标题和描述

恰当的标题能让用户第一时间知道图表展示的指标及其含义,而图表的描述能够起到有效补充说明。我个人的习惯是将图表名设置为指标的英文名,然后在「描述」中补充该指标的中文含义。如下所示:

图片

保存生效的效果如下,图表左上角将展示标题,而鼠标 hover 到帮助按钮上则会悬浮显示描述。

图片

数据单位

一部分指标在采集到观测云后没有单位,因此在绘制仪表板时需要注意补充单位。

图片

别名

图表的曲线会显示对象的名称,并且对象名称会随着分组条件的增多而变得复杂。例如下图,由于添加了 namespace,pod_name 等多个分组条件,对象名称显得很长,很不直观。好在我们可以通过配置「别名」来简化对象名称的显示。

图片

在图表配置的「别名」处,我们选择对应的指标序列,并用 {{}} 将分组条件包起来作为变量,例如下图中的分组条件 pod_name 就写为 {{pod_name}} ,效果如下所示。

图片

我们也支持用多个变量作为别名,写法为 {{分组条件1}}-{{分组条件2}} ,例如 {{namespace}}--{{pod_name}} ,效果如下图所示:

图片

现在,曲线上显示的对象名称已经比原始的名称简洁、清晰了很多。

图例

图表默认没有带上图例,除非将鼠标 hover 上去,否则无法看到什么颜色的曲线代表哪一个对象,如下图的左侧所示。而「图例」则可以将对象的名称和统计值显示到图表中,如下图的右侧所示。

图片

添加图例的方式如下,可选择将图例放置在图表的底部或者右侧,并显示单个或者统计值,将 Avg、Max、Last 一起显示出来是个不错的选择。

图片

分组

当仪表板中需要展示很多张图表时,使用「分组」来将不同含义的图表分门别类地归类就十分有必要了,这会让仪表板的显示更具有条理,用户能通过分组快速找到自己关注的图表,如下图所示。

图片

给仪表板添加分组时,只需要在侧滑菜单中找到「分组」这个图表类型,拖动到左侧画布即可。

图片

取一个有意义的分组名称,选择一个与众不同的颜色,保存即可。

图片

下图即为新创建的分组,后续添加的图表即可拖动到该分组下。

图片

锁定时间

如果你希望每次进入到仪表板,都查看到固定时间区间(例如最近1天)的数据,应该如何实现呢?

我们很容易注意到仪表板的时间控件,可以在这里固定整个仪表板的时间。

图片

如果需要将单个图表的时间进行固定,而其他图表的时间则跟随仪表板的时间控件,也很好实现。我们进入单个图表的编辑窗口,打开「高级配置」,将时间锁定为指定区间即可。

图片

配置完成后,这个图表的右上角会出现你锁定的时间区间,该时间不受仪表板整体的时间区间控制,如下图所示。

图片

视图变量

视图变量允许用户通过下拉菜单来选择特定对象的监控数据,从而根据自身需求动态筛选和分析数据。如下图所示,该仪表板包括了 Cluster、Namespace 和 Node 三个视图变量,用户可以进行自由筛选。

图片

我们首先添加一个简单的视图变量,需求是通过选择 host_ip 来过滤单台主机的数据。在仪表板中点击「添加视图变量」。

图片

图片

host_ip 是 cpu 相关指标数据的一个标签,因此我们从指标类型- CPU指标集里面选择 host_ip 作为视图变量的来源,然后将「变量名」和「显示名」都与之保持一致,保存窗口即可。

图片

此时返回仪表板,就会看到刚才添加的 host_ip 视图变量,从下拉菜单中可以筛选主机 IP。如下图所示:

图片

你可能会发现筛选结果之后,对下方的图表没有任何作用,因为我们还需要在图表中的过滤条件配置变量,使仪表板的额视图变量与图表的过滤条件进行联动。再次进入图表编辑界面,添加一个过滤条件,字段选择为 host_ip,值选择「视图变量」,如下图所示。

图片

返回仪表板,这时仪表板的视图变量 host_ip 就可以与图表中的监控对象 host_ip 进行联动了。我们可以通过下拉菜单来筛选不同的主机,从而观察不同主机的监控指标。

图片

如果是有多个视图变量,且视图变量之间有依赖关系,例如我们针对 Pod 的监控是首先选择 namespace,再选 Pod,那我们又应该如何配置呢?这就要用到「级联」的写法,让我们来再来回顾一下刚才本章开头的那张图片。选择 Cluster 后,Namespace 的值随 Cluster 的取值而联动,Node 的值又随 Namespace 的取值而联动。

图片

我们研究一下这组视图变量的写法,不难发现规律是在 show_tag_value 函数的后面跟随了一个 {key=value} 的过滤条件,其固定写法为 {key='#{value}'} ,key 和 value 都取自上一级的变量名,表示该变量随上一级变量的值而联动。如下图所示,当用户在界面上选择了 cluster_name_k8s 的值后,该值就会传入 namespace 作为过滤条件,从而实现变量联动。

图片

图片

小结

通过上面的几个小技巧,相信你已经跃跃欲试将自己的仪表板更上一层楼了。在得到令自己满意的仪表板后,你可以选择将仪表板开放给团队、配置为定时报告、投放到大屏幕、关联到日志或链路查看器中,又或者在接收到告警时一键查看这张仪表板。我们非常期待你通过仪表板来向你的团队/客户呈现数据的价值。

公司收购 Langfuse,正式进军 LLM 可观测性 (LLM observability) 领域,并推出原生 Postgres 服务,以统一事务型与分析型工作负载。

旧金山 — 2026 年 1 月 16 日 — 实时分析、数据仓库、可观测性 (observability) 以及 AI/ML 领域的领导者 ClickHouse 今日宣布完成 D 轮融资,融资金额达 4 亿美元。本轮由 Dragoneer Investment Group 领投,Bessemer Venture Partners、GIC、Index Ventures、Khosla Ventures、Lightspeed Venture Partners、T. Rowe Price Associates, Inc. 管理的账户,以及 WCM Investment Management 共同参与。

此次融资正值 ClickHouse 持续且加速增长之际。目前,公司通过全托管服务 ClickHouse Cloud 已服务超过 3,000 家客户,年度经常性收入 (ARR) 同比增长超过 250%。在过去三个月中,Capital One、Lovable、Decagon、Polymarket 和 Airwallex 等客户开始采用该平台或扩大了现有部署。这些新客户加入了 ClickHouse 已建立的客户群体,其中包括 Meta、Cursor、Sony 和 Tesla 等 AI 创新者及全球知名品牌。

“ClickHouse 的初衷就是为最严苛的数据工作负载提供卓越的性能和成本效率,而今天的增长势头正是这一战略的最好证明,”ClickHouse 首席执行官 Aaron Katz 表示。“面向未来,我们正在支持统一的事务型与分析型工作负载,让开发者能够在坚实的技术基础之上构建各种由 AI 驱动的应用。同时,我们也在拓展产品能力,引入 LLM 可观测性,帮助 AI 应用构建者在进入生产阶段时,更好地评估 AI 输出的质量和行为。新的资金支持,加上持续的产品执行力,使我们有能力在 AI 时代打造领先的数据与 LLM 可观测性平台。”

图片

对大规模数据基础设施与 AI 的高度确信投资

Dragoneer 成立于 2012 年,由 Marc Stad 创立,采用高度精选、以研究为核心的方法,专注于与少数具有品类定义意义的公司建立长期合作关系。过去十年中,该公司投资了多家领先的数据平台以及多家基础性的 AI 公司。

随着 AI 系统逐步从实验走向生产,对底层数据基础设施提出了更高要求。AI 驱动的应用会产生远高于以往的查询量,对延迟更加敏感,同时还需要持续的评估能力和可观测性。在这样的背景下,真正的价值正越来越集中到那些能够支撑大规模、数据密集型生产工作负载的基础设施平台之上。

“每一次重大的平台变革,最终都会回馈那些最贴近生产环境的基础设施公司,”Dragoneer Investment Group 合伙人 Christian Jensen 表示。“当模型能力不断提升,真正的瓶颈就转移到了数据基础设施上。ClickHouse 的突出之处在于,它能够在大规模 AI 系统运行时,提供所必需的性能、效率和可靠性。”

在严谨的评估过程中,Dragoneer 认为 ClickHouse 已成为现代数据技术栈中具有品类定义意义的领导者。该平台广泛支持关键任务级的实时工作负载,深度嵌入于始终在线、面向客户以及 AI 驱动的系统之中。

ClickHouse 的增长不仅来自对现有系统的替代,更来自对全新工作负载的支持。通过在大规模场景下实现高性价比的实时分析,ClickHouse 让许多过去因延迟或成本受限而无法落地的应用场景成为可能。与主要服务内部分析团队的许多数据基础设施平台不同,ClickHouse 经常直接嵌入到面向终端用户的产品中,在这些场景下,性能和可靠性会直接影响用户体验。

“我们寻找的是在系统绝不能停机时依然值得客户信赖的平台,而 ClickHouse 一直展现出这样的能力,”Jensen 补充道。

LLM 可观测性:ClickHouse 通过收购 Langfuse 进入该市场

ClickHouse 正式宣布收购开源 LLM 可观测性平台 Langfuse。与关注系统健康和性能指标的传统可观测性不同,LLM 可观测性关注的是如何确保非确定性、日益复杂的 AI 系统能够输出准确、安全且符合用户意图的结果。随着 AI 系统不断深入生产工作流,LLM 可观测性已成为构建和运营 AI 应用团队不可或缺的一环。

Langfuse 开源项目增长迅速,截至 2025 年底,已获得超过 2 万个 GitHub Star,每月 SDK 安装量超过 2,600 万次。

“我们之所以在 ClickHouse 之上构建 Langfuse,是因为 LLM 可观测性和评估本质上就是一个数据问题,”Langfuse 首席执行官 Marc Klingen 表示。“如今作为一个团队,我们能够提供更加紧密的一体化体验:更快的数据摄取、更深入的评估能力,以及从生产问题到可量化改进之间更短的闭环。”

图片

Langfuse 联合创始人 Clemens Rawert、Marc Klingen、Max Deichmann

原生 Postgres 服务:ClickHouse 面向 AI 构建者推出统一数据技术栈

ClickHouse 同时宣布推出一个与自身平台深度集成的企业级 Postgres 服务。为了支撑既需要事务处理又需要分析能力的现代实时 AI 应用,ClickHouse 打造了一套统一的数据技术栈,其中包括由 NVMe 存储支撑、具备原生 CDC 能力的高性能可扩展 Postgres。用户只需几次点击,就能将事务数据同步至 ClickHouse,从而解锁最高可达 100 倍的分析性能提升。借助由原生 Postgres 扩展提供支持的统一查询层,开发者可以构建横跨事务与分析的应用,而无需维护多个独立系统。该服务由 ClickHouse 与开源云公司 Ubicloud 联合打造,Ubicloud 团队在 Citus Data、Heroku 和 Microsoft 拥有丰富的产品与工程经验。

“Postgres 与 ClickHouse 在架构上天然互补,是 AI 应用不可或缺的组成部分。通过合作,我们为团队交付了一套真正的一体化技术栈,让生产级 Postgres 负责事务处理,让 ClickHouse 专注分析,并作为一个整体协同运行,”Ubicloud 联合首席执行官兼联合创始人 Umur Cubukcu 表示。“我们非常高兴能在 Ubicloud 与 ClickHouse 携手合作,这正是开源生态系统成功的方式:由值得信赖的团队打造一流产品,并共同成长。”

图片

Ubicloud 联合创始人 Umur、Ozgun 和 Daniel

持续的全球扩张与产品动能

在完成融资并收购 Langfuse 的同时,ClickHouse 也在持续扩展其全球布局和生态体系。过去一年中,公司通过与 Japan Cloud 的合作进入日本市场,并宣布与 Microsoft Azure 围绕 OneLake 建立合作关系。ClickHouse 还在旧金山、纽约、阿姆斯特丹、悉尼和班加罗尔举办了多场用户活动,吸引了超过 1,000 名参与者,演讲嘉宾来自 OpenAI、Tesla、Capital One、Ramp 和 Canva 等公司,并连续第二年举办了 AWS re:Invent Chainsmokers 客户活动。

一系列近期产品进展进一步强化了 ClickHouse 在分析、AI 与可观测性交汇领域的地位。公司在数据湖支持方面持续投入,新增了对 Apache Iceberg、Delta Lake 以及主流数据目录的兼容性。同时,平台扩展了全文搜索能力,这对于包括 AI 可观测性在内的各类可观测性场景正变得愈发关键。此外,ClickHouse 还引入了轻量级更新机制,以支持需求更高、负载更复杂的 AI 驱动型应用。根据近期基准测试结果,ClickHouse 持续提供行业领先的性价比,在性能与成本比上超越主流云数据仓库。

借助 D 轮融资、对 Langfuse 的收购以及原生 Postgres 服务的推出,ClickHouse 已做好加速增长的准备,并将进一步巩固其作为统一数据平台与 AI 可观测性平台的战略地位。

了解更多:

关于 ClickHouse:

 

ClickHouse 是一个快速的开源列式数据库管理系统,专为大规模实时数据处理与分析而设计。ClickHouse Cloud 以高性能为核心,提供卓越的查询速度与并发能力,非常适合需要从海量数据中即时获取洞察的应用。随着 AI 智能体 (AI Agent) 越来越多地嵌入软件系统,并生成频率更高、复杂度更大的查询请求,ClickHouse 提供了一个高吞吐、低延迟的引擎,专门用于应对这一挑战。ClickHouse 受到 Sony、Tesla、Memorial Sloan Kettering、Lyft 和 Instacart 等领先企业的信任,帮助团队通过一个可扩展、高效且现代化的数据平台释放数据价值并做出更明智的决策。欲了解更多信息,请访问 clickhouse.com。

关于 Dragoneer Investment Group:

Dragoneer 是一家以增长为导向的投资机构,资产管理规模超过 300 亿美元。该机构与在公有和私有市场中打造品类定义型公司的创始人及管理团队长期合作。迄今为止,已有 50 多家 Dragoneer 投资的公司成功上市。其投资组合包括 Airbnb、Amwins、Atlassian、Databricks、Datadog、Meta、Nubank、OpenAI、Revolut、ServiceNow、Snowflake、Spotify 和 Uber。

关于 Langfuse:

Langfuse 是一个用于构建、测试和监控 LLM 应用及 AI 智能体的开源平台。团队使用 Langfuse 来追踪和调试智能体工作流、运行评估,并持续衡量和改进生产环境中 AI 输出的质量。Langfuse 既提供托管云服务,也支持在生产规模下自托管。作为增长最快的 LLM 工程平台之一,Langfuse 拥有 20,470 个 GitHub Star、每月超过 2,600 万次 SDK 安装量以及 600 多万次 Docker 拉取,并受到《财富》50 强中 19 家公司和《财富》500 强中 63 家公司的信任。欲了解更多信息,请访问 langfuse.com。

关于 Ubicloud:

Ubicloud 正在打造开源版的 AWS,在裸金属和公有云之上交付核心云服务。Ubicloud 由打造分布式 PostgreSQL 的 Citus Data 团队创立 (该公司已被 Microsoft 收购)。其旗舰数据库产品 Ubicloud PostgreSQL 提供企业级托管 Postgres 体验,并具备行业领先的性价比。Ubicloud 在 AI、计算、PostgreSQL 和 Kubernetes 等领域提供的服务每周支撑超过 100 万台虚拟机运行,可帮助客户将云成本降低多达 70%。Ubicloud 获得了 Y Combinator 及其他知名硅谷投资机构的支持。欲了解更多信息,请在 X 上关注 Ubicloud @ubicloudHQ,或访问 ubicloud.com。

/END/

征稿启示

面向社区长期正文,文章内容包括但不限于关于 ClickHouse 的技术研究、项目实践和创新做法等。建议行文风格干货输出 &图文并茂。质量合格的文章将会发布在本公众号,优秀者也有机会推荐到 ClickHouse 官网。请将文章稿件的 WORD 版本发邮件至:Tracy.Wang@clickhouse.com。

撰稿:李文朋

编辑:王一鹏

最近,“Meta 以 20 亿美元收购 Manus”的消息传得很热。

Manus 曾被嘲讽“套壳”,但业内人士认为,虽然 Manus 整体架构和理念不算颠覆式“新”,但在任务连通性、容错、回退机制等实现上,极度考验工程能力,远不是“换个皮”那么简单。

 

在 Manus 创始团队与媒体的最近一次访谈中,联合创始人季逸超提出目前 Manus 定位只是一位“通用型助手”,帮普通人把复杂工作流做完,不能完全替代用户本身。这也是因为在 ToC 场景里,普通用户对体验要求很苛刻——慢一点不行,错一点也不行,Manus 团队很清楚这一点。

 

如果说 ToC 用户已经够“难伺候”,那 ToB 客户对 Agent 的要求只会更高:一方面,企业希望 Agent 真正“上生产”,意味着要接入复杂的权限体系、业务系统和合规要求;另一方面,任何一次错误操作、脏数据写入、流程走错,带来的代价都远比个人用户高得多。

 

所以会看到,过去一年很多企业在这条路上吃了不少苦:投入人力、投入预算,最后做出来的 Agent 用不了。MIT《2025 年商业 AI 现状》报告里提到,约 95%的生成式 AI 试点项目很难进入生产环境,很多最终都卡在上线前后。

 

问题出在哪?就在于这些一连串的工程难题。

 

比如代码标准不统一、系统接口五花八门、工具调用不稳定、开发周期被拉得很长;数据资产混乱、想用调不出;安全合规和权限管理一碰就痛;甚至出现“越用越退化”的优化难题。

 

说到底,并不是模型不行,也不是工程师不会做,而是整个 Agent 开发还不够成熟,大家还在摸索阶段,没有提前规划一套更清晰、更稳定的“做法”。

 

所以,国内的云厂商开始认真思考一个问题:到底怎样才能帮助企业把 Agent 的难题解决掉?有没有一种更适合落地的开发范式?

 

2025 云栖大会上,阿里云 CTO 周靖人就曾提出过「AI 时代的 Agent 开发范式」。而在 1 月 7 日,阿里云百炼对“1+2+N”体系和开发范式做了一次更系统的升级,把它落成一个工程化的体系。

 

这套“1+2+N”体系的想法并不复杂,本质是把 Agent 落地拆成三层:

 

稳底座(1):把模型和云资源这些基础能力做稳定、可扩展、可治理。地基不稳,再漂亮的 Agent 也只能停在 PoC。

 

定范式(2):给企业一套把 Agent 做成“工业产品”的开发与运行体系,能开发、能部署、能迭代,交付不再反复折腾。

 

理杂活(N):把真实业务里最难、最碎、但最致命的集成、权限、评测、成本这些“脏活累活”,做成可插拔的组件,让企业能按需拼装。

 

从这个角度看,这次阿里云百炼迭代背后体现的是一种更务实的方向:要用更工业化的方式,让企业的 Agent 在真实业务里跑起来。

 

一、“N”:通用大方案,不如啃硬骨头的“高手组件”

 

经过大量 Agent 的试错,企业如今在启动一个 Agent 项目时,最先拎出来掂量的往往不是模型,而是数据怎么处理与调用、安全问题能不能搞定、上线后怎么评估和优化。

 

这些硬问题不先解决,再漂亮的 Agent 构想也很难真正走进生产环境。而在阿里云百炼的“1+2+N”体系里,“N”恰恰就是优先来啃这些硬骨头的。

 

更关键的是,这一次“N”做了很大的升级:它把落地过程中那些最常见、最难啃、最容易反复踩坑的环节抽象出来,沉淀成一组可插拔、可组合的模块化组件。Agent 开发的难题看起来五花八门,但很多难题其实有共通的解法,可以被提炼、被复用。

 

“N”组件的存在,可以让企业缺什么就用什么、按需组合,把时间花在业务价值上,而不是重复造轮子。

 

这次升级里,一个直观的变化在应用广场:阿里云百炼把同类 Agent 做成了十多个精选合集,提供新的多模态模板,支持免登录体验,也能一键调用 API,把“试试到跑起来”的路径压得更短。

 

真正决定“能不能落地”的挑战,还有数据连接与知识管理、安全与权限控制、可观测与持续优化等问题。

 

企业做 AI 转型,数据治理永远是“卡脖子”环节。尽管大家都知道数据重要,但真落到工程上,标注、清洗以及让模型读懂私有数据的成本极其高昂。

 

目前,企业内部约 80%的数据以 PDF、图像、视频或会议录音等非结构化形式存在。据 IDC 预测,这些数据多处于“不可检索、不可复用”的沉睡状态。随着全球数据量预计在 2026 年激增至 221ZB,如何将这些碎片资产转化为 Agent 可调用的知识,成为企业发展的关键。

 

阿里云百炼的思路是把这条链路做成“工具化”:用多模态 RAG、多模态数据库、Connector 连接器,把数据处理变成更工业化的流水线。

 

多模态数据库通过智能解析、分类归档,打破图像/音频/视频等模态壁垒;多模态知识库 RAG 不再局限于纯文本,支持数十种格式的高精度解析,包括扫描件 PDF、复杂报表、音视频会议记录等。

 

在 Workflow 层面添加多模态文件处理与生成节点,同时提供覆盖 Chunking、Embedding、(多模态)Embedding、Rewrite、Retrieval、ReRank 等在内的向量化全流程能力,用于检索与消化企业数据资产。

百炼平台还提供开箱即用的 RAG 工具,企业无需自建复杂的向量库与检索链路,也能获得高性能的知识检索与生成能力。

 

把知识库做起来只是第一步。要让 Agent 真正有用,它就得能接入实时数据。然而,长期以来 ERP、CRM 等异构系统间的集成成本高昂,导致 65%的企业受访者认为业务系统沦为新的“数据孤岛”。

 

百炼平台推出的 Connector(企业级数据连接器),就是想把这个门槛降到最低。

 

通过 Connector,企业可以一键对接飞书、语雀、MySQL 及 OSS 存储;连上之后,这些数据既能直接喂给知识库,也能驱动工作流跑起来;平台还提供数十种预置工具(Tools),支持用自然语言直接查询或检索数据等。

 

当然,数据一旦接进来了,真正棘手的问题也随之出现:权限边界与责任归属难题。

 

长期以来,很多 Agent 在企业业务中多以匿名形式存在。这种“身份透明”导致操作链路难以溯源,不仅无法明确执行指令的主体,更埋下了越权操作的隐患。

 

为此,百炼平台引入 Agent Identity 组件,将 Agent 纳入企业身份治理的范畴。

 

通过集成 Okta、EntraID 等主流系统,平台为每个 Agent 分配数字身份,使其行为从孤立的匿名调用转变为绑定主体、可供审计的合规操作。

 

百炼平台也将传统的“常驻权限”升级为“按需授权”仅在执行任务时获得短期令牌,任务结束权限即刻回收。

 

配合权限降级机制,Agent 的边界被严格限制在用户授权范围内,确保无法越权。全链路审计日志则让每一步决策都透明可查,解决了企业“敢不敢给权限”的顾虑。

 

针对执行环境安全,百炼平台也构建了 Sandbox(沙盒)物理隔离屏障。当 Agent 处理外部代码或第三方数据时,系统可以利用虚拟化技术将其限制在独立空间内,精简系统调用并严控网络访问。

 

每一个任务会话均在“即用即弃”的容器中运行,执行完毕立即重置,彻底阻断了数据残留与交叉污染。平台同步引入实时监控与会话回放,一旦监测到异常行为将立即终止任务。这种设计为 Agent 提供了“受控下的自由”:在屏障内保持灵活性,在边界外确保系统安全。

 

而当 Agent 真正跑进业务之后,新的共性难题也会浮现:怎么评估、怎么持续改进。

 

与传统软件不同,Agent 的执行具有非确定性:即便输入相同,也可能因模型的随机性、工具调用顺序或上下文波动产生不同的输出。这导致开发者难以追踪 Agent 决策逻辑,在任务失败时无法精准定位是模型、工具还是流程缺陷。

 

百炼平台通过 Trace(可观测)与 Evaluate(评估)组件,实现了从“黑盒”到“透明”的转变。

 

Trace 组件提供完整的执行轨迹追踪,清晰复现了从思考(Thought)、行动(Action)到观察(Observation)的每一步。开发者可以判断哪一步耗时最长、哪个工具失败率最高,或是在哪个环节陷入了逻辑死循环。

 

结合 Token 消耗、响应速度等量化指标,这些数据可通过 Grafana 进行可视化监控,构建起实时的生产环境观测能力。

 

基于此,Evaluate 则建立了体系化的评价标准。

 

在任务完成度评价方面,百炼平台可以通过衡量目标满足率与输出质量对 Agent 进行评分;并支持“模型评测(LLMasJudge)”、专家打分与人工复查相结合的混合模式,对失败任务进行深度归因。

 

可以说,基于日志(Logs)、指标(Metrics)与追踪(Traces)的三大支柱,百炼平台设计了一个“评估—优化—验证”的持续迭代闭环。这种由数据驱动的迭代机制,也驱动着 Agent 实现“越用越好用”的工程闭环。

 

相比于自建底层架构,直接调用百炼平台的成熟组件能让开发周期缩减数倍。以 RAG 系统为例,以往搭建搜索和解析链路需要数周,现在利用多模态 RAG 组件,几个小时就能跑通。

 

企业不需要为每个 Agent 单独开发身份认证或数据接口,一套 Agent Identity 就能管好所有 Agent 的工号,一个 Connector 就能接通全公司的数据源。

 

放在阿里云百炼“1+2+N”体系中,组件化正填补模型到业务之间的最后一块拼图:模型提供计算力,开发范式定好流程,而这“N”个组件则专门负责解决数据怎么连、权限怎么划、效果怎么评、安全怎么管这些具体的“杂活”。

二、“2”:“下一代”Agent,需要新开发范式

 

“N”组件把坑填平,只解决了“这事能不能接得上、管得住”。企业真正要把 Agent 变成长期能用的工业生产能力,还得解决另一个现实问题:怎么开发、怎么协作、怎么迭代。

 

阿里云百炼“1+2+N”体系里的“2”,就负责这一点,它涵盖两种开发方式(低代码+高代码),以及配套 Agent 开发平台,通过同一套平台和运行时,分别服务两类人、两种交付方式。

 

为什么要做成“2”种模式?因为企业落地 Agent 的过程,基本就是两条路同时走:想快速试点、尽快看到效果,低代码更省事、更快;真要进核心业务、对接复杂系统,高代码才够灵活、够深。

更现实的是,企业在代码协作上存在长期的“割裂”:低代码不够用,高代码效率低。产品经理用低代码搭建的草案,往往需要技术团队用高代码重新开发,而这种重复劳动会导致业务逻辑在传递中失真。

 

为了让 Agent 更快、更深地融入业务,百炼把低代码和高代码“打通”:企业可以从低代码起步做验证,再逐步演进到高代码做优化,形成一种更自然的渐进式开发,让真正懂业务的人与懂技术的人有机协作。

 

据 Gartner 的预测,到 2028 年,企业里相当一部分 Agent 应用会由业务人员主导搭建。双开发模式很可能会成为 Agent 走向工业化落地的一种主流形态。

 

但“2”的意义还不止是“怎么写代码”。更重要的是:下一代 Agent 本身就需要新的开发范式。

 

过去的一年,很多企业里的 Agent 实际上还停留在比较“表层”的形态:一种是以提示词工程为核心、更多承担辅助角色的 Copilot;另一种是能处理重复流程、严格按预设步骤执行的“数字员工”。它们能提升效率,但往往缺少主动规划与闭环执行能力。

 

Agent 不应仅“被告知怎么做”,而是“应该主动思考怎么做”。

 

因此阿里云百炼提出了 Agent2.0:未来的 Agent 要能围绕目标自主规划,把复杂问题拆成可执行的小任务,过程中还能根据反馈调整策略,最后交付更稳定、质量更高的结果。

 

按照这个定义,Agent2.0 的核心链路是“规划—执行—反思”。

 

而现实里很多 Agent 开发失败,问题往往是开发范式还停留在老路上。传统那种线性链路(用户 →Agent→ 模型 → 输出)有三个硬伤:没有规划,就很难应对动态场景;没有反馈与纠错,走偏就很难拉回来;没有长期记忆,交互体验容易断裂。

 

为了能承载 Agent2.0 的生产级落地,百炼平台对开发范式做了系统升级:AgentScope 从过去偏“开源写代码”的工具形态,演进为覆盖 Agent 全生命周期的工业化开发平台。

第一步,是把“上手门槛”压到尽量低。

 

一方面,AgentScope 做了对主流模型能力的统一集成,内置 100+预训练模型,拿来就能用。

 

另一方面,百炼平台提供了一批可复用的智能体库,比如交易智能体(EvoTraders)、调研智能体、金融分析智能体、数据科学智能体(Data-Juicer)、浏览器使用智能体、语音智能体等,减少从零开始的成本。

 

第二步,是围绕更高级的 Agent2.0,把“协作与执行”能力补齐。

 

AgentScope 主要通过三块来支撑:

 

多智能体编排:引入基于 Actor 模型的分布式架构,支持多个专业 Agent 的并行协作与自动调度。研究表明,协作模式任务成功率比单一 Agent 高出 90.2%。

 

智能体上下文管理(长期记忆):深度适配 Mem0、ReMe 等记忆系统。使得 Agent 能够自主存储并检索历史交互中的关键信息,在后续任务中实现能力的持续迭代。

 

工具调用能力:全面兼容 StreamableHTTP、SSE、STDIO 等主流接口标准。通过支持 AnthropicAgentSkill 规范,在运行时即可动态加载新工具或移除冗余资源。

 

在工具调用这层,ReAct 这类“边想边做”的范式,也被不少实践证明更容易形成任务闭环:学术基准测试中,ALFWorld 任务只需 2 个示例即可达到 71%的成功率,高于强化学习模型的 37%;在复杂任务中,准确率相较纯 FunctionCalling 提升约 15%–20%,成本比 CodeAct 低 78.9%。

 

在 Agent2.0 优化与部署阶段,阿里云百炼通过 AgentScope-Studio+AgentScope-Runtime 打通了全生命周期的工业化链路。

 

AgentScope-Studio 可通过自定义多维表现指标,评估工作流设计的合理性;提供从输入到输出的全链路追踪与可视化,让 Agent 行为与决策过程实现“可观测、可复盘”。

 

百炼平台利用评测结果持续改进,让失败样本成为训练资产,形成“评测→优化→验证→再优化”的迭代闭环,实现从“盲目调参”到“数据驱动优化”的范式转换。

 

在落地部署环节,AgentScope-Runtime 支持 Docker、K8S、ACK、Serverless 等多种部署形态;通过 Agent-as-a-Service 将 Agent 封装为可独立调用的 API 服务,兼容 A2A 与 ResponseAPI 等协议,便于集成、弹性扩缩与快速迭代。

 

如果把阿里云百炼的开发范式拆开来看,其实就是从“构建”走向“运营”的一个完整闭环。

 

前半段构建,重点是更快、更省力地把东西搭起来:

 

用可选智能体模板减少重复劳动;用多智能体编排与工作流把复杂任务拆成可协作的子任务;用高低代码一体化实现统一开发与交付;通过 ReAct 等方式完成多任务的规划、执行与自我纠偏,再结合用上下文和长期记忆支撑长链路执行等。

 

后半段上线运营,就是做让它智能地跑起来:

 

用可观测和自动化评测把效果变成可量化的指标;打通真实系统和数据源,拿到反馈并持续优化;在企业既有基础设施上实现更便捷的部署与稳定运维;同时借助 Identity、模型单元专属部署、机密推理等能力,把权限、安全与合规治理补齐。

 

这套开发范式的最大亮点,就是它统一按照“工业级 Agent2.0”的标准做事:高效的开发体系+可持续的反馈闭环+便捷可靠的上线部署。

 

三、“1”:模型优势之外,深挖“模型服务”工程

 

最后,无论是组件化拼装,还是低/高代码协作,最终都要落在同一个问题上:模型调用能不能稳定、能不能扛流量、能不能控成本、能不能过合规。

 

所以“1”是整个体系的地基——模型与云服务底座把推理服务、弹性、部署形态与安全边界做成统一供给,保证上层“能跑起来,也跑得久”。

 

很多企业在用 Agent 的过程中,卡住的往往不是“模型会不会”,而是一些更现实、更工程的问题:1)延迟、并发、稳定性跟不上真实业务流量;2)成本容易失控(链路长、多轮工具调用、重试一多就更明显);3)部署和合规麻烦(私有化、混合云、权限边界、数据隔离等)。

 

在调用模型的时候,企业最关心的也无非就两件事:成本与性能。为此,百炼平台提供了一套云资源调度组合拳:“异步调用+闲时调度”。

 

以前搞大规模的数据清洗、标注,或者是分析长视频,这些任务不仅计算密集,而且耗时漫长。最头疼的就是走“同步调用”,跑到一半接口超时了,任务断掉,前面全白干。

 

有了异步调用就省事多了,它像寄快递一样,你把任务丢给后台,拿个任务 ID,就可以去干别的。不用在那儿死等结果,等服务器处理完了你再回来取就可以。

 

而“闲时调度”更像“错峰用电”:不着急的任务挪到资源空闲的时候跑,单价更划算,整体资源利用率也更高。阿里云百炼官方给出的数据是,动态调度后闲时推理成本可降低 50%。对需要处理海量数据的企业来说,这种节省是实打实的。

 

此外,阿里云百炼这次把“模型服务能力”也做了系统升级,主要围绕四块:模型后训练、专属模型单元部署、平台可观测、推理安全防护,系统性地”深挖“模型的服务能力。

 

先从选型说起。百炼平台把模型体验中心做了结构性重构,把在线模型的能力做成更直观的“能力图谱”,支持文本、视觉理解、图像/视频生成、语音交互等全模态体验。

 

这样企业就不用靠猜,也不用“盲选”,可以在平台上直接对比不同模型在具体场景下的表现,再做选择。

 

模型选定之后,是否“实用”往往取决于后训练。很多企业真正需要的不是通用能力,而是用自家数据和业务知识微调出来的“专家模型”,这才更贴近业务,也是企业的核心壁垒。

 

模型训完后,真正容易被“拦住”的常常是部署。自建集群运维复杂、成本也难估:为了应付峰值不得不预留一堆算力,平时又闲着浪费;多租户环境下的数据隔离和性能争抢,会让企业心里不踏实。

 

阿里云百炼推出“模型单元”部署,其实相当于给企业开了条“专属通道”,减少资源争抢带来的不确定性,让高并发和低延迟更稳定。

 

同时提供全托管的 Serverless 方式:系统会跟着实时流量自动扩缩容——忙的时候自动扩,保证体验;闲的时候自动收,尽量省成本。

 

官方给出的测试数据里,模型单元部署相对传统自建集群方案,推理性能提升超过 1.3 倍,并发能力提升超过 1.5 倍。对企业来说,这类提升的意义很直接:同样的业务量,成本更低性能更好。

 

此外,调用模型处理数据时,最难绕开的是安全——尤其在金融、医疗、法律等高敏行业。很多企业不是不想用,而是卡在一句话:数据给到模型,会不会出事?

 

为此,百炼平台推出模型“机密推理服务”,依托三层安全架构,为企业构建起全链路的数据保护围墙:

 

第一层是基于 CPU/GPU 硬件可信执行环境的机密计算能力,将模型推理运行在硬件隔离的安全区内。即便云侧其他组件遭受攻击,敏感数据也难以被窃取或泄露。

 

第二层是端到端加密的可信链路:实现了从用户端到云端计算中心的全程加密传输。数据在加密状态下进入 TEE 区域处理,计算结果在加密状态下返回,确保数据在“流动”与“处理”的全生命周期中始终处于保护伞下。

 

第三层是公开审计的可信服务:平台提供可验证的身份与安全能力证明。企业不仅能自主校验服务安全性,更能以此作为合规背书,向管理层、审计机构及客户证明其 AI 系统的高安全性。”

 

在使用体验上,机密推理被做成了“一键交付”的形态:企业只需要在模型库中选择支持机密推理的版本,一键部署到 TEE 隔离环境,就能直接调用机密推理服务来处理敏感数据。

 

放在一起看,这次升级是在原有模型性能优势之上,又补上了几块关键拼图:云资源调度、后训练、模型单元化部署、机密推理安全体系等。几块一起发力,让大模型调用变得更实用、更省钱,也更安全。

四、没人愿意再“从零开始”,阿里云百炼 Agent 平台企业版已发布

 

从市场角度来看,政企、金融、医疗等行业在采购云服务时,始终受困于一种不完美的平衡。

 

公有云上手快、性能强,但数据边界与合规要求是跨不过的门槛;私有化部署虽有安全感,但往往陷入“模型、工具、流程”极其复杂的运维战泥潭,开发周期长、技术更新慢。

 

1 月 7 日,阿里云百炼企业版的发布,为市场提供了一个既保留数据主权,又拥有云端顶级效率的方案。

 

企业版支持专有云、本地化及 VPC 隔离,百炼平台将云端的成熟能力“下沉”至企业环境。更重要的是,百炼平台企业版支持源码级交付。这不仅仅是技术开放,更是给予企业自主演进的确定性。

 

企业不再需要买一堆零件回去组装,而是直接获得一个在自身安全边界内运行的 Agent 基座。

 

事实上,企业版也并非新功能的简单集合,而是将百炼平台“1+2+N”体系(顶级模型、成熟范式、核心组件)封装为完整的交付体:

 

双代码统一:兼顾业务验证的敏捷性与复杂逻辑的深度定制。

 

多模态 RAG:激活企业沉睡的音视频与文档资产,转化为实时知识。

 

Trace 与 Evaluate:将 Agent 的黑盒行为拉到台面上,让调试与迭代成为标准工序。

 

大规模组织的管理诉求:企业版强化了多租户部署、SSO 账号集成以及细粒度的权限审计。这些功能解决了 IT 部门的核心忧虑——让 Agent 的应用在组织内部不仅“能跑通”,更“可治理”。

 

一个行业走向成熟的标志,是目光从技术指标移向业务价值的“深水区”。

 

阿里云百炼 Agent 平台企业版,本质上在扮演“AI 时代技术中台”的角色。从行业趋势上看,未来企业大概率将不会从零开始建设 AI 能力,而是直接基于一个完整、成熟的技术中台起步。

 

这意味着,在一年的野蛮生长后,留给企业 AI 试错的窗口期正在关闭。

 

展望 2026 年,Agent 应用爆发增长几乎已成共识。Gartner 预测,到 2026 年底,40%的企业应用将集成任务型 AI agents(相比 2025 年不足 5%),这也标志着 Agentic AI 正从概念走向主流生产环境。

 

对阿里云这样的全栈人工智能服务商而言,这将是多年技术积累转化为业务增量的红利期;对使用模型与 Agent 的企业客户而言,也将是 Agent 正式进入“拼效率、拼落地”的竞争元年。

今天这篇博客文章由 Streamfold 的 Mike Heffner 和 Ray Jenkins 撰写。他们是 Rotel 的维护者,该项目是一个用 Rust 编写的开源工具,致力于实现高性能、资源高效的 OpenTelemetry 数据采集。

TLDR;

大规模系统中的效率至关重要:哪怕是资源消耗的小幅下降,也可能带来显著的成本节约和效率提升。

OTel + ClickHouse 的基准测试:我们构建了一套数据管道,用于评估将流式追踪数据写入 ClickHouse 的性能。

Rotel 实现了 4 倍性能提升:我们展示了如何将 OTel Collector 每核每秒处理 13.7 万个追踪跨度 (trace span) 提升到 Rotel 的 46.2 万个,并详细说明了多项关键的性能优化。

工具和资源:文末提供了我们在基准测试中所用的工具清单。

引言

在 PB 级规模下运营一个可观测性平台,需要持续关注资源利用效率。即便是每核性能或内存使用上的细微改进,也能大幅降低基础设施开销。

本文源自我们在丹佛举办的一场 ClickHouse 技术见面会的演讲。在会上,我们分享了我们对 Rotel 的开发工作。Rotel 是一个面向大规模系统的高性能 OpenTelemetry 数据平面 (data plane)。

得益于其高压缩比和良好的成本效益,ClickHouse 越来越多地被用于大规模的 OpenTelemetry 负载中。而在这些系统中,OTel Collector 往往是整条数据管道中成本最高的部分。

最近,ClickHouse 发布了一篇关于大规模系统中效率重要性的文章(https://clickhouse.com/blog/scaling-observability-beyond-100pb-wide-events-replacing-otel),并介绍了他们在内部平台 LogHouse 上运行 OTel 的实际经验。

其中有个细节引起了我们的注意:

“OTel Collector:使用超过 800 个 CPU 核传输每秒 200 万条日志。”

按每核每秒约 2500 条日志计算,对于典型的日志行来说,这意味着一个 8 核服务器每秒仅能传输约 10MB,远远低于现代硬件的处理能力。而 ClickHouse 每核每秒最多可处理超过 1.25 万条 OTel 事件,吞吐能力是前者的五倍以上。因此,当前的瓶颈在数据采集端,而非存储端。尽管我们无法复现 ClickHouse 内部的 LogHouse 平台,但我们认为,对现代 OpenTelemetry 数据管道进行基准测试仍具有重要意义。因此,我们希望借此次演讲探讨一个核心问题:将追踪数据发送到 ClickHouse 时,不同的 OpenTelemetry 数据平面表现如何?

本文将逐步介绍我们构建的基准测试流程,比较 OpenTelemetry Collector 和 Rotel 的性能。我们搭建了一套合成的追踪数据管道,先通过 Kafka 传输追踪跨度,再写入 ClickHouse。在 OTel Collector 达到 110 万跨度/秒的基准测试后,我们展示了通过以下几项优化如何让 Rotel 在相同硬件上实现最高 370 万跨度/秒的处理能力:实现 JSON 的二进制序列化、分析 Tokio 任务调度性能 (perf analysis of Tokio task management)、以及引入改进的 LZ4 压缩算法。

文末我们还列出了用于此次基准测试的框架和工具。

基准测试框架

在进入测试结果之前,我们先介绍一下评估 OpenTelemetry Collector 和 Rotel 所采用的测试方法。如果你感兴趣,也可以直接跳转到结果部分,链接见这里。

追踪数据管道

我们此次基准测试的重点是将追踪跨度 (trace span) 写入 ClickHouse,因为在大型系统中,追踪数据增长极快。我们参考了一个高度可靠的流处理管道进行建模,选用 Kafka 作为日志流层。测试目标是模拟这样一种场景:大量边缘采集器将数据发送至 Kafka 流,由少数几个核心采集器批量写入 ClickHouse。在这个管道中,Rotel 和 OTel Collector 使用相同的 Kafka Protobuf 编码,因此两者可以互换使用。

图片

评估方法

我们希望找出在固定硬件条件下,单个采集器能够稳定支持的最大吞吐量,重点关注的是采集效率,而非系统扩容能力。测试的关键是观察单节点在不降级的前提下可以被“压榨”到什么程度,同时也控制在我们的评估预算范围内。我们选择网关采集器作为测试核心组件,因为它直接将数据输出至 ClickHouse,而后者在处理大批量数据插入时效率最高。为实现更高的批处理效率,部署少量、但能力更强的网关采集器是理想方案,因此我们专注对该组件进行优化与测量。

饱和识别

我们通过两个关键信号来判断采集器是否已达到处理极限:

  • 内存激增:当下游系统产生反压时,采集器会将数据缓存于内存中,导致内存快速增长;

  • Kafka 消费延迟:如果采集器处理速度赶不上 Kafka 流的速度,其消费延迟会不断增加,即“上次读取的消息时间”与“当前时间”的间隔在变大。

测试配置

每项测试我们都将数据管道运行在接近饱和的边缘状态,持续 15 分钟,记录以下两个关键指标:

  • 每秒处理的追踪跨度数,由负载生成器记录;

  • 向 ClickHouse 写入的数据吞吐量(MB/s),由 AWS Cloudwatch 监控采集。

带宽这一指标有助于统一比较不同环境下的处理能力,因为追踪跨度在实际场景中大小差异可能很大。在测试配置中,边缘采集器会将数据打包优化后发送至 Kafka,这样可以减少消息总数,同时提高单条消息的体积。

测试过程中,我们也记录了 Rotel 与 ClickHouse 的平均 CPU 使用率。

OpenTelemetry 的 ClickHouse 数据模式

本次测试使用的 ClickHouse 表结构同时兼容 OpenTelemetry Collector 与 Rotel。这一数据模式是官方推荐的方案之一,适用于 ClickHouse 与 ClickStack 可观测性平台,支持 OTel 的指标、日志与追踪数据。

OTel 的数据模型高度依赖键值属性(key/value attributes)来描述基础设施与应用环境中的关键特征,有助于进一步分析。最初在 ClickHouse 中,这类字段采用 Map 类型存储。但近期,OTel Collector 引入了支持 JSON 列类型(JSON column type)的新特性,使得原有结构可以转换为 JSON 格式。虽然这会给 ClickHouse 带来更高的 CPU 压力,但查询表达能力也因此大大增强。我们的测试选择启用这一新特性。你可以在这里查看我们使用的完整 ClickHouse 追踪数据结构(https://gist.github.com/mheffner/dc332a61f3b9ba1d03fd7c7d5c1b7fbb)。

我们的测试配置中还使用了 ClickHouse 的 Null 表引擎,这是一项关键优化手段。Null 引擎可以接受写入请求但不进行实际存储,因此能帮助我们剥离磁盘 I/O 的影响,专注评估写入吞吐能力与数据结构正确性。在完成峰值吞吐的测试后,我们会进一步评估 ClickHouse 如何处理真实的磁盘写入负载。

负载生成器

我们尝试使用 telemetrygen CLI 工具生成数据,但它难以达到所需的数据量。因此我们改用之前内部构建的负载生成器,该工具最初用于测试 OpenTelemetry 与其他遥测管道。该项目可在 Github 的 otel-loadgen 仓库中找到。它还具备验证端到端数据传输等增强功能,我们将在后续文章中进一步介绍。

我们构造的每个追踪包含约 100 个跨度,涵盖丰富的属性与元数据。和所有合成测试一样,这些数据并不完全等同于真实生产环境中的流量。

测试硬件

所有基准测试均在 AWS EC2 实例上执行。数据管道的每一层组件部署在独立的实例中,所有实例均位于同一可用区,以确保测试结果的一致性与准确性。

图片

为了最大化磁盘吞吐能力,我们将 Kafka 和 ClickHouse 的数据卷直接挂载在实例自带的 NVMe 本地磁盘上。所有测试均使用 Amazon Linux 2023 操作系统,通过 Docker Compose 编排运行各个组件。

本次基准测试的目标是评估单台网关采集器主机所能承载的最高吞吐量。我们最终选择的测试机器为 m8i.2xlarge 实例,配备 8 核 CPU 和 32GB 内存。随着测试规模扩大,数据管道中的其他节点进行了扩容,但网关采集器始终保持不变,便于横向对比。

测试 OpenTelemetry Collector

测试从 OpenTelemetry Collector 开始,它在测试中既作为边缘采集器,也作为网关采集器。

测试配置

图片

你可以在这里查看 Docker Compose 的配置文件(https://github.com/streamfold/rotel-clickhouse-benchmark/blob/main/docker-compose-otelcoll.yml)。

测试结果如下:

在运行单个 Collector 实例时,我们在处理速率达到约 70 万个追踪跨度每秒(约 40 MB/s)时遇到了性能瓶颈。此后内存占用开始持续上升,尽管此时 CPU 利用率尚不足 50%。

OTel 的 Kafka 接收器采用单个 goroutine(轻量线程)处理消息,这很可能成为吞吐量的限制瓶颈。我们尝试了若干 Kafka 参数调整,包括消息大小限制等,但都未能显著提升性能。于是我们转向横向扩展方案,在同一主机上启动第二个 Collector 实例(通过 Docker Compose 的 scale: 2 设置)。

当两个 Collector 实例各自消费一半 Kafka 分区后,系统最大稳定吞吐量达到 110 万追踪跨度每秒(69 MB/s)。一旦超过这个阈值,发送队列开始堆积,内存使用迅速上升。当队列完全填满后,Kafka 接收器仍然会继续读取消息,但会直接丢弃数据。这意味着表面上 Kafka 消费延迟没有上升,但实际上我们已经在丢失追踪数据!

测试期间,网关采集器的 CPU 峰值使用率超过 83%,成为主要瓶颈。而 ClickHouse 的 CPU 使用率维持在 23% 左右。

图片

测试 Rotel

测试配置

图片

你可以在这里查看 Rotel 的 Docker Compose 配置(https://github.com/streamfold/rotel-clickhouse-benchmark/blob/main/docker-compose-rotel.yml)。

测试结果如下:

Rotel 同样使用一个接收循环从 Kafka 拉取数据,与 OTel Collector 架构类似。这使我们初步判断存在串行处理瓶颈。果然,当我们在主机上运行两个 Rotel 实例并充分利用 CPU 后,吞吐量大幅提升。

在两个 Rotel 实例并行运行时,我们实现了每秒 145 万个追踪跨度(76 MB/s)的最大吞吐能力,较 OTel Collector 提升约 1.3 倍。继续提升负载后,我们观察到 Kafka 消费延迟开始缓慢上升,说明消费速率已逼近极限。

此时,网关采集器 CPU 使用率达到 91.3%,成为新的瓶颈;ClickHouse CPU 使用率也升至 60.4%。

图片

我们随后继续挖掘进一步的优化空间,将注意力转向了如何更高效地处理 JSON 列类型的数据传输。

优化 RowBinary 格式下的 JSON 编码

在 Rotel 中,我们基于官方的 Rust ClickHouse 库 clickhouse-rs 进行了改造。该库使用的是 RowBinary 格式——一种面向行的二进制序列化协议,通过 HTTP 与 ClickHouse 进行数据读写。相比之下,OTel Collector 所使用的 Go 驱动和 ClickHouse 内部组件则采用面向列的原生协议。

在处理 JSON 列时,clickhouse-rs 的默认做法是:先将 JSON 内容转为字符串后再发送。虽然 ClickHouse 本身不会以原样字符串存储 JSON 列,但这一“字符串化”过程是为了传输而必须进行的。不过,这样做在高并发情况下代价很大:客户端需要序列化 JSON,服务端则需重新解析,还必须扫描键名和字符串值以转义引号、反斜杠等字符。尤其当字符串体量较大时,这一过程非常耗资源。

在 ClickHouse Slack 社区的帮助下,我们发现其实可以将 JSON 列直接编码为 RowBinary 原生格式。这种方式下,JSON 会被序列化为一系列键值对,每个键为字符串,紧跟一个表示值类型的标签,再跟上该值的原始二进制内容。这种结构可以跳过整个 JSON 的序列化解析过程,从而实现更高效的结构化数据传输。

比如,考虑下面这样一个简单的 JSON 对象:

{  "a": 42,  "b": "dog",  "c": 98}
复制代码

RowBinary 格式下的编码方式如下:

图片

首先,它会将键值对的数量以变长整数(varint)编码,例如上例中是 03 对;然后逐个对键值对编码。每个键会先写入一个表示字符串长度的 varint(如 01),再写入字符串本身,接着是对应值的编码。如果值的类型在 JSON 声明中已知(如上例中的键 a 是整数 42),那么会直接用固定类型编码,如 2a 00 00 00 00 00 00 00。如果类型未声明,则使用动态类型编码方式,例如键 c 用 0a 表示 Int64 类型,后跟值 98(62 00 00 00 00 00 00 00)。最后,键 b 表示字符串类型(15),跟上字符串长度 03 和字符串内容 “dog”。

相比传统的 JSON 传输方式,这种方法在客户端和服务端两端都能显著减少序列化和解析的资源消耗。虽然 clickhouse-rs 库目前尚未原生支持这种编码方式,但我们计划参与贡献该功能的开发。

重新测试

在将 Rotel 升级为使用上述优化编码后,我们重新进行了性能测试,以评估实际效果。结果显示,虽然总体吞吐量依然维持在之前的峰值——每秒 145 万个跨度未变,但 ClickHouse 服务器的 CPU 使用率下降了约 10%,网关采集器的 CPU 占用也略有减少。这种改善在多次测试中均表现稳定,说明服务端解析负担确实得到了缓解。

需要说明的是,此次测试中使用的合成负载并未包含大量长字符串,同时每个跨度的属性数量也与真实生产环境可能有所不同。因此,虽然客户端的改进不明显,但我们相信,在处理属性字段较多、字符串数据较大的实际业务场景中,这种更快的 JSON 序列化路径将带来更明显的性能收益。

图片

用一个意想不到的技巧将吞吐量翻倍(定位并解决内存分配器锁争用)

在这轮测试中,为了充分利用网关采集器主机的 8 个 vCPU 并将事件吞吐量提升至每秒 145 万条写入 ClickHouse,我们必须同时运行两个 Rotel 实例。Rotel 的 Kafka 接收器逻辑原本运行在一个 Tokio 异步任务中,其处理流程简化如下:

图片

这种实现方式存在两个主要问题:

1. 整个处理流程是串行执行的,缺乏并行能力;

2. 数据反序列化(unmarshaling)是一项高度依赖 CPU 的操作,容易阻塞 Tokio 的执行线程。

Tokio 是 Rust 语言的异步运行时,采用协作式调度模型。这要求任务在运行过程中需主动在 `.await` 或其他让出点交还执行权给调度器。网络上已有大量文章探讨该机制的重要性以及忽视它可能带来的严重性能问题。通俗来说,一个 tokio 任务应尽可能靠近 `.await` 点,业界建议任务在两个 `.await` 之间的执行时间应控制在 10 到 100 微秒以内。

在 Rotel 的 exporter 模块中,我们使用了一个专用线程池来处理诸如数据序列化与压缩等 CPU 密集型任务。而在 Kafka 接收流程中,rust-rdkafka 库会将解压缩工作分派至后台线程,在调用 `recv()` 之前完成。但最初我们依然将数据的反序列化逻辑保留在 Tokio 异步任务中。随着分析深入,我们确认反序列化过程极其耗费 CPU,因此决定将其改为异步提交到与 exporter 共用的线程池中,以避免阻塞主线程。

经过这一重构后,Kafka 接收器的主处理循环结构如下:

loop {  select! {    message = recv() => {        unmarshaling_futures.push(spawn_blocking(unmarshal(message)))         },    unmarshaled_res = unmarshaling_futures.next() => {        send_to_pipeline(unmarshaled_res)    }  }}
复制代码

我们随后在网关采集器上使用单个 Rotel 实例重新运行测试,并将负载生成器设置为此前的最大值——每秒 145 万个 trace span。结果系统依旧稳定运行。但让我们颇为意外的是:CPU 使用率相比优化前下降了约 40%!

原先我们之所以要运行两个 Rotel 实例,是因为单个实例未能充分利用主机资源,Kafka 接收模块存在明显的串行处理瓶颈。而此次重构将反序列化逻辑迁移至专用线程池后,这一限制被有效解除。我们预期,在这种并行架构下,单实例就能实现与双实例相同的吞吐性能,并维持类似的资源利用率。

在看到 CPU 占用大幅下降后,我们继续提升负载压力。最终,我们成功将吞吐量从每秒 145 万条提升至 360 万条 trace span,实现翻倍增长!

当处理速率达到每秒 360 万条时,CPU 占用再次达到约 93%,系统达到新一轮饱和。

图片

在验证性能大幅提升后,我们开始着手分析背后 CPU 效率提升的具体原因。为此,我们借助 Linux 的 Perf 工具以及 flame graph(火焰图),对优化前后的 Rotel 构建版本进行了性能剖析,从而定位 CPU 时间的实际开销位置。

使用 Flamegraph 剖析 Rotel 的 Kafka 接收器

我们针对 Rotel Kafka 接收器的旧版本与新版本重新运行了一轮测试,并捕获了 flamegraph(火焰图)用于性能分析。起初乍一看,两者并未显现出明显差异。你是否能发现其中关键?在两个版本中,我们都观察到:将追踪数据准备并导出至 ClickHouse 占据了主要运行时间,此外,接收器中的消息反序列化操作(在 prost::message::Message::decode 函数中执行)也消耗了相当多的资源。这类负载会创建大量生命周期极短的对象,因此系统在内存分配与释放上耗费了大量时间。

旧版本:

图片

新版本:

图片

使用 Linux Perf 评估接收器优化前后的变化

通过运行 perf stat,我们发现两个版本在底层表现上差异巨大。

perf stat -c cycles,instructions,cache-misses,cache-references,context-switches,cpu-migrations 
复制代码

旧版本

295612663445 cycles 264853636815 instructions # 0.90 insn per cycle 615670230 cache-misses 1867733351 cache-references 1224819 context-switches 1230 cpu-migrations 50.296446757 seconds time elapsed
复制代码

新版本:

150590256805 cycles 287007890213 instructions # 1.91 insn per cycle 598469068 cache-misses 1163669589 cache-references 37675 context-switches 43 cpu-migrations 43.716966122 seconds time elapsed
复制代码

新版本平均每周期执行 1.9 条指令,每秒仅发生 862 次上下文切换。尽管这在指令级并行性(ILP)方面不算极致表现,但相较之下已经有明显进步。而旧版本平均仅能达到 0.9 条指令/周期,且上下文切换次数竟高达每秒 24,350 次 —— 新版本将此指标降低了约 32.5 倍!说明旧版本几乎无法并行处理,线程频繁被挂起与唤醒,调度开销巨大。

此外,CPU 迁移数据也显示出改进:新版本平均仅有 1 次迁移/秒,表明线程在相同 CPU 核上保持良好的缓存亲和性,而旧版本则高达 24.5 次/秒。这些迹象显示,旧版本中调度器难以保持线程驻留在固定核心上。

新版本具备更优秀的并行处理特性,使得我们可以进一步扩大吞吐负载。而这一切的背后,仅仅是我们将部分任务拆分至独立线程处理。

我们原先推测旧版本性能瓶颈可能源于 Tokio 执行线程被阻塞,导致运行时不得不频繁轮询、空转,甚至尝试工作窃取。但 perf report 的深入分析为我们揭示了更具体的问题。

深入分析 perf report 结果

通过 perf record 捕获更详细的运行数据后,我们对比了优化前后的性能差异。

在新版本中,大部分计算时间用于压缩数据、将 OTLP 转换为 ClickHouse 所需的数据行结构、以及内存分配与释放等正常开销,整体运行表现健康。

图片

但旧版本的问题非常突出:15% 的运行时间用于释放内存,而压缩和构造数据的时间仅占 9.75%,相比之下新版本达到了 20%。同时,我们发现大量 CPU 时间耗费在如下底层函数中:_raw_spin_unlock_irqrestore、finish_task_switch.isra.0、__lll_lock_wait_private 与 __lll_lock_wake_private。

图片

开启子调用视图后,我们发现这些锁操作多数出现在内存释放阶段。

图片

这些函数具体负责什么?

  • _raw_spin_unlock_irqrestore 是 Linux 内核中的函数,用于释放自旋锁并恢复中断状态。当任务即将被抢占时会调用它,以便调度器执行上下文切换;

  • finish_task_switch.isra.0 是编译器优化后的上下文切换清理函数,负责完成切换后的调度收尾;

  • __lll_lock_wait_private 和 __lll_lock_wake_private 是 glibc 内部函数,用于 mutex 互斥锁等同步机制的实现。

值得注意的是,这些锁相关的函数在释放内存时频繁出现,暗示我们的旧版本在这一过程中产生了严重的锁争用。

回过头来看旧版本的 flamegraph,这一问题其实非常明显。理想情况下,如果我们能使用类似差分 flamegraph(differential flamegraph)工具对比两个版本图谱,可能会更快定位瓶颈点(此处也再次呼吁出现更多易用的 flamegraph 工具)。不过幸运的是,我们还是通过 perf stat 和 perf record 快速找到了问题根因 —— 并不是 Kafka 接收器的串行处理导致瓶颈,而是 ClickHouse exporter 中的序列化函数(TransformPayload)在进行 marshaling 操作时产生了锁争用。

图片

Glibc 多线程内存分配机制下的锁争用问题

从测试数据来看,我们已能清楚解释为何在优化后,系统的 CPU 使用率大幅下降而吞吐能力却反而提升。原先的版本确实消耗了大量计算资源,但主要耗在了无效的系统开销上 —— 本质上,它的大量 CPU 时间都被花在释放内存时的自旋锁等待中。

为了理解这种情况,我们需要简单了解 glibc 默认内存分配器的工作方式。系统将内存划分为多个“arena”(内存区域),每个 arena 都通过一个互斥锁(mutex)来保障内存的分配与释放线程安全。为了减少锁争用,不同线程会尝试创建独立的 arena,随着线程池规模扩大,arena 数量也会同步增长。

但关键在于,如果某段内存在 A 线程上分配,最终却在 B 线程上释放,B 线程就必须锁住 A 所属的 arena,这很容易造成其他线程等待,从而产生锁争用。

在旧版本中,我们在 Kafka 接收器的反序列化(unmarshaling)过程中,于 Tokio 的 I/O 执行线程上分配处理 trace 数据所需的内存。这类异步任务调度在线程数受限的 Tokio executor 上 —— 网关采集器上仅有 8 个线程,刚好一核一个。之后,这段内存在 ClickHouse exporter 的数据序列化过程中被释放,而这部分逻辑则运行在一个大规模阻塞线程池上(包含几十甚至上百个线程)。线程之间频繁切换导致 arena 访问被频繁锁定,进而引发了锁争用问题。

图片

新版本中,我们将反序列化阶段的内存分配也迁移到了与释放操作相同的阻塞线程池中,解决了跨线程释放的问题。随着管道内数据量增加,线程池自动扩展,arena 的数量也随之增加,锁争用的风险被大幅降低。

图片

验证 arena 锁争用:Jemalloc 的对比测试

一位审阅本文的工程师提问:“如果换成 jemalloc 分配器,会出现同样的问题吗?”Jemalloc 是一个专为多线程环境优化的内存分配器,目标之一就是减少锁争用。我们曾在早期测试中尝试过 jemalloc,但当时未见显著性能收益。然而,随着 ClickHouse exporter 的负载提升,以及 Kafka 接收器架构的变化,内存分配压力大幅增加,这促使我们重新测试旧版和新版在 jemalloc 下的表现。

我们将旧版本切换为使用 jemalloc 后,CPU 使用率从 93% 降至 40%,与我们将反序列化迁移至共享线程池后的效果几乎一致,进一步印证了锁争用才是核心瓶颈。

尽管 jemalloc 能缓解 CPU 压力,但在满负载条件下,Kafka 消费延迟却有所增加。加上 jemalloc 当前已不再活跃维护,我们决定不将其设为默认分配器。不过,未来我们可能会引入 feature flag,让用户根据需求自由选择 jemalloc、mimalloc 等自定义内存分配器。

额外提升:开启快速 LZ4 压缩优化

Rotel 采用 ClickHouse 官方推荐的 LZ4 压缩配置来减少网络传输数据量。我们使用的是 lz4_flex crate —— 与 clickhouse-rs 相同的依赖库,但我们是直接引用的。在引入相关压缩支持时,我们忽略了 Cargo.toml 中的功能标志配置。

Lz4-flex 同时提供安全(safe)和非安全(unsafe)两种实现版本,其中 unsafe 版本的性能更优(关于 Rust 中的 unsafe,请参考官方文档(https://doc.rust-lang.org/book/ch20-01-unsafe-rust.html))。默认情况下,需要显式启用 unsafe 特性才能使用高性能实现。

clickhouse-rs 默认启用了 unsafe 模式,而我们最初未启用此选项。启用之后,我们观察到网关采集器的吞吐能力由每秒 360 万条 trace span 提升至 370 万条,网络压缩输入达到了 209 MB/s。

与此同时,网关采集器的 CPU 使用率也进一步小幅下降。

图片

完整的端到端性能评估

在对 Rotel 进行了多轮性能优化,并基于 ClickHouse 的 Null 表引擎完成初步测试后,我们成功将单实例的吞吐能力从最初的每秒 110 万条 trace span 提升至 370 万条,相当于每核每秒处理 46.25 万条。这比最早测试 OTel Collector 所获得的吞吐性能提升了超过 4 倍。

我们随后将评估重点转向了整个链路的最后一环 —— 数据写入 ClickHouse 并真正持久化至磁盘。在扩展 ClickHouse 写入能力时,通常需要从写入性能与查询效率两个维度优化数据表结构。本次测试我们仍采用默认的 OTel 数据模式,因此主要通过选择具备足够写入能力的实例来支撑高负载。

为应对大规模写入负载,我们将 ClickHouse 部署在更高性能的 AWS 实例上,并通过 4 块本地存储构建 RAID0,以确保不会受到磁盘带宽瓶颈限制。

在测试期间,我们关闭了 Rotel 的异步写入功能,并将批处理规模大幅提升至 --batch-max-size=102400,以提升整体写入效率。通过设置 --clickhouse-exporter-async-inserts=false,我们成功维持了每秒 370 万条 trace span 的网关采集器吞吐量。

此时 ClickHouse 的 CPU 占用率约为 50%,压缩后的写入流量达到 210MB/s。

图片

Visual inspection 

可视化效果上,我们在 ClickHouse 中成功查询到了超过 30 亿条追踪数据,验证了端到端链路的可用性。

图片

总结

极限规模下,效率至关重要

ClickHouse 内部 LogHouse 平台所运行的 PB 级可观测性场景表明,效率不再是优化选项,而是生存必要条件。他们将管道吞吐能力提升了 20 倍,同时仅使用之前 10% 的资源。如果仍按原有路径扩展,运维成本将变得无法承受。Netflix 与 OpenAI 等大型技术公司也达成了类似共识 —— 当数据量达到如此规模时,效率的优劣将直接影响业务运转。

本项目的目标正是在这一背景下,推动 OpenTelemetry 数据采集效率提升,并推出 Rotel。

近 4 倍的吞吐性能提升

通过本次工作,我们将 Rotel 打造为一款高吞吐量的 OpenTelemetry 流式采集工具。在相同硬件环境下,Rotel 的处理能力几乎是 OpenTelemetry Collector 的 4 倍。这种差异在大规模场景下可以带来显著的资源节省。Rotel 原生支持 OpenTelemetry 的 trace、metric 和 log 类型。本篇文章聚焦追踪数据,未来我们还将扩展基准测试到日志与指标场景。

我们也希望了解,在海量数据处理场景下,用户最看重哪些功能特性。如果你有宝贵经验或希望分享你的扩展实践,欢迎加入我们的 Discord 社区(https://rotel.dev/discord),或在 GitHub 上(https://github.com/streamfold/rotel)提交贡献。

后续方向

以下是我们在完成本次测试后,计划进一步探索的几个方向:

深入探讨 Kafka 的可靠传输机制

本文仅简单提及了 Rotel 的消息可靠性设计。Rotel 支持端到端消息确认机制,确保从 Kafka 中读取数据时实现“至少一次(at-least-once)”语义,避免依赖 Kafka 默认的自动提交机制可能导致的数据丢失。为此我们对数据管道做了多处修改,并进行了严格测试,以确保在避免重复的同时不丢失任何数据。未来我们计划单独撰文,深入介绍其设计与验证方法。

评估 ClickHouse 原生通信协议

Rotel 当前通过 clickhouse-rs 实现与 ClickHouse 的集成,采用基于 HTTP 的 RowBinary 协议。相比之下,OTel Collector 使用 Go 实现的 ClickHouse 驱动,采用的是 ClickHouse 的原生协议。该协议也是 ClickHouse 节点之间通信所用方式,基准测试显示其性能比 RowBinary 高出约 20%。ClickHouse 还新增了对 Apache Arrow Flight 的支持,后者基于内存格式 Arrow 实现高效传输。我们计划评估是否可将 RowBinary 替换为这些列式协议,以进一步提升 Rotel 吞吐性能。

进一步分析 tokio 中的阻塞任务影响

类似反序列化这类阻塞操作对 tokio 的运行时性能影响显著。在本次评估中我们首次直观感受到其影响,因此希望在其他处理路径中继续探讨类似瓶颈。目前我们已知 Rotel 的 OTLP 接收器在处理连接时会在异步任务中直接执行较重的 Protobuf 反序列化操作,该处理逻辑由 tonic crate 承担。我们计划分析如何将其拆分为独立任务。初步通过 perf 工具观察,预计该处存在巨大优化潜力。

优化内存分配路径

虽然 Rust 本身没有垃圾回收机制,但高频率的内存分配与释放在高负载场景中依然会成为瓶颈。Rotel 在处理短生命周期对象时存在大量内存分配行为。如果我们采用内存重用池(freelist)的方式跳过分配器,将常用缓冲区复用,有望显著减少开销。当然,这类机制的实现难度较高,若不慎也可能导致内存占用飙升。我们可能需要深入修改 tonic crate 才能实现该优化。

我们特别感谢 Sujay Jayakar、Ben Sigelman、Rick Branson、Vlad Seliverstov、Rory Crispin 和 Achille Roussel 对本文早期版本的审阅与反馈。

附录

评估过程中考虑但未纳入的项目

在设计本次基准测试框架时,我们曾希望纳入更多支持 OpenTelemetry 的数据平面工具。但实际测试中发现,它们与我们所设定的测试流程并不兼容。我们之所以选择分布式追踪作为测试对象,是因为它是推动 OTel 被广泛采用的关键场景之一,且在大规模系统中数据增长迅速。然而,日志与指标则属于传统监控领域,很多工具对 trace 类型的遥测数据仍缺乏完善支持。因此虽然未在本次测试中覆盖这些工具,我们仍计划未来开展日志与指标方面的基准评估。

Vector

Vector 是一款专为构建高性能遥测数据管道设计的轻量级工具。它支持广泛的数据源和输出目标,能很好地融入多种系统中。该项目目前由 DataDog 主导开发,并被用于其 observability pipelines 产品。

不过,Vector 对 OpenTelemetry 的支持还处于早期阶段,目前尚无法与多种目标系统对接。尤其在 trace 数据方面,其内部数据模型起初并不支持追踪结构,因此目前对 OTel trace 的支持较为有限。由于 Kafka 和 ClickHouse 的输出插件对 trace 数据尚不兼容,我们未能将其纳入此次测试。

例如,我们曾尝试:

  • 从 OpenTelemetry source 向 Kafka sink 发送 trace 数据(https://github.com/vectordotdev/vector/discussions/21018);

  • 在 ClickHouse 中存储 trace span(https://github.com/vectordotdev/vector/issues/17307#issuecomment-1641075239)。

Fluent Bit

Fluent Bit 是一个以性能为重点、由 C 编写的 Fluentd 替代方案。它提供了对 OpenTelemetry 的输入与输出支持,包括日志、指标与追踪数据。Fluent Bit 支持 Kafka 输入输出,因此理论上可用于构建可靠的数据流管道。

然而我们测试发现,当前版本中,在将 OpenTelemetry 作为输入的同时通过 Kafka 或 HTTP 输出 trace 与 metric 数据,尚不完全支持。这一限制使其暂时无法参与本次评估。

简化 OTel 与 ClickHouse 的迁移操作

根据 ClickHouse 官方文档建议,用户应在部署前手动创建表结构,而不是依赖导出器自动建表。但由于这些迁移脚本通常打包在 OTel exporter 中,缺乏独立部署方式,因此部署过程并不直观。

为了解决这个问题,我们在 Rotel 中将表结构管理逻辑拆分为一个独立的命令行工具 —— clickhouse-ddl,用于便捷地部署数据模式(schema)。该工具可创建与 Rotel 和 OTel Collector 完全兼容的表结构。

我们将该工具封装为一个 Docker 镜像,用户只需运行一条命令即可快速创建用于接收 OTel trace 数据的表。例如,下面是一个用于创建 trace span 表结构的命令示例:

docker run streamfold/rotel-clickhouse-ddl create \    --endpoint https:    
复制代码

此外,也可以像我们在本篇文章中所做的那样,使用 Null 表引擎来创建 schema,以便进行基准测试:

docker run streamfold/rotel-clickhouse-ddl create \    --endpoint https:        
复制代码

参考资料

/END/

征稿启示

面向社区长期正文,文章内容包括但不限于关于 ClickHouse 的技术研究、项目实践和创新做法等。建议行文风格干货输出 &图文并茂。质量合格的文章将会发布在本公众号,优秀者也有机会推荐到 ClickHouse 官网。请将文章稿件的 WORD 版本发邮件至:Tracy.Wang@clickhouse.com。