01 背景

Lancer是B站的实时流式传输平台,承载全站服务端、客户端的数据上报/采集、传输、集成工作,秒级提早,作为数仓入口是B站数据平台的生命线。目前每日峰值 5000w/s rps, 3PB/天, 4K+条流的数据同步能力。

服务如此大的数据规模,对产品的可靠性、可扩展性和可维护性提出了很高的要求。流式传输的实现是一个很有挑战的事件,聚焦快、准、稳的需要,  Lancer整体演进经验了大管道模型、BU粒度管道模型、单流单作业模型三个阶段的演进,上面咱们娓娓道来。

02 关键词阐明

logid:每个业务方上报的数据流以logid进行标识,logid是数据在传输+集成过程中的元信息标识。

数据源:数据进入到lancer的入口,例如:log-agent,bfe-agent,flink cdc

lancer-gateway(数据网关):接收数据上报的网关。

数据缓冲层:也叫做外部kafka,用于解耦数据上报和数据散发。

lancer-collector(数据散发层):也叫做数据同步,能够依据理论场景实现不同端到端的数据同步。

03 技术演进

整个B站流式数据传输架构的演进大抵经验了三个阶段。

3.1 架构V1.0-基于flume的

大管道数据传输架构(2019之前)

B站流式传输架构建设之初,数据流量和数据流条数绝对较少,因而采纳了全站的数据流混合在一个管道中进行解决,基于flume二次定制化的数据传输架构,架构如下:

  • 整个架构从数据生成到落地分为:数据源、数据网关、数据缓冲、数据散发层。
  • 数据上报端根本采纳sdk的形式间接发送http和grpc申请上报。
  • 数据网关lancer-gateway是基于flume二次迭代的数据网关,用于承载数据的上报,反对两种协定:http用于承载公网数据上报(web/app),grpc用于承载IDC内服务端数据上报。
  • 数据缓冲层应用kafka实现,用于解耦数据上报和数据散发。
  • 数据散发层lancer-collector同样是基于flume二次迭代的数据散发层,用于将数据从缓冲层同步到ODS。

v1.0架构在应用中暴露出一些的痛点:

1. 数据源端对于数据上报的可控性和容错性较差,例如:

  • 数据网关故障状况下,数据源端短少缓存能力,不能间接反压,存在数据失落隐患。
  • 重SDK:SDK中须要增加各种适配逻辑以应答上报异常情况

2. 整体架构是一个大管道模型,资源的划分和隔离不明确,整体保护老本高,本身故障隔离性差。

3. 基于flume二次迭代的一些缺点:

  • 逻辑简单,性能差,咱们须要的性能绝对繁多
  • hdfs散发场景,不反对exactly once语义,每次重启,会导致数据大量反复

3.2 架构V2.0-BU粒度的

管道化架构(2020-2021)

针对v1.0的缺点,咱们引入了架构v2.0,架构如下:

此架构的要害细节如下:

1. 强化了数据上报源端的边缘可控能力

  • 服务器上部署log-agent承载服务端数据上报。
  • cdn上部署bfe-agent用于承载公网(web端、app端)数据上报。
  • log-agent/bfe-agent中集成数据缓冲、预聚合、流控、重试、降级等能力,数据上报sdk只需专一数据的生成和上报逻辑。
  • agent端基于logid的BU属性,将数据路由到不同的管道。

2. 数据管道以BU为粒度搭建,管道间资源隔离,每个管道蕴含整套独立的残缺数据传输链路,并且数据管道反对基于airflow疾速搭建。故障隔离做到BU级别。

3. 数据网关降级到自研lancer-gateway2.0,逻辑精简,反对流控反压,并且适配kafka failover, 基于k8s进行部署。

4. hdfs散发基于flink jar进行实现:反对exactly once语义保障。

V2.0架构绝对于v1.0, 重点晋升了数据上报边缘的可控力、BU粒度管道间的资源划分和隔离性。然而随着B站流式数据传输规模的疾速减少,对数据传输的时效性、老本、品质也提出了越来越高的要求,V2.0也逐步暴露出了一些缺点:

