前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用ClickHouse对每秒6百万次请求进行HTTP分析

使用ClickHouse对每秒6百万次请求进行HTTP分析

作者头像
后场技术
发布2020-09-03 15:27:44
3.1K0
发布2020-09-03 15:27:44
举报
文章被收录于专栏:后场技术

我们在Cloudflare的一个大规模数据基础架构挑战是为我们的客户提供HTTP流量分析。我们所有客户都可以通过两种方式使用HTTP分析:

在这篇博文中,我将谈谈去年Cloudflare分析管道的令人兴奋的演变。我将首先介绍旧管道以及我们遇到的挑战。然后,我将描述我们如何利用ClickHouse构建新的和改进的管道的基础。在此过程中,我将分享有关我们如何进行ClickHouse的架构设计和性能调整的详细信息。最后,我期待数据团队将来考虑提供什么。

让我们从旧数据管道开始。

老数据管道架构

之前的管道建于2014年。之前已经在使用CitusDB和更多数据扩展PostgreSQL for CloudFlare Analytics,以及来自Data团队的更多数据博客文章中提到过。 它有以下组件:

  • 日志转发器: 从边缘收集Cap'n Proto格式化日志,特别是DNS和Nginx日志,并将它们发送到Cloudflare中央数据中心的Kafka。
  • Kafka集群: 由106个具有x3复制因子的代理组成,106个分区,以平均每秒6M日志的速度摄取Cap'n Proto格式化日志。
  • Kafka消费者:106个分区中的每个分区都有专门的Go消费者(又名Zoneagg消费者),每个区域每分钟读取日志并生成聚合,然后将它们写入Postgres。
  • Postgres数据库:单实例PostgreSQL数据库(又名RollupDB),接受来自Zoneagg使用者的聚合,并按分区每分钟将它们写入临时表。然后,它使用聚合cron将聚合汇总到更多聚合中。进一步来说:
    • 每个分区,分钟,区域的聚合→每分钟聚合数据,区域
    • 每分钟聚合,区域→每小时聚合数据,区域
    • 每小时聚合,区域→每天聚合数据,区域
    • 每天聚合,区域→每月聚合数据,区域
  • Citus Cluster:由Citus master和11位Citus工作者组成,具有x2复制因子(又名Zoneagg Citus集群),Zone Analytics API背后的存储以及我们的BI内部工具。它有复制cron,它将表格从Postgres实例远程复制到Citus工作分片。
  • Zone Analytics API:来自内部PHP API的服务查询。它由5个用Go和查询的Citus集群编写的API实例组成,对外部用户不可见。
  • PHP API:3个代理API实例,它将公共API查询转发到内部Zone Analytics API,并在区域计划,错误消息等方面具有一些业务逻辑。
  • Load Balancer:nginx代理,将查询转发到PHP API / Zone Analytics API。

自从该管道最初于2014年设计以来,Cloudflare已经大幅增长。它开始以每秒1M的请求处理,并且发展到当前每秒6M请求的水平。多年来,管道为我们和我们的客户提供了很好的服务,但在接缝处开始分裂。在需求发生变化时,应在一段时间后重新设计任何系统。

原始管道的一些具体缺点是:

  • Postgres SPOF:单个PostgreSQL实例是一个SPOF(单点故障),因为它没有副本或备份,如果我们丢失了这个节点,整个分析管道可能会瘫痪并且不会为Zone Analytics API产生新的聚合。
  • Citus master SPOF:Citus master是所有Zone Analytics API查询的入口点,如果它发生故障,我们所有客户的Analytics API查询都会返回错误。
  • 复杂的代码库:用于聚合的数千行bash和SQL,以及数千行Go和API和Kafka消费者使得管道难以维护和调试。
  • 许多依赖项:由许多组件组成的管道,以及任何单个组件中的故障都可能导致整个管道停止。
  • 高昂的维护成本:由于其复杂的架构和代码库,经常发生事故,有时需要数据团队和其他团队的工程师花费数小时来缓解。

随着时间的推移,随着我们的请求数量的增长,操作此管道的挑战变得更加明显,我们意识到这个系统正在被推到极限。这种认识激发了我们思考哪些组件将成为替代的理想候选者,并促使我们构建新的数据管道。

