在上一篇文章采集篇的事情做完后,源数据就已经有了,但应该如何上报到存储就是接下来要考虑到的事情。
本文结合我司在传输链路的建设,简述一下期间的一点思考。

先来说传输链路的实现方式,业界关于传输的实现主要有2种:

  1. 推模型
  2. 拉模型

推模型

推模型典型的系统代表就是open-falcon,即agent通过rpc将采集到的数据推给上游。

拉模型

拉模型是prometheus带起的节奏, 即每个target提供一个/metrics的接口,由中心主动并定期的去scrape

关于两个模型的对比, 网上有很多争论。但实际上在不同的场景下,使用的模型是不同的,没有银弹。

也如 这个slide 所述,“no winner”

而在我司的实现方式,在传输模块和采集之间,有一层queue,用于解耦。
目前这个queue的选型是 nsq。之所以使用nsq而不是其他的消息队列, 因为建立传输链路时本人还未加入,所以以下均属个人猜测:

  1. nsq轻小易维护。最小部署只需nsqdnsqlookup 2个二进制文件就可以快速部署。
  2. 当年有同事做相关分享时,有人问为什么不用kafka。
    其实关于这类问题,还是那个答案,没有银弹,够用即可。
    永远没有依靠一种技术就吃遍天下的。

传输的功能

传输最主要的功能,当然就是把采集端的数据打入存储。

除此之外,我司的传输链路还加入了以下的功能:

  1. filter: 过滤特征比较明显的垃圾指标
  2. quota: 限制增长量急、速度快的上报

另外,传输还有2点功能需要描述一下:

  1. 传输应提供基于queue的订阅功能,即除了api等方式提供数据查询的功能之外,也提供流式的数据接口(当然前提是在根源做好垃圾指标的防范工作)。
    但我司目前是没有提供这样的功能的。原因?因为这样势必会带来queue的运维成本。而且现在的相关需求不强烈,以后相关需求较多时,再行考虑。

  2. 这里存在一个涉及采集、传输、存储、查询的数据流转问题,我们知道凡是时序数据都可以抽象为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-falconquery/transfer+graph的老几套。由于种种原因,在系统内部充斥着KV map和uuid(排序过的KVs 生成的字符串)的相互转换代码。如此造成了极大的性能损耗。
    一个解决办法是,在采集端,就计算好每个指标的uuid, 及对应的meta数据。这样任意环节均可取用,而即使整个链路中都携带meta数据和uuid。也好过大几百甚至上千ns/op的计算开销和相同量级的B/op内存开销。
    这部分内容也会在存储篇再次谈及。

传输部分就说到这里,下一篇会说说存储。

-EOF-