1. logid级别隔离性差:

  • 单个管道外部某个logid流量陡增,几倍甚至几十倍,仍然会造成整个管道的数据散发提早,
  • 单个管道内散发层组件故障重启,例如:hdfs散发对应的flink jar作业挂掉重启,从checkpoint复原,此管道内所有的logid的hdfs散发都会存在归档提早隐患。

2. 网关是异步发送模型,极其状况下(组件解体),存在数据失落危险。

3. ods层部分热点/故障影响放大

  • 因为散发层一个作业同时散发多个logid,这种大作业模型更易受到ods层部分热点的影响,例如:hdfs某个datanode热点,会导致某个散发作业整体写阻塞,进而影响到此散发作业的其余logid, kafka散发同理。
  • hdfs单个文件块的所有正本生效,会导致对应散发工作整体挂掉重启。

4. hdfs小文件问题放大

  • hdfs散发对应的flink jar作业为了保障吞吐,整体设置的并发度绝对较大。因而对于管道内的所有logid,同一时刻都会关上并发度大小的文件数,对于流量低的logid,就会造成小文件数量变大的问题。

针对上述痛点,最间接的解决思路就是整体架构做进一步的隔离,以单logid为维度实现数据传输+散发。面临的挑战次要有以下几个方面:

  • 如何保障全链路以logid为单位进行隔离,如何在资源应用可控的状况下正当控流并且保障数据流之间的隔离性
  • 须要与内部零碎进行大量的交互,如何适配内部零碎的各种问题:部分热点、故障
  • 集成作业的数量指数级减少,如何保障高性能、稳定性的同时并且高效的进行治理、运维、品质监控。

3.3 架构V3.0-基于Flink SQL的

单流单作业数据集成计划

在V3.0架构中,咱们对整体传输链路进行了单作业单数据流隔离革新,并且基于Flink SQL撑持数据散发场景。架构如下:

相比v2.0, 资源池容量治理上仍然以BU为粒度,然而每个logid的传输和散发互相独立,互不影响。具体逻辑如下 :

  • agent:整体上报SDK和agent接管+发送逻辑依照logid进行隔离革新,logid间采集发送互相隔离。
  • lancer-gateway3.0:logid的申请解决之间互相隔离,当kafka发送碰壁,间接反压给agent端,上面具体介绍。
  • 数据缓冲层:每个logid对应一个独立的外部kafka topic,实现数据的缓冲。
  • 数据散发层:散发层对每个logid的启动独立的flink sql作业进行数据的散发,单个logid解决碰壁,只会导致当个logid的数据沉积。

相较于之前的实现,v3.0架构具备以下的劣势:

1. 可靠性:

  • 性能品质上整顿链路能够保证数据不失落,网关层以同步形式发送数据,能够保证数据被长久化到外部kafka;flink反对状态复原和exactly once的语义,同样保证数据不丢。

2. 可维护性上:

  • 隔离性上logid之间互相隔离,一个logid呈现问题,其余logid不受影响。
  • 资源分配以logid为最小单位,能够准确管制单个logid的资源应用。

3. 可扩展性:

  • 能够以单个logid为单位灵便管控:灵便的扩缩资源

04 V3.0架构具体实现

咱们重点介绍下,以后V3.0构造各个分层的实现。

4.1 数据上报边缘层

4.1.1 log-agent

基于go自研,插件化架构,部署于物理机,牢靠、高效的反对服务端数据上报。

工夫架构分为收集、解决、发送三层,具备以下次要个性:

  • 反对文件采集和unix sock两种数据上报形式
  • 与网关GRPC通信:ACK+退却重试+流控
  • 整体上报SDK和agent接管+发送逻辑依照logid进行隔离革新,单logid解决互相隔离:每个logid启动独立的pipeline进行采集、解析、发送。
  • 网关基于服务发现,自适应网关的调整
  • 发送碰壁状况下,基于磁盘进行本地沉积
  • logid粒度的埋点监控,实时监控数据的解决状态
  • CGroup资源限度:CPU + 内存
  • 数据聚合发送,晋升传输效率
  • 反对物理机和容器日志此采集,配置随利用公布,自适应配置的增、删、改。

