OpenTelemetry Protocol with Apache Arrow in Production
博客文章在发布后不会更新。这篇文章已经发布一年多了,其内容可能已过时,部分链接可能无效。在依赖任何信息之前,请务必核实。
OpenTelemetry Protocol with Apache Arrow (OTel-Arrow) 项目的 exporter 和 receiver 组件现已包含在OpenTelemetry Collector-Contrib版本中。这是一个案例研究,介绍了我们在ServiceNow Cloud Observability中部署OpenTelemetry Collectors的经验,以OTel-Arrow组件作为内部遥测数据的首选摄入路径。
自F5公司向OpenTelemetry项目做出最初贡献以来,包括F5在内的社区成员一直在协作努力,将OTel-Arrow exporter和receiver组件打造成一个可靠、高性能的解决方案,用于在昂贵的网络链路上传输大量OpenTelemetry数据,并实际应用于生产环境。通过在内部遥测中使用这些组件,我们观察到压缩因子在15x到30x未压缩大小的范围内(比未压缩时小15到30倍)。在OpenTelemetry Protocol (“OTLP”) 和 OpenTelemetry Protocol with Apache Arrow(针对类似配置的traces管道)的并排比较中,我们观察到压缩率提高了30%。尽管本研究专门关注traces数据,但我们在生产环境中也观察到了logs和metrics信号的结果,对于OTel-Arrow用户来说,在类似管道配置下,可以预期比OTLP提高50%到70%。
随着我们之前的实验结果在生产中得到验证,OpenTelemetry Protocol with Apache Arrow exporter和receiver组件现在可以投入一般性使用了。
Exporter and receiver components
Apache Arrow 是OpenTelemetry的一个重要技术依赖,因为这两个项目有很多共同之处。与OpenTelemetry一样,Apache Arrow拥有共享数据规范、传输协议、跨语言API规范以及为众多运行时环境构建的社区SDK。
Apache Arrow现已成为数据处理行业中面向列式数据的标准,因其互操作性和性能而广受欢迎。以下是我们如何利用这项激动人心的技术在OpenTelemetry Collectors之间建立压缩桥梁。
压缩桥由两个OpenTelemetry Collectors组成,分别标记为exporter和receiver,它们也可以是两个负载均衡的Collector池。
如 OTEP 0156 设计文档中所述,exporter将任意的OpenTelemetry数据转换为Arrow record batch。Arrow record batch是一块内存,具有标准化的布局,可以在不同地址空间和虚拟进程边界之间交换数据,无需复制。这种“零拷贝”方法使得Arrow能够调用用任何能够操作Arrow record batch的语言编译的原生函数和处理器特定的执行“内核”。
标准的OpenTelemetry Protocol数据结构化为Resource、Scope和单个遥测项的层次结构。在编码spans、logs和metrics之前,会识别、去重并作为单独的结构编码到OTel-Arrow record batch中。在这里,我们进行了其他优化,例如对项目进行排序以提高数据局部性。
Apache Arrow项目定义了进程间通信(IPC)的协议。Arrow IPC是一个“解耦”协议,不与传输一系列Arrow record batch的任何特定传输方法绑定。Apache Arrow有自己的RPC框架——Arrow Flight,但对我们来说,利用OpenTelemetry Collector中现有的gRPC配置、服务、授权扩展和仪表化,通过将Arrow IPC嵌入gRPC流中来实现更自然的设计。这种设计使我们能够受益于高度优化的Arrow IPC函数,这些函数可以压缩和编码重复的record batches,同时提供与OTLP/gRPC服务配置的即插即用兼容性。
OTel-Arrow receiver应用逻辑来反转Encoder中的转换,将数据重建为原始等效数据,并提供给OpenTelemetry Collector管道中的下一个组件进行消耗。我们预计未来使用Arrow端到端的数据在OpenTelemetry中将带来许多好处,从SDK到处理器,但这将是下一篇文章的主题。
性能与可扩展性
用户和服务提供商可以通过使用OTel-Arrow exporter和receiver组件作为OpenTelemetry Collector核心OTLP gRPC exporter和receiver组件的即插即用替换件来受益。用户可以预期与使用OTLP/gRPC、大批处理和Zstd压缩所能达到的最佳结果相比,网络带宽能够减少30-70%。
我们理解出色的压缩是一个优势,并且网络成本是可观察性总成本的一个主要因素,但用户也期望遥测收集基础设施的可靠性、可扩展性和可观察性。
我们在ServiceNow Cloud Observability的生产环境中运行了使用OTel-Arrow组件的OpenTelemetry Collector,作为收集内部遥测数据的主要代理已超过一年,并且我们将所学到的经验反馈到OTel-Arrow组件和OpenTelemetry Collector本身的改进中。
在这里,我们将简要介绍我们如何调整使用OTel-Arrow组件的OpenTelemetry Collectors,以提供可靠、可扩展的遥测交付。
OTel-Arrow exporter
OTel-Arrow exporter和receiver对旨在提供与核心OTLP/gRPC exporter和receiver对等的功能,以便用户可以在它们之间切换。OTel-Arrow组件最初源自这些组件,并且两者都支持OTLP/gRPC请求以及OTel-Arrow,集成在一个服务中。
OTel-Arrow exporter组件将OpenTelemetry数据进行转换,起始于一个同步导出调用,该调用携带一批OpenTelemetry traces、logs或metrics。导出上下文包括标准的gRPC元数据,如截止时间、跟踪上下文和每个请求的头部信息,所有这些上下文都会穿过OTel-Arrow流。请求被分派到流后,调用者会等待响应或截止时间过期,然后返回。
每个OTel-Arrow流维护内部状态,包括模式、字典和相关数据,这些数据可供未来的流请求引用。流请求由两个组件顺序编码和解码,允许它们维护正确的状态,这限制了每个流可以处理的数据量。增加exporter流的数量可以提高吞吐量,但每个流都有一定的开销,因此通常流的数量越少,压缩效果越好。
OTel-Arrow流是gRPC流,映射到HTTP/2流。流的生命周期由多个因素决定,包括中间负载均衡器协商的限制。OTel-Arrow exporter支持最大流生命周期配置,这会导致它按一定间隔自动重启流。流生命周期越长,压缩效果越好,但收益会递减。
OTel-Arrow exporter使用Collector内置的gRPC导出器配置机制(例如,endpoint、headers、TLS),并使用Collector的标准exporter支持,包括队列、重试和超时行为。由于这些组件有很多共同之处,包括endpoint配置,用户可以通过少量重新配置,在Collector配置中用OTel-Arrow exporters替换现有的OTLP exporters。
示例配置
exporters:
otelarrow:
endpoint: collector.local:4317
tls:
insecure: true
arrow:
num_streams: 1
OTel-Arrow receiver
OTel-Arrow receiver组件管理传入的OTel-Arrow流。receiver协调一个异步进程,具有每个流的读取器和写入器线程。管道操作使用独立的worker线程进行,使每个流都能最大化吞吐量。Receiver处理尽可能多的并发工作,但受到几个限制。有两个主要的配置参数控制OTel-Arrow receiver中的内存使用。
第一个限制控制活动流的总内存使用,包括模式、字典和相关数据。当达到内存限制时,receiver会以资源耗尽状态码终止该流。这可以防止receiver因意外的大流内存需求而耗尽内存。
第二个限制控制进入管道的数据量,涵盖OTLP和OTel-Arrow数据路径。当达到此限制时,单个请求或流会阻塞或立即失败,具体取决于并发等待者的数量限制。准入限制可以防止receiver因管道停滞而耗尽内存。
我们建议使用这些限制来控制OTel-Arrow管道中的内存,而不是使用标准的memory-limiter处理器。通过标准gRPC设置还有其他限制可以帮助管理内存和负载均衡,包括gRPC消息大小限制、每个连接的流限制和keep-alive限制。
当单个receiver的负载过大时,我们建议使用外部HTTP/2负载均衡器,以限制连接数、流数和连接生命周期。
示例配置
receivers:
otelarrow:
protocols:
grpc:
max_recv_msg_size_mib: 16
arrow:
memory_limit_mib: 128
admission:
request_limit_mib: 128
OTel-Arrow流中的批处理和背压
批处理大小对压缩性能有很大影响。更大的批处理通常能获得更好的压缩效果,但这会付出代价。更大的批处理需要更多的内存,使用更多的CPU,并增加管道的网络和CPU延迟,因此需要权衡这些因素。OpenTelemetry Collector用户有几种批处理选项可用,这些选项与其他因素相关,包括并发、队列和持久化的可用选项。
对于从其他源接收数据并通过OTel-Arrow exporter导出的网关Collector,我们建议使用完全同步的请求路径,即调用者在释放原始数据之前等待管道确认其请求。这样,当单个流饱和时,由于管道处理更多数据,延迟和内存使用量会上升。这种响应被称为“背压”,类似于物理管道中的压力。背压可以让遥测生产者知道管道是否出现问题,让他们有机会尝试连接到其他连接,并让服务运维人员根据内存利用率自动扩展实例数量以处理增加的负载。
有关详细信息,请参阅OTel-Arrow exporter的 批处理和背压文档。
性能
在ServiceNow Cloud Observability,我们评估了OpenTelemetry Collector作为内部traces和logs数据的网关。我们进行了一系列实验,使用了一个内部traces管道,该管道在采样后,平均每秒写入50万到60万个spans,通过OTel-Arrow桥,导出压缩数据约250-300 MB/秒。我们使用了OTel-Arrow exporter和receiver内置的OpenTelemetry仪表化,以量化管道在压缩、故障率和中位数延迟方面的性能。
实验设置如下图所示。在这里,数据从左到右流动,OpenTelemetry-instrumented应用程序通过OpenTelemetry标准OTLP over gRPC将遥测数据发送到网关Collector部署,并进行轮询负载均衡。网关Collector应用各种处理器,包括上面描述的并发批处理器,然后是OTel-Arrow exporter。