我们的第一个改进分析管道设计以使用Apache Flink流处理系统为中心。我们以前曾使用Flink作为其他数据管道,所以对我们来说这是一个很自然的选择。但是,这些管道的速度远远低于我们需要为HTTP Analytics处理的每秒6M请求,并且我们很难让Flink扩展到此卷 - 它无法跟上每个分区的摄取率每秒所有6M HTTP请求。

我们的DNS团队的同事已经在ClickHouse上构建并生成了DNS分析管道。他们在Cloudflare如何分析每秒1M DNS查询博客文章中写到了这一点。所以,我们决定深入研究一下ClickHouse。

ClickHouse

“ClickHouseнетормозит。” 来自俄语的翻译:ClickHouse没有刹车(或者不慢) ©ClickHouse核心开发者

在探索替换旧管道的一些关键基础架构的其他候选者时,我们意识到使用面向列的数据库可能非常适合我们的分析工作负载。我们希望确定一个面向列的数据库,该数据库具有水平可扩展性和容错性,可以帮助我们提供良好的正常运行时间保证,并且具有极高的性能和空间效率,从而可以处理我们的规模。我们很快意识到ClickHouse可以满足这些标准,然后是一些标准。

ClickHouse是一个面向开源列的数据库管理系统,能够使用SQL查询实时生成分析数据报告。它速度快,线性可扩展,硬件高效,容错,功能丰富,高度可靠,简单易用。ClickHouse核心开发人员在解决问题,合并和维护我们的PR到ClickHouse方面提供了很大的帮助。例如,Cloudflare的工程师在上游贡献了大量代码:

  • Marek Vavruša的聚合函数topK
  • Marek Vavruša的IP前缀字典
  • Marek Vavruša对SummingMergeTree引擎进行了优化
  • Kafka Marek Vavruša表引擎。我们想用这个引擎取代Kafka Go的消费者,因为它足够稳定,可以直接从Kafka摄取到ClickHouse。
  • 聚合函数sumMap由Alex Bocharov。如果没有此功能,则无法构建新的Zone Analytics API。
  • 由Alex Bocharov 标记缓存修复
  • uniqHLL12功能修复 Alex Bocharov的大基数。问题的描述及其修复应该是一个有趣的阅读。

除了提交许多错误报告外,我们还会报告我们在群集中遇到的每个问题,我们希望将来有助于改进ClickHouse。

尽管ClickHouse上的DNS分析取得了巨大成功,但我们仍然怀疑我们是否能够将ClickHouse扩展到HTTP管道的需求:

  • 对于HTTP请求主题,Kafka DNS主题平均每秒有1.5M消息,而每秒6M消息。
  • 对于HTTP请求主题,Kafka DNS主题平均未压缩消息大小为130B,而对于1630B。
  • DNS查询ClickHouse记录包含40列和104列,用于HTTP请求ClickHouse记录。

在尝试使用Flink失败后,我们对ClickHouse能够跟上高摄取率持怀疑态度。幸运的是,早期的原型显示出了良好的性能,我们决定继续进行旧的管道更换。替换旧管道的第一步是为新的ClickHouse表设计一个模式。

ClickHouse架构设计

一旦我们将ClickHouse确定为潜在候选者,我们就开始探索如何移植现有的Postgres / Citus模式以使它们与ClickHouse兼容。

对于我们的Zone Analytics API,我们需要为每个区域(域)和时间段(每分钟/每小时/每日/每月)生成许多不同的聚合。要深入了解聚合的具体信息,请遵循Zone Analytics API文档或此便捷电子表格。

这些聚合应该适用于过去365天的任何时间范围。虽然ClickHouse是一个非常好的工具来处理非聚合数据,但我们的每秒6M请求量,我们只能负担不长时间存储非聚合数据。

为了让您了解这是多少数据,这里有一些“餐巾 - 数学”容量规划。我将使用每秒6M请求的平均插入速率和100美元作为1 TiB的成本估算来计算不同消息格式的1年存储成本:

Metric

Cap'n Proto

Cap'n Proto (zstd)

ClickHouse

消息平均大小/记录大小

1630 B

360 B

36.74 B

存储一年

273.93 PiB

60.5 PiB

18.52 PiB (RF x3)

存储年费用

$28M

$6.2M

$1.9M

那就是如果我们假设每秒的请求将保持不变,但实际上它一直在快速增长。 尽管存储要求非常可怕,但我们仍在考虑将原始(非聚合)请求日志存储在ClickHouse中1个月+。请参阅下面的“数据API的未来”部分。