4.1.2 bfe-agent

基于go自研,部署于cdn,用于承载公网数据上报。

边缘cdn节点,cdn服务器上部署nginx和bfe-agent,bfe-agent整体实现架构与log-agent相似,对于web和app端数据上报申请QPS高、突发性强的特点,次要强化了以下能力:

  • 应答流量陡增:基于边缘节点的本地缓冲起到削峰作用
  • 策略(降级、流控)前置,加强可控力
  • logid级别分流隔离, 反对等级划分
  • 聚合压缩回传以晋升数据传输效率、降低成本,回源QPS升高90%以上。

4.2 数据上报网关层

v3.0计划中,数据数据网关的架构如下:

数据网关性能个性如下:

  • kafka的通用代理层:反对grpc /http协定
  • 基于kafka send callback实现了同步发送模型,保证数据不丢:数据写入kafka后,再对申请返回ack
  • 申请不拆分:基于agent的聚合机制,只反对单次申请单条记录,因而一条记录对应一条缓存层kakfa的音讯
  • lancer-gateway3.0依据申请的topic信息,发送申请到对应的kafka集群
  • lancer-gateway3.0适配kafka集群的部分热点:反对partition动静剔除
  • logid与topic一一对应,解决流程中互相隔离:一个topic发送碰壁,不影响其余的topic

整个数据网关中的实现难点是:单gateway承载多logid解决的过程中如何保障隔离性和公平性,咱们参考了Golang 中GMP的机制,整体数据流程如下:

1. 收到的申请,会把申请放到logid对应的申请队列,如果队列满,间接拒绝请求

2. 每个kafka集群,会初始化一个N大小的kafka producer pool,其中每个producer会遍历所有的队列,进行数据的发送。

3. 对于每个logid的申请队列,会从两个保护限度资源的占用,以保障公平性和隔离性

  • 限度当个logid队列绑定的producer数量
  • 基于工夫片限定当个producer服务于单个队列的工夫长度

4.3 数据上报散发层

随着flink在实时计算畛域的成熟,其高性能、低提早、exactly once语义保障、批流一体、丰盛的数据源反对、沉闷的社区等劣势,促使咱们抉择了以flink sql作为数据散发层的解决方案。以后咱们次要反对了kafka→hive, kafka→kafka, cdc→kafka->hudi/hive三种场景:

1. kafka→hive

  • 以流式形式,实时导入数据到hive。
  • file rolling on check,保障exactly once。
  • 依照event time写入分区和归档,归档提早小于15min
  • 反对text+lzo(行存)和 orc+zstd(列存)两种存储格局。
  • 反对上游作业增量同步。

2. kafka→kafka

  • 以流式形式,反对数据的实时同步
  • 反对kafka header metadata信息的透传

3. cdc→kafka->hudi/hive

  • 以实时流的形式同步全量和增量数据,整个cdc的应用场景分为两个环节
  • cdc → kafka
  • 基于cdc 2.1,同步mysql的全量和增量binlog同步
  • 单sql作业反对分库分表、多库多表的同步。
  • 反对依据db和table自定义策略分流到不同的数据缓冲层kafka topic
  • kafka→hudi/hive
  • 生产单topic同步到单张hudi/hive表,反对event_time落分区。
  • 保证数据最终一致性

05 Flink connector性能迭代

在Flink SQL数据散发场景的反对中,针对咱们遇到的理论需要,对社区原生connector进行了对应的优化,咱们针对性的介绍下。

5.1 hive sink connector优化

断流空分区提交

背景:B站离线作业的拉起依赖上游分区提交,HDFS分区提交的判断依赖于作业整体watermark的推动,然而某些logid在断流的状况下,如何进行分区的提交呢

解决办法:

如图所示:当所有的StreamFileWriter间断两次checkpoint内未解决任何数据的状况下,StreamingFileCommiter会断定产生了断流,依照以后工夫提交分区。

