监控系统构建实践之传输篇
在上一篇文章采集篇的事情做完后,源数据就已经有了,但应该如何上报到存储就是接下来要考虑到的事情。
本文结合我司在传输链路的建设,简述一下期间的一点思考。
先来说传输链路的实现方式,业界关于传输的实现主要有2种:
- 推模型
- 拉模型
推模型
推模型典型的系统代表就是open-falcon
,即agent通过rpc将采集到的数据推给上游。
拉模型
拉模型是prometheus
带起的节奏, 即每个target提供一个/metrics
的接口,由中心主动并定期的去scrape
。
关于两个模型的对比, 网上有很多争论。但实际上在不同的场景下,使用的模型是不同的,没有银弹。
也如 这个slide 所述,“no winner”
而在我司的实现方式,在传输模块和采集之间,有一层queue,用于解耦。
目前这个queue的选型是 nsq。之所以使用nsq而不是其他的消息队列, 因为建立传输链路时本人还未加入,所以以下均属个人猜测:
- nsq轻小易维护。最小部署只需
nsqd
、nsqlookup
2个二进制文件就可以快速部署。 - 当年有同事做相关分享时,有人问为什么不用kafka。
其实关于这类问题,还是那个答案,没有银弹,够用即可。
永远没有依靠一种技术就吃遍天下的。
传输的功能
传输最主要的功能,当然就是把采集端的数据打入存储。
除此之外,我司的传输链路还加入了以下的功能:
- filter: 过滤特征比较明显的垃圾指标
- quota: 限制增长量急、速度快的上报
另外,传输还有2点功能需要描述一下:
-
传输应提供基于queue的订阅功能,即除了api等方式提供数据查询的功能之外,也提供流式的数据接口(当然前提是在根源做好垃圾指标的防范工作)。
但我司目前是没有提供这样的功能的。原因?因为这样势必会带来queue的运维成本。而且现在的相关需求不强烈,以后相关需求较多时,再行考虑。 -
这里存在一个涉及采集、传输、存储、查询的数据流转问题,我们知道凡是时序数据都可以抽象为KV对的组合,例如
name=cpu.idle.core core=1 instance=job1 timestamp=1500000000 value=1.234
这样的一个point,其中name=cpu.idle.core core=1 instance=job1
这部分可以称为meta data
, 这个信息会被整个系统系统使用。
而我们的存储又是使用的open-falcon
的query/transfer+graph
的老几套。由于种种原因,在系统内部充斥着KV map和uuid(排序过的KVs 生成的字符串)的相互转换代码。如此造成了极大的性能损耗。
一个解决办法是,在采集端,就计算好每个指标的uuid, 及对应的meta数据。这样任意环节均可取用,而即使整个链路中都携带meta数据和uuid。也好过大几百甚至上千ns/op
的计算开销和相同量级的B/op
内存开销。
这部分内容也会在存储篇再次谈及。
传输部分就说到这里,下一篇会说说存储。
-EOF-