在桥梁的另一侧,一组Envoy负载均衡器将流分配到运行OTel-Arrow receiver的Collector池,在终止TLS之后。我们使用Envoy的轮询配置,因为我们发现它比最少负载策略更能有效地平衡长生命周期的流。我们将Envoy和OTel-Arrow receiver的HTTP/2 max_concurrent_streams设置配置为1,以改进负载均衡。
管道是完全同步的,原始OTel SDK和所有中间管道阶段都等待后端响应每个请求。两个Collector池都没有配置重试。我们配置OpenTelemetry SDK进行重试。
实验方法
由于这些实验是在实时生产系统上进行的,而且OTel-Arrow桥梁是端到端管道的一部分,其中还包括其他配置的处理器和专有后端等变量,因此我们仅将这些结果用于演示压缩性能的相对改进以及批量遥测传输的成本优势。
下面的实验结果中的每个试验时长为两小时,在测量之前,在测试配置下至少运行一小时。为了使试验有效,平均成功率必须高于99.95%,中位数管道延迟必须低于3秒。在测试的配置中,网关Collector实例池每vCPU/秒接收约35,000 spans/秒,导出约7,000 spans/秒(采样后)。网关Collector由Kubernetes水平Pod自动伸缩策略管理,目标CPU利用率为60%。
OTel-Arrow组件使用otelcol_exporter_sent、otelcol_exporter_sent_wire、otelcol_receiver_recv和otelcol_receiver_recv_wire指标,持续报告OTLP和OTel-Arrow协议的压缩和未压缩字节数,实验结果以timeseries查询结果报告,使用ServiceNow Cloud Observability度量查询。这些指标方便地标记了gRPC方法名称,便于在生产环境中监控压缩性能。
例如,使用以下查询计算导出器观测到的每个导出方法的压缩因子
with
uncompressed = metric otelcol_exporter_sent
| rate
| group_by ["method"], sum;
compressed = metric otelcol_exporter_sent_wire
| rate
| group_by ["method"], sum;
join uncompressed / compressed
我们将压缩数据报告为缩减因子,而不是压缩率,这样更大的值对应更好的性能。压缩率可以计算为缩减因子的数学倒数;例如,因子为20意味着结果小20倍,对应5%的压缩率。
测试了OpenTelemetry Collector和OTel-Arrow组件的版本0.105.0。
实验:压缩与流生命周期的关系
在本实验中,我们改变了OTel-Arrow exporter的最大流生命周期。假设压缩效果随着流持续时间的延长而提高,正如我们初步发现的那样,因为更长的流拥有更多的数据,为压缩提供了更大的机会。在本实验中,批次大小为4000-5000 spans,压缩后大小在250-300KiB范围内。
测试了五种最大流生命周期值,范围从3.75秒到4分钟,我们看到了流生命周期和压缩之间预期的关系。未测试超过4分钟的流生命周期,仅仅是因为测试中的OTel-Arrow receiver的gRPC keepalive设置限制了流的生命周期为5分钟。
| Stream lifetime | Exporter Reduction Factor |
|---|---|
| 3.75s | 15.6 |
| 15s | 16.3 |
| 1m | 16.9 |
| 2m | 17.2 |
| 4m | 17.1 |
通过OTLP协议传递的类似数据平均缩减因子为12.0。
OTel-Arrow exporter观察到的压缩缩减因子通常比receiver观察到的高1%,因为虽然它们观察到相同的压缩数据,但由于OTLP Resource和Scope值层次结构中的去重,桥梁两侧的未压缩大小不同。例如,在1分钟生命周期测试中,exporter将数据缩减了16.9倍,而receiver由于未压缩大小的变化,仅将数据扩展了16.8倍。
实验:压缩与批处理大小的关系
在另一个实验中,我们改变了上面描述的并发批处理器的批处理大小参数。众所周知,更大的批处理大小可以提高压缩效果,同时也会增加内存使用量和管道延迟。通常,后端服务对请求大小有上限,这限制了增加批处理大小的收益。
OTel-Arrow桥梁与一个类似配置的OTLP traces管道进行了比较。我们发现OpenTelemetry Protocol with Apache Arrow将网络带宽提高了约30%。
| Batch size parameters (min, max span count) | OTel-Arrow Exporter Average Reduction Factor | OTLP Exporter Average Reduction Factor |
|---|---|---|
| 1000–1250 | 16.4 | 11.9 |
| 2000–2500 | 17.2 | 12.0 |
| 4000–5000 | 17.7 | 12.2 |
实验:与OTLP的差异成本比较
项目开始时,我们的一个假设是,对于发送批量遥测数据的用户来说,压缩带来的好处将超过编码所需的额外计算资源的成本。我们对此指标尤其感兴趣,因为这影响到发送遥测数据到服务提供商的用户可观察性的总成本。在这里,我们比较了发送标准OTLP数据的成本与发送OTel-Arrow数据的成本。
虽然OTel-Arrow exporter比其对应的OTLP exporter使用的内存稍多,但差异并不显著影响成本,因为其他因素(包括垃圾回收)使得两个exporter需要相似的内存量,并且在测试的机器尺寸下,内存成本是CPU成本的10%。
我们对比较两种导出器配置的vCPU/小时成本和数量,以及发送的遥测数据GiB/小时数量感兴趣。在云计算环境中,一个vCPU/小时的价格通常低于一个GiB出口到公共互联网的成本。我们估计,通常情况下,一个vCPU/小时的成本是每GiB出口成本的四分之一到二分之一。
根据这个逻辑,当我们比较vCPU/小时的差异与导出的GiB的差异时,OTel-Arrow桥是经济上合理的。例如,在一个试验中,OTel-Arrow exporter平均使用了77.0 vCPU,并以107 GiB/小时的速度导出。在另一个具有相似聚合数据量的试验中,我们观察到OTLP exporter使用了53.7 vCPU,并导出了143 GiB/小时。在大多数云计算协议中,23 vCPU/小时的成本远低于36 GiB/小时的成本,因此采用OpenTelemetry with Apache Arrow桥将降低遥测传输的总成本。
摘要
我们报告了许多OTel-Arrow exporter配置的性能,在每种情况下,与OpenTelemetry OTLP编码相比,都提供了显著的压缩优势,而且没有牺牲可靠性或可扩展性。使用ServiceNow Cloud Observability的内部traces和logs数据,OTel-Arrow实现了比未压缩数据小15到30倍的压缩缩减,通常比OTLP协议节省30%到50%的网络带宽。
这仅仅是OpenTelemetry Protocol with Apache Arrow项目的开始。我们期望将Apache Arrow record batch处理的好处进一步扩展到OpenTelemetry Collector管道中。我们期待一个端到端的OpenTelemetry Protocol with Apache Arrow管道,具有显著更低的总体成本,其中OpenTelemetry SDK可以直接生成这种格式,并且遥测处理器可以基于Apache Arrow库编写。
更重要的是,我们已经证明,OTel-Arrow桥今天就可以降低整体遥测成本。OpenTelemetry Protocol with Apache Arrow已准备好投入生产使用。我们邀请用户和遥测系统采用OpenTelemetry Protocol with Apache Arrow组件,以降低遥测传输成本。如果您觉得这很有趣,并希望看到OpenTelemetry和Apache Arrow之间更多的集成,请加入我们的社区或在我们的 项目仓库 中发布一个问题。