反对上游增量数据同步

背景:传统形式ods到dwd的数据同步只有当ods层分区ready之后才会开始,时效性较差,如何减速数据的同步?

解决办法:

  • 不依赖ods层分区ready,当ods目录中文件生成后,即可开始数据的解决,以增量的形式读取数据文件。
  • 通过HDFS的list操作来获取须要读取的文件,对NameNode压力较大,为此咱们提供了文件list列表索引(包含文件名和数据条数),上游只须要读取索引,即可获取增量文件列表。
  • 实现中索引文件状态被长久化到state中,snapshot中生成.inflight状态临时文件,notifyCheckpointComplete中将文件rename成commit正式文件, 提供exactly once语义保障。
  • 上游作业读取文件索引,反对ods到dwd的增量数据同步。

orc+zstd

背景:相较于行式存储,列式存储在压缩比上有着显著的劣势。

解决办法:反对orc+zstd, 通过测试,相较于text+lzo,空间节俭在40%以上。

hdfs异步close

背景:snapshot阶段flush数据,close文件常常因为个别文件慢连累整体吞吐。

解决办法:

  • 将close超时的文件扔到异步队列中。也就是 close 的动作不会去梗塞整个主链路的解决,晋升hdfs部分热点状况下的吞吐。异步close 文件列表保留到pendingPartsForCurrentCheckpoint,并且长久化到 state 当中。故障复原时,也能持续对文件进行敞开。
  • 异步close的引入,会引入分区提前创立的隐患,为此引入了对于bucket状态的判断。对于某分区,只有当隶属于此分区的所有bucket中的pendingPartsForCurrentCheckpoint为空(所有文件都进行了敞开),才在commit算子中进行分区的提交。

小文件合并

背景:rolling on checkpoint的滚动策略,会导致文件数量的收缩,对namenode产生较大的压力。

解决办法:

  • 引入了小文件合并性能,在checkpoint实现后,由 Streaming writer 的 notifyCheckpointComplete 办法触发合并操作,向上游发送EndCheckpoint信号。
  • coordinator 收到每个writer的EndCheckpoint后,开始进行文件的分组,封装成一个个compactunit播送上游,全副unit发送完之后,再播送EndCompaction。
  • compact operator找到属于本人的工作后开始解决,当收到EndCompaction后,往上游发送分区提交信息。

5.2 kafka connector优化

反对protobuf format

背景:用户有解决protobuf格局数据的需要

解决办法:

  • 应用protoc 生成java类,打包jar,上传到实时计算平台。
  • 实现对应的DeserializationSchema和SerializationSchema,动静加载pb类并通过反射调用办法,实现pb bytes与RowData的互转。

kafka sink反对自定义分流

背景:用户心愿在一个sql作业中依据须要,灵便定制将音讯发送到指定kafka 集群和topic。

