本文共 3342 字,大约阅读时间需要 11 分钟。
原文作者:ShiftLeft资深基础架构工程师,发布于2018年12月5日。本文最初。
时间序列(Time series)是ShiftLeft运行时体验的主要组成部分。对于很多其他产品和组织来说也是如此,但是,每种情况都涉及不同的特性和要求。本文描述了我们必须要用到的要求,我们如何使用来存储和检索时间序列数据,以及我们为管理基础架构而开发的工具。
我们有两类时间序列数据:指标和漏洞事件。指标代表应用事件,那些涉及安全问题的子集是漏洞事件。在这两种情况下,这些时间序列都具有某种ID、时间戳和计数。漏洞事件也可以有事件样本,其中包含实施安全漏洞要求的详细信息。除了这些属性之外,时间序列也可以由内部ID来键入,我们称该内部ID为SP ID,其本质上代表了特定版本的客户项目。
指标的数据模型与的源-汇模型(source-sink model)密切相关,因此,对于给定的应用,其方式和I/O以及数据流被组织成触发器、输入及输出。下图说明了这一点,它总结了一些充当触发器的典型端点,以及在这些端点处接收的输入最终到达输出(如日志)的流。我们很少查询单个指标的时间序列数据;通常,我们需要根据该数据模型查询大量相关指标。
流及其触发器、输入和输出端点的可视化以下是我们用于实施的要求:
到目前为止,我们发现最符合这些要求。TimescaleDB是开源的PostgreSQL插件,提供称为元数据表(hypertable)的特殊表,操作起来类似常规的PostgreSQL表,但在底层被划分为几个块。这些块可以是时间分区和用户定义的属性。在我们的案例中,我们把SP ID用作分区栏。这样可以快速更新和查询,有益于多个表的使用,无需在查询中处理分区逻辑。
我们的元数据表可以有上千个块。对于给定SP ID和时间范围,我们查询指标时,TimescaleDB会过滤掉不必要的块,只查询小子集以执行查询操作。元数据表的另一个优点是,我们能够通过而不是在大型表上运行昂贵的删除操作来快速清除旧数据。
最后,因为我们仍在使用PostgreSQL,所以可以利用已有的开发和运营经验。我们把其他PostgreSQL实例用于一些我们所需的其他SaaS数据存储,因此,我们受益于像Gaum这样的代码重用。还有很多支持PostgreSQL开箱即用的监控解决方案。
几乎所有的ShiftLeft是用Docker容器部署在编排系统上的。这包括TimescaleDB。我们也用Docker映像来进行测试,并拥有一个使用Docker Compose的复杂E2E测试套件。
大多数ShiftLeft运行时基础架构是用Go语言编写的。来自代理的运行时指标数据结束于网关实例,这些网关实例发布到Kafka主题。另一方面,我们有消费者实例,它们会摄取和汇总指标数据,偶尔会批量写入TimescaleDB。最小的粒度是2秒,在消费者中,我们也有1分钟和5分钟汇总粒度。ShiftLeft也有1小时和1天的粒度,但是,这是用批处理来管理的。
我们创建了一个时段下采样工作来支持更大的粒度,而无需在内存中汇总。在摄取时,我们定期地更新metrics_downsampling_status
表,这是用于存储下采样任务的表。
metrics_downsampling_status
表中的样本数据:
在这张表中,输入的更新与我们的5秒刷新汇总同步。当下采样任务运行时(每小时一次),它寻找状态表中没有处理过的行,把5秒粒度的数据汇总成1小时或1天的粒度,然后再更新该状态表。
我们的指标API是用Go语言编写的,它的逻辑是根据请求来使用最佳(或几个)粒度)。比如,如果一个5小时的间隔要求有60个点,这意味每个点是5分钟,因此,我们可以使用5分钟粒度的数据。任何比在5小时范围内采样60个点小的任务意味着我们必须使用1分钟或2秒钟的粒度。汇总计数(除了图表外)表现得像图表,只是用1个点而已。
粒度逻辑示例:
我们在查询上的问题是,有时候在计划上花费了太多时间。在有个例子中,我们观察到一个查询花费17秒来计划,但只用了250毫秒来执行。随着0.10版本的发布,这个问题得到了解决,0.10版显著地改善了查询的块交互。可以阅读以了解更多有关Timescale在这个改进方面的工作。
##示例
漏洞事件可以有查询的详细信息,包括HTTP路径和表头的请求信息。其中的一些事件利用JSONB列进行采样并在元数据表中存储为JSON。通这个方法,我们可以灵活地使用JSON和非结构性数据,以及元数据表的运营优势。
我们用多种方式监控请求、TimescaleDB和相关组件。为了监控查询性能,我们结合使用PgHero和应用程序指标。PgHero使用pg_stat_statements,并提供对顶层查询的粗略视图。在实践中,我们通常没觉得这有用,因为我们的查询往往很快,而我们的请求延迟主要来自于执行大量的这类查询,而不是单个慢速的查询。大多数时间序列指标请求监控使用Prometheus指标来完成,它们通过API和Grafana可视化展示出来。
平均指标延迟在摄取监控方面,我们密切关注DB写入速率和延迟。
数据库写入速率 刷新指标到TimescaleDB的平均延迟时间我们还广泛使用Grafana和PostgreSQL,但是出于运营目的,同时,不从元数据表中提取时间序列。通过使用Grafana中的PostgreSQL数据源选项,我们可以针对任何PostgreSQL数据库,在查询的基础上创建可视化。我们的下采样图表就是好例子。这些例子利用前面所描述的metrics_downsampling_status表,并让我们关注待做的工作和处理时间。
利用Grafana来监控下采样作业状态以下是Grafana图表的SQL查询之一:
平均下采样作业延迟时间当缩小像90天这样比较长的时间段时,可以清楚地看到一些有趣的趋势。在我们的例子中,下采样任务用时开始变得越来越长。它们仍然保持在平均2秒钟,因此,我们还没有遇到任何问题。
长期下采样延迟趋势我们一直在用kafka运行基础架构,并在生产环境中用了一段时间的TimescaleDB,在功能使用和监控方面已经用它完成了很多不同的工作。换句话说,还有些地方我们希望能看到改进,也即我们管理基础架构的方式和TimescaleDB可以实现的功能。
我们如何能够改进基础架构
最佳块的大小:我们还未决定最佳块的大小,我们也还未尝试自适应组块。只读副本:我们还未使用只读副本。通过添加只读副本和并行化请求,我们可以轻松地提高只读查询性能。
PostgreSQL 10: 我们还在使用PostgreSQL 9.6。PostgreSQL 10引入了JIT编译和WHERE语句的评估,这可以真正地改进那些必须过滤很多行的查询。
更好的摄取监控:我们对PostgreSQL有很多可见性,但是,对在PostgreSQL之前指标上发生的事情没有可见性。例如,关于指标消息在API上被接受直到进入TimescaleDB所需的时间,我们想要有更好的指标。
我们希望从TimescaleDB看到的东西
RDS支持:TimescaleDB是我们自己托管的唯一数据库。其他的PostgreSQL实例托管在RDS上。如果TimescaleDB是受支持的插件,我们可能都用RDS了。压缩:我们可以用ZFS来压缩,但是还未尝试。压缩还不是主要的需求。如果TimescaleDB支持开箱即用压缩,那是太好不过了。
阅读英文原文:
转载地址:http://ttxna.baihongyu.com/