非聚合请求表

我们存储超过100列,收集有关通过Cloudflare传递的每个请求的大量不同类型的指标。其中一些列也可在我们的Enterprise Log Share产品中使用,但ClickHouse非聚合请求表包含更多字段。

由于存储了如此多的列和巨大的存储要求,我们决定继续使用聚合数据方法,这种方法在旧流水线之前适用于我们,这将为我们提供向后兼容性。

聚合架构设计#1 根据API文档,我们需要提供许多不同的请求细分并满足这些要求,我们决定测试以下方法:

  1. 使用ReplicatedAggregatingMergeTree引擎创建Cickhouse物化视图,该引擎指向非聚合请求表,并包含每个细分的精确聚合数据:
  • 请求总计 - 包含总请求,字节,威胁,唯一身份等数字。
  • 按colo的请求 - 包含请求,字节等由edgeColoId细分 - 120多个Cloudflare数据中心
  • 按http状态发出的请求 - 包含HTTP状态代码的细分,例如200,404,500等。
  • 按内容类型的请求 - 包含按响应内容类型分类,例如HTML,JS,CSS等。
  • 按国家/地区的请求 - 包含客户所在国家 /地区的细分(基于IP)
  • 威胁类型的请求 - 包含威胁类型的细分
  • 浏览器请求 - 包含从用户代理提取的浏览器系列细分
  • ip class的请求 - 包含客户端IP类的细分
  1. 使用两种方法编写来自所有8个物化视图的代码收集数据:
  • 使用JOIN一次查询所有8个物化视图
  • 分别并行查询8个物化视图中的每一个
  1. 针对常见的Zone Analytics API查询运行性能测试基准

架构设计#1效果不佳。ClickHouse JOIN语法强制编写超过300行SQL的怪异查询,多次重复所选列,因为您只能在ClickHouse中进行成对连接。

至于并行分别查询每个物化视图,基准显示了显着但温和的结果 - 查询吞吐量比使用基于Citus的旧管道架构要好一点。

聚合架构设计#2

在模式设计的第二次迭代中,我们努力保持与现有Citus表类似的结构。为此,我们尝试使用SummingMergeTree引擎,该引擎由优秀的ClickHouse文档详细描述:

此外,表可以具有以特殊方式处理的嵌套数据结构。如果嵌套表的名称以“Map”结尾,并且它包含至少两列符合以下条件的列...则此嵌套表将被解释为key =>(values ...)的映射,以及合并时它的行,两个数据集的元素由'key'合并为相应的(值...)的总和。

我们很高兴找到这个功能,因为与我们的初始方法相比,SummingMergeTree引擎允许我们显着减少所需的表数。同时,它允许我们匹配现有Citus表的结构。原因是以'Map'结尾的ClickHouse嵌套结构类似于Postgres hstore数据类型,我们在旧管道中广泛使用它。

但是,ClickHouse地图存在两个问题:

  • SummingMergeTree对具有相同主键的所有记录进行聚合,但是所有分片的最终聚合应该使用一些聚合函数来完成,而这在ClickHouse中是不存在的。
  • 对于存储唯一身份用户(基于IP的唯一访问者),我们需要使用AggregateFunction数据类型,尽管SummingMergeTree允许您创建具有此类数据类型的列,但它不会对具有相同主键的记录执行聚合。

要解决问题#1,我们必须创建一个新的聚合函数sumMap。幸运的是,ClickHouse源代码具有卓越的品质,其核心开发人员非常有助于审查和合并所请求的更改。

对于问题#2,我们必须将uniques放入单独的物化视图中,该视图使用ReplicatedAggregatingMergeTree Engine并支持对具有相同主键的记录合并AggregateFunction状态。我们正在考虑将相同的功能添加到SummingMergeTree中,因此它将进一步简化我们的架构。

我们还为Colo端点创建了一个单独的物化视图,因为它的使用率较低(Colo端点查询为5%,Zone仪表板查询为95%),因此其更分散的主键不会影响Zone仪表板查询的性能。 一旦架构设计可以接受,我们就进行了性能测试。

ClickHouse性能调整

我们在ClickHouse中探索了许多提高性能的途径。这些包括调整索引粒度,并改善SummingMergeTree引擎的合并性能。