解决办法:

  • 反对用户自定义udf,灵便抉择sql中的字段作为udf的入参,在udf外部,用户依据业务场景定制逻辑,返回topic或者broker list。最终sink外部发送到对应的kafka集群和topic。
  • kakfa sink外部动静加载udf,通过反射机制实时获取对应的broker和topic,同时反对后果的缓存。
  • 例子:

    CREATE TABLE sink_test (  broker_name_arg varchar,  topic_name_arg varchar,  message string,  t1 string) WITH('bootstrapServers' = 'BrokerUdf(broker_name_arg)', // 依据broker_name_arg作为udf参数计算brokers'bootstrapServers.udf.class' = 'com.bilibili.lancer.udf.BrokerUdf', // 获取brokers Udf'topic' = 'TopicUdf(broker_name_arg, topic_name_arg)', // 依据broker_name_arg和topic_name_arg作为udf参数计算topic'topic.udf.class' = 'com.bilibili.lancer.udf.TopicUdf', // 计算topoc Udf'udf.cache.min' = '1', // 缓存工夫'exclude.udf.field' = 'false', // udf的相干字段是否输入'connector' = 'kafka-diversion');

5.3 cdc connector优化

sql场景下多库多表场景反对

背景:原生的flink cdc source在单个sql工作中,只能同步雷同DDL定义的表,如果须要同步异构DDL,不得不启动多个独立的job进行同步。这样会存在资源的额定开销。

解决办法:

  • sql定义去DDL:

    原生flink cdc source会对所有监听到的数据在反序列化时依据sql ddl定义做column转换和解析,以RowData的模式传给上游。咱们在cdc-source中新增了一种的format形式:changelog bytes序列化形式。该format在将数据反序列化时在不再进行column转换和解析,而是将所有column间接转换为changelog-json二进制传输,外层将该二进制数据间接封装成RowData再传给上游。对上游通明,上游在生产kafka数据的时候能够间接通过changelog-json反序列化进行数据解析。并且因为该改变缩小了一次column的转换和解析工作,通过理论测试下来发现除主动感知schema变更外还能晋升1倍的吞。在kafka sink connector中,依据db和table进行分流,能够反对发送到不同的topic。

  • 扩大metadata,增加sequence:

    将增量数据同步到kafka中,因为kafka存在多分区,因而必然会导致音讯乱序问题。因而须要提供一个单任务内严格枯燥递增的sequence,用于上游消费者进行排序,保证数据的最终一致性。最终咱们提取binlog中的gtid作为binlog音讯的sequence id,通过metadata的形式裸露解决来,写入kafka record的header中,对于全量数据,sequence设置为0。

断流场景分区提交反对

背景:因为整个cdc计划存在上游和上游两个独立的job,并且都是基于event time推动watermark做分区的提交,上游watermark的推动碰壁可能受到数据失常断流或者上游作业异样两种起因的影响,如果正确判断呢?

解决办法:

  • 在cdc source connector内定义一种新类型的record HeartbeatRecord,此record工夫为以后工夫。当发现某张表数据进行发送时,定期mock心跳数据进行发送。失常断流状况下,上游作业能够依据心跳信息失常推动watermark,并且能够过滤抛弃此信息。

  • 最终cdc connector sql样例:

    CREATE TABLE mysql_binlog (  host_name STRING METADATA              FROM 'host_name' VIRTUAL,  db_name STRING METADATA                FROM 'database_name' VIRTUAL,  table_name STRING METADATA             FROM 'table_name' VIRTUAL,  operation_ts TIMESTAMP(3) METADATA     FROM 'op_ts' VIRTUAL,  sequence BIGINT METADATA               FROM 'sequence' VIRTUAL,  // sequence严格枯燥递增  heartbeat BOOLEAN METADATA             FROM 'heartbeat'VIRTUAL, // 对于心跳信息标识为true  mtime TIMESTAMP(3) METADATA            FROM 'mtime'VIRTUAL, // 提取mtime,用于上游推动watermark  id BIGINT NOT NULL,  filed_list BYTES NOT NULL,  // 去DDL,在source外部数据全副依照changelog-json格局进行序列化、  PRIMARY KEY(id) NOT ENFORCED) WITH (  'connector' = 'mysql-cdc',  'hostname' = 'xxxx',  'port' = '3552',  'username' = 'datacenter_cdc',  'password' = 'xxx',  'database-name' = 'xxx',  'debezium.format' = 'bytes',  'table-name' = 'xxx',  'server-time-zone' = 'Asia/Shanghai',  'heartbeat.enable'='true',    'scan.incremental.snapshot.chunk.size' = '80960');

    06 架构稳定性优化

为了保障流式传输稳固和高效运行,咱们在以下几个方面做了一些优化,别离介绍下:

6.1 管道热点优化

作业在失常运行的过程中,常常遇到部分热点问题,例如kafka/hdfs io热点导致部分并行度生产速度降落或者写入碰壁、yarn队列机器load不平均导致作业局部并行度生产能力不如,尽管起因多种多样,然而实质看,这些问题的一个共性就是因为部分热点导致部分数据提早。针对这个问题,咱们别离从部分流量调度和全局流量调度两个维度进行优化。

部分流量调度

部分流量调度的优化思路是在单个producer和task外部,分区之间进行流量的重调配。目前在两个点就行了优化:

  • bsql Task manager外部subtask上下游通信优化:

    集成作业并没有keyby的需要,基于Flink Credit-based Flow Control反压机制,能够通过Backlog Size判断上游工作的解决负载,那么咱们就能够将Round-robin发送的形式批改为依据Channel的Backlog Size信息抉择负载更低的上游Channel发送的形式。留神:此种策略只有source和sink端之间是rebalance/rescale时,才有成果。会造成肯定的序列化开销,然而测试下来能够承受。

  • kafka producer partition主动剔除机制:

    kafka producer在发送数据callback异样(绝大多数是timeout)超出肯定的阈值,会将对应tp从available partition list中进行剔除,后续record将不再发送到剔除的tp。同时,被剔除tp后续将进行恢复性测试,如果数据能够失常发送,将从新放入到available partition list中。目前此机制在flink kafka sink connector和规范kafka client都进行了实现。

全局流量调度

全局流量调度的优化思路是整个传输链路层级之间的流量调配,目前咱们将生产者(lancer-gateway)与消费者(flink sql kafka source)进行联动,当消费者呈现tp生产lag的状况,通过注册黑名单(lag partition)到zookeeper,上游生产者感知黑名单,进行向高lag partition中持续发送数据。

Flink kafka source中基于flink AggregateFunction机制,kafka source subtask上报lag到job manager,job manager基于全局lag判断注册黑名单到zookeeper

黑名单判断逻辑:当单tp lag > min(全局lag平均值,全局lag中位数) 倍数 && 单tp lag 大于 lag绝对值, 其中 "单tp lag 大于 lag绝对值" 是为了躲避此机制过于敏感,"单tp lag > min(全局lag平均值,全局lag中位数) 倍数" 用于筛选出头部的lag tp。为了避免黑名单比例过大,黑名单剔除的tp数量下限不得大于全副tp数量的肯定比例。

部分流量调度和全局流量调度在管道热点优化成果上存在肯定的互补性,然而也各有劣势。

6.2 全链路埋点品质监控

数据品质是重要一环,通常数据品质蕴含完整性、时效性、准确性、一致性、唯一性等方面,对于数据传输场景,当面咱们重点关注完整性和时效性两个方面

整体品质计划大抵蕴含监控数据采集和规定配置两个大的方向,整体架构如下:

监控数据采集

咱们自研了trace零碎:以logid为单位,咱们在数据处理流程中的每一层都进行了监控埋点

  • 每层埋点蕴含三个方面:接管、发送、外部谬误。所有埋点数据以数据创立工夫(ctime)进行窗口对齐,并且通过更新utime以统计层间和层内的解决耗时。
  • 通过监控埋点能够实时统计出:端到端、层级间、层级外部的数据处理耗时、完整性、谬误数。
  • 以后计划缺点:flink sql挂掉从ck复原,监控数据不能保障幂等,后续须要进一步改良。

监控报警规定

咱们针对数据流进行了分级,每个等级指定了不同的保障级别(SLA),SLA破线,报警告诉oncall同学解决。

提早归档报警:hdfs分区提交提早,触发报警。

实时完整性监控:基于trace数据,实时监控端到端的完整性,接管条数/落地条数

离线数据完整性:hdfs分区ready后,触发dqc规定运行,比照接管条数(trace数据)/落地条数(hive查问条数)

传输提早监控:基于trace数据,计算端到端数据传输提早的分位数。

DQC阻塞:离线数据完整性异样后,阻塞上游作业的调度。

6.3 kafka同步断流反复优化

绝对比2.0计划中flume计划,基于flink sql的kafka到kafka的实现计划显著的一个变动就是作业的重启、故障复原会导致整体的断流和肯定比例的数据反复(从checkpoint复原),因而如何升高用户对此类问题的感知,至关重要。

首先梳理下可能造成问题呈现的起因:1)作业降级重启 2)task manager故障 3)job manager 故障 4)checkpoint间断失败,同时依据flink job整体提交流程,影响作业复原速度的关键环节是资源的申请。根据上述剖析和针对性测试,针对kafka同步场景的断流反复采纳了如下优化形式:

  • checkpoint interval设置成10s:升高从checkpoint复原导致的数据反复比例
  • 基于session模式提交作业:作业重启无需反复申请资源
  • jobmanager.execution.failover-strategy=region,单个tm挂掉后,只复原对应的region,不必复原整个作业。集成作业DAG绝对简略,能够尽量躲避rebalance的呈现,升高复原的比例。
  • 应用小资源粒度task manager(2core cpu,8GB memory,2 slot):等同资源规模下,tm数量变多,单tm挂掉影响水平显著变低。
  • 针对高优作业冗余task manager:冗余一个tm,当单个tm挂掉状况下,流量简直没受影响
  • 基于zookeeper实现job manager ha:在开启jm ha后,jm挂掉工作未断流
  • 针对checkpoint间断失败的场景,咱们引入了regional checkpoint,以region(而不是整个topology)作为checkpoint治理的单位,避免个别task的ck失败造成整个作业的失败,能够无效避免在个别task的ck间断失败的状况下须要回溯的数据量,减小集群稳定(网络,HDFS IO等)对checkpoint的影响

