接收处理器
Flume Sink 挂了怎么办?接收处理器帮你兜底
Flume 跑在生产上,最怕两件事:Sink 挂了数据发不出去,和单个 Sink 扛不住流量积压。
前几篇文章里,每个 Agent 都只配了一个 Sink。单点跑的没问题,但线上环境谁敢用单点?Sink 指向的 Kafka 集群抖动、HDFS 做安全模式、网络闪断,随便一个就能让采集链路瘫痪。
Flume 的 Sink Group + 接收处理器(Processor) 就是干这个的。这篇文章我讲清楚两种处理器怎么配、什么场景用哪个,以及我实际用下来的一些判断。
先搞清楚处理器是干什么的
一个 Agent 可以有多个 Sink,多个 Sink 组成一个 Sink Group。处理器(Processor)管的是:数据来了,往哪个 Sink 发?
Flume 官方提供三种接收处理器:
| 处理器类型 | 核心功能 | 适用场景 |
|---|---|---|
| DefaultSinkProcessor | 单 Sink 处理(不支持组) | 简单场景,无需冗余或负载均衡 |
| FailoverSinkProcessor | 故障转移(按优先级切换)主 Sink 挂了切到备 Sink | 需要高可用性的关键链路 |
| LoadBalancingSinkProcessor | 负载均衡(轮询或随机)多个 Sink 分摊流量 | 需要提升吞吐量的高并发场景 |
默认情况下,你只配了一个 Sink,用的就是 DefaultSinkProcessor,没冗余也没扩展。
故障转移(Failover)配置与原理
这个场景我遇到过:Kafka 集群要做滚动重启,每次重启一个 Broker,期间部分分区不可用。如果 Flume 只连一个 Kafka 集群,重启期间数据就发不出去。
用 Failover 可以配两个 Kafka Sink,指向不同的 Kafka 集群,主集群挂了自动切到备集群。
核心配置示例
以下配置实现两个 Kafka Sink 的故障转移,优先级高的 Sink 优先处理数据:
# 1. 定义 Sink Group(包含两个 Sink)
agent1.sinkgroups = g1
agent1.sinkgroups.g1.sinks = kafkaSink1 kafkaSink2
# 2. 配置故障转移处理器
agent1.sinkgroups.g1.processor.type = failover
# 配置优先级(数值越大优先级越高)
agent1.sinkgroups.g1.processor.priority.kafkaSink1 = 10 # 高优先级
agent1.sinkgroups.g1.processor.priority.kafkaSink2 = 5 # 低优先级
# 故障 Sink 的惩罚时间(毫秒):暂时“隔离”故障 Sink 的时间
agent1.sinkgroups.g1.processor.maxpenalty = 30000
# 3. 配置第一个 Kafka Sink(高优先级)
agent1.sinks.kafkaSink1.type = org.apache.flume.sink.kafka.KafkaSink
agent1.sinks.kafkaSink1.kafka.bootstrap.servers = kafka1:9092,kafka2:9092
# 4. 配置第二个 Kafka Sink(低优先级,备用)
agent1.sinks.kafkaSink2.type = org.apache.flume.sink.kafka.KafkaSink
agent1.sinks.kafkaSink2.kafka.bootstrap.servers = kafka3:9092,kafka4:9092
# 5. 绑定 Channel 到 Sink Group
agent1.sinks.kafkaSink1.channel = memoryChannel
agent1.sinks.kafkaSink2.channel = memoryChannel
工作逻辑:
- 正常情况下,所有数据走 kafkaSink1(优先级 10 最高)
- kafkaSink1 连不上(超时、连接拒绝),处理器把它标记为”故障”
- 自动切换到 kafkaSink2(优先级 5)
- kafkaSink1 进入 30 秒”惩罚期”,期间不会被选
- 30 秒后尝试恢复,正常了重新启用
几个实操建议:
- 优先级差值别太小。我一般设 5 以上的差距,避免两个 Sink 优先级太接近导致频繁判断。
- maxpenalty 设多少? 取决于你的 Sink 恢复需要多久。Kafka 集群重启一般 30-60 秒,我设 30000(30 秒)。太短的话,Sink 还没恢复好就被拉回来试,浪费资源;太长的话,恢复后不能及时复用。
- 别忘了监控。Flume 有
SinkProcessorFailoverCount这个指标,记录了故障切换次数。如果这个数字频繁上涨,说明主 Sink 一直不稳定,得去排查原因,而不是放任它切来切去。
负载均衡(Load Balancing)配置与原理
这个场景更常见。比如你的日志量特别大,单个 HDFS Sink 写入速度跟不上,Channel 越积越多,最后 OOM。
解决办法:配两个(或更多)HDFS Sink,指向不同的 HDFS 集群或者不同的目录,流量分摊。
核心配置示例
以下配置实现两个 HDFS Sink 的负载均衡,采用轮询策略:
# 1. 定义 Sink Group(包含两个 HDFS Sink)
agent1.sinkgroups = g1
agent1.sinkgroups.g1.sinks = hdfsSink1 hdfsSink2
# 2. 配置负载均衡处理器
agent1.sinkgroups.g1.processor.type = load_balance
# 选择负载均衡策略:round_robin(轮询)或 random(随机)
agent1.sinkgroups.g1.processor.selector = round_robin
# 是否启用回退机制(失败时自动切换到其他 Sink)
agent1.sinkgroups.g1.processor.backoff = true
# 失败重试间隔(指数退避)
agent1.sinkgroups.g1.processor.selector.maxTimeOut = 3000
# 3. 配置第一个 HDFS Sink(指向不同 HDFS 集群)
agent1.sinks.hdfsSink1.type = hdfs
agent1.sinks.hdfsSink1.hdfs.path = hdfs://hdfs-cluster1/flume-data/
# 4. 配置第二个 HDFS Sink(指向不同 HDFS 集群)
agent1.sinks.hdfsSink2.type = hdfs
agent1.sinks.hdfsSink2.hdfs.path = hdfs://hdfs-cluster2/flume-data/
# 5. 绑定 Channel 到 Sink Group
agent1.sinks.hdfsSink1.channel = memoryChannel
agent1.sinks.hdfsSink2.channel = memoryChannel
负载均衡策略
Flume 提供两种负载均衡策略,可以通过processor.selector属性指定:
| 策略 | 工作原理 | 适用场景 |
|---|---|---|
| round_robin | 按顺序轮流选择 Sink(如 Sink1 → Sink2 → Sink1…) | 流量均匀的场景,避免单个 Sink 压力过大 |
| random | 随机选择 Sink | 快速分散流量,适合突发流量场景 |
我一般用 round_robin,分配均匀、可预期。random 在流量分布不均匀的时候可能会导致某个 Sink 突然被大量命中,不好控制。
回退机制(Backoff)
当启用 backoff = true 时,
- 某个 Sink 如果写入失败了,处理器会暂时把它踢出可用列表
- 用指数退避算法(如初始 100ms,每次重试加倍)去重试;
- 若重试成功,重新将该 Sink 加入可用列表。
避免一个 Sink 出问题了还在持续给它分流量,浪费资源。
高级应用:组内负载均衡 + 组间故障转移
大一点的场景,可以两层嵌套:
- 组内:多个 Sink 负载均衡,分摊流量
- 组间:多个组之间故障转移,A 组全挂了切 B 组
# 1. 定义两个 Sink Group(每个组内负载均衡,组间故障转移)
agent1.sinkgroups = group1 group2
# 2. 配置第一个 Sink Group(包含两个 Kafka Sink,负载均衡)
agent1.sinkgroups.group1.sinks = kafkaSink1 kafkaSink2
agent1.sinkgroups.group1.processor.type = load_balance
agent1.sinkgroups.group1.processor.selector = round_robin
# 3. 配置第二个 Sink Group(包含两个 HDFS Sink,负载均衡)
agent1.sinkgroups.group2.sinks = hdfsSink1 hdfsSink2
agent1.sinkgroups.group2.processor.type = load_balance
agent1.sinkgroups.group2.processor.selector = round_robin
# 主处理器:组间故障转移
# 4. 配置主 Processor(故障转移:优先使用 group1,失败时切换到 group2)
agent1.sinks = failoverSink
agent1.sinks.failoverSink.type = org.apache.flume.sink.FailoverSink
agent1.sinks.failoverSink.sinkgroups = group1 group2
agent1.sinks.failoverSink.priority.group1 = 10
agent1.sinks.failoverSink.priority.group2 = 5
这种配置的好处是:正常情况下流量分散到两个 Kafka Sink,吞吐翻倍;Kafka 集群出问题了,整组切到 HDFS 做降级存储,数据不丢。
最佳实践与性能优化
1. 故障转移配置建议
- 优先级差异化:相邻 Sink 优先级差值≥5,避免因微小差异导致频繁切换;
- 惩罚时间:根据 Sink 恢复时间设置
maxpenalty(如 Kafka 集群重启需 30-60 秒); - 监控告警:结合 Flume 内置指标(如
SinkFailedCounter)监控故障切换频率,避免频繁故障。
2. 负载均衡配置建议
- 策略选择:
- 流量稳定场景用
round_robin,确保均匀分配; - 突发流量场景用
random,快速分散压力;
- 流量稳定场景用
- 回退机制:始终启用
backoff = true,避免向故障 Sink 持续发送数据; - Sink 数量:根据下游系统性能和数据量调整 Sink 数量(如 HDFS Sink 建议每 100MB/s 流量配置 1 个 Sink)。
3. 性能监控与调优
通过 JMX 或 Flume 内置指标监控 Sink Group 性能:
- 吞吐量:监控
SinkEventDrainSuccessCount指标,评估数据处理速率; - 失败率:监控
SinkEventDrainAttemptCount和SinkEventDrainFailedCount,计算失败率; - 故障切换频率:统计
SinkProcessorFailoverCount,过高表示存在频繁故障。