默认情况下,ClickHouse建议使用8192索引粒度。有一篇很好的文章深入解释了ClickHouse主键和索引粒度。

虽然默认索引粒度可能是大多数用例的绝佳选择,但在我们的例子中,我们决定选择以下索引粒度:

  • 对于主要的非聚合请求表,我们选择了索引粒度为16384.对于此表,查询中读取的行数通常为数百万到数十亿。在这种情况下,较大的索引粒度不会对查询性能产生巨大影响。
  • 对于聚合的requests_ * stables,我们选择了索引粒度为32.当我们只需要扫描并返回几行时,低索引粒度是有意义的。它在API性能方面产生了巨大的差异 - 当我们改变索引粒度8192→32时,查询延迟减少了50%,吞吐量增加了~3倍。

与性能无关,但我们还禁用了min_execution_speed设置,因此扫描几行的查询不会返回异常,因为每秒扫描行的速度“慢”。

在聚合/合并方面,我们也进行了一些ClickHouse优化,比如将SummingMergeTree地图的合并速度提高了x7倍,我们将其贡献回ClickHouse以获得每个人的利益。

一旦我们完成了ClickHouse的性能调优,我们就可以将它们整合到一个新的数据管道中。接下来,我们将介绍基于ClickHouse的新数据管道的体系结构。

新数据管道架构

新的管道架构重新使用旧管道中的一些组件,但它取代了其最弱的组件。 新组件包括:

  • Kafka消费者 - 每个分区106个消费者使用Cap'n Proto原始日志并提取/准备所需的100多个ClickHouse字段。消费者不再做任何聚合逻辑。
  • ClickHouse群集 - 具有x3复制因子的36个节点。它处理非聚合请求日志提取,然后使用物化视图生成聚合。
  • Zone Analytics API - Go中重写和优化的API版本,包含许多有意义的指标,运行状况检查和故障转移方案。

正如您所看到的,新管道的体系结构更加简单且容错。它为我们所有7M +客户的域提供分析,每月独立访问量超过25亿,每月页面浏览量超过1.5万亿。

平均而言,我们每秒处理6M HTTP请求,峰值高达每秒8M请求。

Cap'n Proto格式的 平均日志消息大小曾经是~1630B,但由于我们的平台运营团队对Kafka压缩的惊人工作,它显着下降。请参阅“压缩firehose:从Kafka压缩中获取最多”博客文章,深入了解这些优化。

新管道的好处

  • 没有SPOF - 删除所有SPOF和瓶颈,一切至少有x3复制因子。
  • 容错 - 它更容错,即使Kafka使用者或ClickHouse节点或Zone Analytics API实例失败,它也不会影响服务。
  • 可扩展 - 随着我们的发展,我们可以添加更多Kafka代理或ClickHouse节点并扩展摄取。当群集将增长到数百个节点时,我们对查询性能不太有信心。但是,Yandex团队设法将他们的集群扩展到500多个节点,使用两级分片在几个数据中心之间进行地理分布。
  • 降低复杂性 - 由于删除了混乱的crons和消费者正在进行聚合和重构API代码,我们能够:
    • 关闭Postgres RollupDB实例并将其释放以供重用。
    • 关闭Citus群集12个节点并将其释放以供重用。由于我们不再将Citus用于严重工作负载,因此我们可以降低运营和支持成本。
    • 删除成千上万行旧的Go,SQL,Bash和PHP代码。
    • 删除WWW PHP API依赖项和额外延迟。
  • 改进的API吞吐量和延迟 - 使用以前的管道Zone Analytics API难以每秒提供超过15个查询,因此我们不得不为最大用户引入临时硬率限制。使用新的管道,我们能够删除硬率限制,现在我们每秒服务约40次查询。我们进一步对新API进行了密集负载测试,并且通过当前的设置和硬件,我们每秒可以提供大约150个查询,并且可以通过其他节点进行扩展。
  • 操作更简单 - 关闭许多不可靠的组件,我们终于可以相对容易地操作此管道。ClickHouse质量在这件事上对我们有很大的帮助。
  • 事故数量减少 - 随着新的更可靠的管道,我们现在发生的事故比以前更少,最终减少了通话负担。最后,我们可以在晚上安然入睡:-)。