通过上述优化,通过测试一个(50core,400GB memory,50 slot)规模的作业,优化成果如下:

6.4 kafka流量动静failover能力

为了保证数据及时上报,Lancer对于数据缓冲层的kafka的发送成功率依赖性很高,常常遇到的case是高峰期或者流量抖动导致的kafka写入瓶颈。参考Netflix Hystrix 熔断原理,咱们在网关层实现了一种动静 kafka failover机制:网关能够依据实时的数据发送状况计算熔断率,依据熔断率将流量在normal kafka和failover kafka之间动静调节。

  • 基于滑动工夫窗口计算熔断比例:滑动窗口的大小为10,每个窗口中统计1s内胜利和失败的次数。

  • 熔断器状态:敞开/关上/半开,熔断率=fail_total/sum_total , 为防止极其状况流量全切到 failover,熔断率须要有一个下限配置。熔断后的降级策略:normal kafka 熔断后尝试切 failover,failover kafka 如果也熔断的话就切回 normal
  • 判断逻辑:

6.5 全链路流控、反压、降级

从端上上报到数据落地的整个流程中,为了保障稳定性和可控性,除了前述伎俩,咱们还引入了整体流控、反压、降级等技术手段,上面综合介绍下。

从后向前,分为几个环节:

1. 数据散发层:

  • 如果呈现生产提早,数据反压到数据缓冲层kafka
  • 单作业外部通过backlog反压做subtask之间的流量平衡

