flume 自定义需求 - 组合队列(FileAndMemoryChannel)

需求背景

event
event
游戏服
中转服
数据中心

如上,公司游戏的传输路线如图,在公司游戏服会部署flume,进行日志采集,作为日志传输拓扑的最前沿,如果下游中转服和数据中心出现问题,而造成堵塞,游戏服也会逐渐堵塞而导致无法继续接受数据,所以,如何在游戏无法缓存太多数据和频繁重发的情况,我们需要在游戏服部署一个尽可能多的存大量数据,从而防止堵塞,进而影响游戏

flume 自带channel缺陷

flume自身提供Channel有两种,一种是MemoryChannel, 一种是FileChannel。
优劣势对比:

对比MemoryChannelFileChannel
劣势内存容量远小于磁盘容量,重启内存数据丢失文件操作为磁盘操作,慢
优势基于内存存取数据,速度快,吞吐量大队列可以无限大,重启不丢数据

这两种Channel的数据结构都是队列,先进先出。Flume源码中MemoryChannel用的是Java的双端阻塞队列 LinkedBlockingDeque。
@GurardedBy(value = "queueLock")
private LinkedBlockingDeque<Event> queue;

通过查找Flume性能测试报告,可以大致得知 MemoryChannel的性能比FileChannel的性能高5-10倍左右,但是这个完全取决于不同的配置,对于FileChannel来说,每次批处理的大小,也就是事务处理Event的量(TransactionCapacity)直接影响到性能。

自定义Channel的产生背景 — MemoryAndFileChannel

公司的游戏日志采集逻辑是这样的,有两部分数据:
1、游戏的实时数据 (通过FlumeSDK 发送到游戏服上的Flume)
2、每个小时的20分统一发送上个小时的数据(数据源于游戏打印的不规范日志文件,通过定时跑程序完成)

这样的数据流就有一个特点 每个小时20分会有一个小高峰,因为通过第二部分的数据是集中式的发送的。

所以我们Flume中ChannelSize的变化大致是这样的:

/\/\____

因为之前用的是MemoryChannel,这个Channel的大小是有上限的,我们之前最大设置为100W,但是在一些用户比较多的服务器上,还是会出现在20-28分这个小高峰,ChannelSize容量满了的情况。
一旦满了,后续的数据Flume就无法接受了,也就会出现数据丢失的情况。
而且最为关键的点是:游戏通过FlumeSDK 发送的实时数据的逻辑因为历史原因有一些坑爹的地方,在尝试发送到Flume的数据如果失败的情况,会不停的重试,且重试的过程中会阻塞游戏业务逻辑。

所以,针对于这种情况,公司同事给出的方案是:

 通过使用MemoryAndFileChannel来弄一个容量无限大的Channel

我能想到的方案还有:

增加Sink的数据,加快下游处理的速度。

MemoryAndFileChannel 的运行原理

MemoryAndFileChannel的底层其实用的依然是MemoryChannel和FileChannel,只是组合起来使用而且,然后在往这个两个Channel中存取的时候加一些判定条件。
我们第一版的MemoryAndFileChannel 的逻辑如下:
1、存数据的逻辑
MemoryChannel的容量为50W ,当这50W容量用完的时候,数据往FileChannel中存,容量为1亿(几乎不可能满)
2、取数据的逻辑
先从MemoryChannel中取数据,如果MemoryChannel 中为数据为0,那么再处理FileChannel中的数据。

自定义Channel存在的问题

运营的小伙伴跟我们反馈的情况是这样的,说有玩家充了一笔钱,买了些东西,但是他们查不到。最后把问题定位到日志,说数据从日志出来的,但是从日志里面查不到。用Flume的小伙伴都清楚,Flume能不宕掉的情况下,是不可能丢失数据的。关键我们也没收到任何告警说,Flume宕了,ChannelSize满了之类的。

然后查Zabbix监控,观察我们的自定义Channel中两个Channel的ChannelSize的变化情况。

内存队列大小依旧一样,是这个样子的:
______/\_/\/\_/\

文件队列大小的变化其实就能说明问题了, 是这个样子的:

FileChannel 大小变化这里写图片描述

也就是在相当长的时间内FileChannel中的大小只涨不减,也就说明,在FileChannel中的数据到最后下降的时候才被发送到下游,也就出现了巨大延迟的情况。

然后找FileChannel出现这个问题的原因,为啥里面的数据就是不被下游处理呢?
这个问题很坑爹,找了很久都没找到,因为下游没有任何问题,上游也没有问题。只能拿本地机器模拟线上环境,然后通过Flume打印日志最终找到了问题,因为MemoryCHannel的曲线中,0和1的很小,然后高峰时刻又是50W,所以没有发现MemoryChannel的大小其实很长一段时间都是1,而不是0。

从我们上面说到MemoryAndFileChannel的运行原理中,可以发现,如果MemoryChannel的大小不为0,那么就一直处理MemoryChannel中的数据,不去处理FileChannel中的数据,直到某个时刻MemoryChannel中的大小为0。

所以结论就是:

因为MemoryChannel的大小一直为1,导致高峰时刻写进到FileChannel中的必须要等到MemoryChannel的大小为0。所以延时的时间取决去MemoryChannel何时为0,根据我们观察,只有到第二天凌晨才有机会为0。

优化方案

因为之前的逻辑的缺陷在于FileChannel中的数据直到MemoryChannel的大小为0时才有机会处理,然而事实却是MemoryChannel会长时间为1,所以导致延迟
所以修改逻辑:
当MemoryChannel中的数据小于等于某个值时,就去处理FileChannel中的数据,而不是必须等到0。
修改完之后:
FileChannel和MemoryChannel的变化图都是这样的:
______/\_________/\_________/\_________/\

数据延迟的问题被解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值