最近,我们通过更好的硬件进一步提高了新流水线的吞吐量和延迟。我将在下面提供有关此群集的详细信息。

我们的ClickHouse集群

我们总共有36个ClickHouse节点,我们做过一次新硬件大升级。

  • 机箱 - 广达D51PH-1ULH机箱代替Quanta D51B-2U机箱(物理空间减少2倍)
  • CPU - 40个逻辑内核E5-2630 v3 @ 2.40 GHz而不是32个内核E5-2630 v4 @ 2.20 GHz
  • RAM - 256 GB RAM而不是128 GB RAM
  • 磁盘 - 12 x 10 TB希捷ST10000NM0016-1TT101磁盘代替12 x 6 TB东芝TOSHIBA MG04ACA600E
  • 网络 - MC-LAG中的2 x 25G Mellanox ConnectX-4,而不是2 x 10G Intel 82599ES

我们的平台运营团队注意到,ClickHouse还不能很好地运行异构集群,因此我们需要逐步用新硬件替换现有集群中的所有节点,全部36个。这个过程非常简单,与替换失败的节点没什么不同。问题是ClickHouse没有限制恢复。

以下是有关我们群集的更多信息:

  • 平均插入率 - 我们所有的管道每秒汇集11M行。
  • 平均插入带宽 - 47 Gbps。
  • 每秒平均查询数 - 平均每秒群集服务大约每秒40次查询,频率峰值高达每秒约80次查询。
  • CPU时间 - 在最近的硬件升级和所有优化之后,我们的集群CPU时间非常短。
  • 最大磁盘IO(设备时间) - 它也很低。

为了尽可能无缝地切换到新管道,我们从旧管道执行历史数据传输。接下来,我将讨论此数据传输的过程。

历史数据传输 由于我们有1年的存储要求,我们不得不从旧的Citus集群到ClickHouse进行一次性ETL(提取转移负载)。

在Cloudflare,我们喜欢Go及其goroutines,因此编写一个简单的ETL工作非常简单,其中:

  • 对于每分钟/小时/日/月,从Citus群集中提取数据
  • 将Citus数据转换为ClickHouse格式并应用所需的业务逻辑
  • 将数据加载到ClickHouse中

整个过程耗时数天,成功传输了超过60亿行数据,并进行了一致性检查。这个过程的完成最终导致了旧管道的关闭。但是,我们的工作并没有就此结束,我们不断展望未来。在下一节中,我将分享一些有关我们计划的细节。

数据API的未来

日志推送

我们目前正在研究一种名为“Log Push”的东西。日志推送允许您指定所需的数据端点,并定期自动发送HTTP请求日志。目前,它处于私人测试状态,并支持将日志发送到:

  • 亚马逊S3存储桶
  • Google Cloud Service存储桶
  • 其他存储服务和平台

预计很快就会推出,但如果您对这款新产品感兴趣并希望试用,请联系我们的客户支持团队。

记录SQL API

我们还在评估构建名为Logs SQL API的新产品的可能性。我们的想法是通过灵活的API为客户提供对日志的访问,该API支持标准SQL语法和JSON / CSV / TSV / XML格式响应。

查询可以提取:

  • 原始请求记录字段(例如SELECT field1,field2,... FROM FROM WHERE ...)
  • 来自请求日志的聚合数据(例如SELECT clientIPv4,count()FROM请求GROUP BY clientIPv4 ORDER BY count()DESC LIMIT 10)

Google BigQuery提供类似的SQL API,亚马逊也提供产品调用Kinesis数据分析,并支持SQL API。

我们正在探索的另一个选项是提供类似于带有过滤器和维度的DNS Analytics API的语法。

我们很高兴听到您的反馈并了解有关您的分析用例的更多信息。它可以帮助我们构建新产品!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-09-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 后场技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 老数据管道架构
  • ClickHouse
  • ClickHouse架构设计
  • 非聚合请求表
  • ClickHouse性能调整
  • 新数据管道架构
  • 我们的ClickHouse集群
  • 数据API的未来
相关产品与服务
腾讯云 BI
腾讯云 BI(Business Intelligence,BI)提供从数据源接入、数据建模到数据可视化分析全流程的BI能力,帮助经营者快速获取决策数据依据。系统采用敏捷自助式设计,使用者仅需通过简单拖拽即可完成原本复杂的报表开发过程,并支持报表的分享、推送等企业协作场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档