2. 数据网关层:

  • 如果写入kafka提早,间接返回流控码(429)给数据上报端
  • 数据网关层和数据散发层之间通过 kafka tp级别流控调度适配部分tp解决提早。

3. 数据上报层:

  • 适配数据网关的流控返回:做退却重试
  • 基于本地磁盘进行数据的沉积
  • 配置动静推送失效被动采样/降级沉积

6.6 开发阶段品质验证

为了在开发阶段保障整体服务的正确性和稳定性,开发阶段咱们设计了一套残缺的测试框架。

  • 新版本上线之前,咱们会同时双跑新旧两条作业链路,将数据别离落入两张hive表,并且进行全分区的条数和内容md5校验,校验后果以小时级别/天级别报表的模式收回。此测试框架保障了版本迭代的过程中,端到端的正确性。
  • 同时为了保障异样极其状况下数据的准确性,咱们也引入了混沌测试,被动注入一些异样。异样包含:job manager挂掉,taskmanager挂掉、作业随机重启、部分热点、脏数据等等。

07 将来瞻望

  • 链路架构降级,接入公司级的数据网关(Databus),架构对立并且能够涵盖更多的数据上报场景。
  • 云原生,拥抱K8S,面向用户quota治理,并且实现主动资源AutoScale。
  • 拥抱批流一体,强化增量化集成,笼罩离线批集成场景,打造对立基于Flink的统一化集成框架。