如果体验过不少监控系统的人会发现,大部分apm对消息的处理都是推送,类似prometheus这种的则是拉取(pushgateway虽然是推送,但是从prometheus的角度看还是拉取。都是监控系统,为什么会有两种不同的获取选择呢。
推模式
信息类型
推模式主要是事件信息,一旦触发一个事件,立马收集发送。这样的信息一般不会保存在采集端,因为事件的不可预知性,完全不知道会产生多少数据量,例如http调用链的监控,有一个http的请求就会有一个监控链这样的数据不可预知也无法计算占用大小,基本有消息产生就要发送出去,以免内存占用过大,反而对被监控的进程有影响。
消息可靠性
由于消息是推送,有更多的主动权在推送方。在失败的时候可以尝试重新发送,也可以达到一定次数后加入到发送队列(有内存撑爆的风险),也可以自己持久化到文件等等。
发送方+确认状态的场景下很容易造成重复数据。例如消息发送后,久久没有得到确认的ack,那么会再次发送,如果是网络延迟,或者网络闪断的情况下,会再次发送,结果接收端收到两条相同的数据。这种情况一般是逻辑去重的,一个时间点一个进程只有一个状态,可以利用一些软件的特性达到这个效果,例如opentsdb,他依赖的hbase在文件块拆分合并的过程中会把重复的数据去掉。
拉模式
信息类型
拉取模式主要是采样工作,他更多拉取的是统计值或者采样值,统计值例如java里暴露出来的gc次数和gc时间,是一直累加的。因为拉取模式有拉取间隔,所有并不能准确的获取数值状态的变化,我们只能看到拉取间隔内前后的变化,以此描述中间的变化情况,我们能看到2秒内gc次数从2变成4,说明发生了2次gc,那么是2秒内的什么时刻发生的gc呢,无法知道了。采样值例如cpu使用率,我们可以获取每次间隔间的使用率,但是无法描述中间的过程,例如cpu在1秒的时候cpu使用率上升到了100%,然后第二秒的时候降低到了50%,如果我们的间隔为2的话,可能看到的是cpu的使用率是20%到50%,只看到了上升的值和下降的值,从数据上看,以为是从20%上升到50%。
消息可靠性
经过上面的场景,如果消息是统计值,那么消息的可靠性有保证,哪怕有一次拉取超时了,也不影响,下次拿到的状态依旧是新的,从数值上丢失的部分其实并不怎么影响,后面的状态是前面状态的一个延伸。
如果是采样值。虽然消息丢了一个,但是影响没那么大,毕竟采样,只是一个采样的值丢了。他本身就是反应一个状态的,并不能准确反应一个趋势。我们一般用的就是单点的数据。这里解释一下采样的适用性,采样只是对持续性的问题有用,还是cpu使用率的例子,例如使用率能在2秒内降下来,那也当没问题,但是能每次采样的时候都在涨,那说明还是有一些问题的,正好每次采集到上升数据是个概率。而且是小概率。
他的数据可靠性不保证,但是并不影响我们对数据的分析。
数据处理
在统计值的情况下,数据其实是人不可读取的。例如上面的gc次数,人可能识别的信息是2秒的gc次数,而不是2秒的一个折线图,斜率虽然也能体现增长情况,但是却不直观,所有需要对数据进行加工处理。
真实场景
我们经常看到推送数据的时候也有采样值和统计值。这个居多是架构的一个考量,不能说一个进程一部分数据在推送,一部分数据在拉取,这个很容易混乱。
同时我们也没看到过啦的模式来获取事件的数据,主要是两个方面的考虑,一个是拉取的间隔导致数据量增多,很容易导致内存问题。另外一个原因是事件信息需要可靠性,这就需要采集的时候自身维护好信息的便宜量,到底哪些成功被拉取,哪些失败,这个信息的维护导致了开发难度的直线上升。