Pinterest 是一个帮助用户寻找创意的硅谷初创公司。自2010年上线至今,月活跃用户从零发展到了1.9个亿,云计算平台也扩展到了几万台虚拟机。
就像公司的发展一样,运维这样一个平台所需要的监控系统也是逐步发展和完善起来的——从最初的单机版基于时序序列的监控系统,发展到了到现在的多个监控子系统并可以处理每秒几百万个数据点。本文将描述七年里的监控系统的衍变,并分享一些经验和教训。
Pinterest 公司
Pinterest 公司是2010年成立的硅谷公司,现在已经有7年了,这个公司可以用一句话描述,现在是世界上最大的图片探索引擎,是探索不是搜索,和百度、谷歌是有区别的。用户是在网站上分享他们新的想法和好的东西,其他用户可以来探索这些新的想法,在生活中来实现这些想法。
到目前为止我们有1.9亿个月活用户,用户一共在这个平台上分享了1000亿个各种有趣的想法,所有这1000亿个想法都是以图片形式存在,被用户分享到了20亿个收藏夹中去,平台每月会有20亿个搜索行为产生。
Pinterest 不强调社交,而是鼓励用户根据自己的兴趣去寻找和尝试新东西。增长虽然没有社交网络那么快,但也是在稳步增长的。
后台架构
我们的后台完全运行在亚马逊云三万多台虚拟机上,在上面有少量亚马逊云服务、100多个自开发的微服务和自开发的数据存储平台,有搜索平台、内容平台和广告平台等。
公司里有十几个人左右的专职SRE(Site-reliability Engineer)团队,除此之外还有一部分嵌入式的SRE成员,他们被分配到每一个产品部门中去,在结构上他们和普通的SRE一起,分享同样的技能包。但由于他们同时嵌入到了不同的产品部门,他们的SRE技能包结合对产品的了解有时候可以更有效地解决运维方面的问题。
我们的运维指标总体想达到99.9%,意味着一个月之内最多有43分钟的时间是宕机的。 为了达到这个指标,我们的运维团队和软件开发人员要使用很多工具,我所在的团队目标就是给他们开发这类工具的。
组成与衍变
接下来讲一下我们的监控系统是怎么组成和衍变的。
首先跟大家分享一句从网上看到的很有意思的话:“如果你想成为一个有10倍影响力的工程师,一个捷径就是帮助10个工程师更好的完成他们的工作”。作为工具的开发者,我觉得我们有很大的可能性能成为这样一个有10倍影响力的工程师,因为我们的目标就是让其他工程师用我们的工具更快更好地解决他们的问题。
在我们开发的监控系统里提供了三个具体的工具,做不同的事情处理不同的数据。
- 第一个工具叫做基于时序数据的监控系统和报警系统,它处理的是一些数据指标,根据这些指标用户可以看到整个系统总体的性能,还可以做一些报警。
- 第二个工具叫做日志搜索,相信大家都知道日志搜索的功能。
- 第三个工具是我们从去年开始开发的,叫做分布式跟踪系统。这个跟踪系统可以跟踪进入我们复杂的后台的每一个用户请求:它是怎么调用各个微服务的、各个调用的时间关系和很多很丰富的上下文的信息等,都被记录下来。
简单回顾一下我们怎样开发这个系统,怎么发展到现在这个状态的。公司在2010年开始上线,当时我们没有一个监控工具的开发组,但需要这样一些监控工具,就从SRE团队分出一两个人来做这些工具的开发。
后来公司的用户数得到了很大的增长,从2012年开始我们开始逐渐使用一些以开源系统为基础的工具。首先使用Ganglia,但它仍不能满足我们的增长需求,随后我们引入了Graphite,这个开源工具包可以收集应用程序里的各种指标数据,但Graphite在扩容上有些局限性。
2014年我们引入了openTSDB来收集操作系统和应用程序的指标,当时我们的后台规模已经很大了。2015年我们的队伍得到了扩大,我们发现日志搜索是非常有用的。2016年我们开始开发分布式跟踪系统,它可以处理前面两个系统很难处理但很有意思的一些问题。
开发的工具
基于时序数据的监控和警报
第一个最重要的工具是基于时序数据的监控系统,从下面的架构图来看可能和大家公司里面的监控系统很类似。
我和一些硅谷公司同仁交流后,感觉大家想法差不多,虽然具体用到的模块不太一样,但总体的思想都类似,都是从各个虚拟机、各个应用程序里得到一些数据,然后传到中间一个pub/sub系统里 (我们用kafka的pub/sub系统),后台从pub/sub里读入数据, 进行分类、整合或者调整采样率,最后将数据存到硬盘上的数据库里。
到目前为止我们这个系统每秒能处理250个数据点,每秒大概有3.5万个数据查询,90%的查询来自于报警系统。
应用场景一:数据搜索和可视化
数据查询,用户就是我们的工程师,用户可以从我们数据查询的工具里可视化一些他们关心的指标,可以看到数据指标是怎么变化的。
下图反映的是我们开发的一个前台工具,用户可以利用它来定义他们的数据表达式、定义他们想看什么样的指标数据,把名字放进去就可以看到某一段时间之内这个数据是怎么变化的等等。
应用场景二:仪表盘
第二个应用场合是做一些用户定制的仪表板,仪表板就是一堆图表,这些图表可能是他们感兴趣的某些指标,然后放在一起,这样他们一下子看到所有相关联的数据。
应用场景三:警报
第三个使用的场合是报警系统,报警系统非常重要。比如有一个报警的表达式被触发了但没有及时送出去,可能会导致很严重的问题。
一个比较棘手的问题是选择警报触发的阈值 。我们的报警系统可以帮助解决这个痛点。如选定某一个报警阈值,这个工具可以让用户把过去旧的数据按这个阈值重放一次,我们可以看到在过去一段时间之内什么时候会触发,通过这个可以选择比较合适的阈值。我们也可以定义很多不同的条件来定义一个复杂的警报,也可以和JIRA事件管理系统联合起来做很多事情。
痛点、挑战和对策
在这个基于时序数据的系统里我们遇到的最大挑战有三个:
- 第一,系统要处理的数据量非常大,大概每天产生100TB的数据,对后台成本压力非常大。我们做了几件事情来处理这些挑战,首先将这些数据从kafka读出来之后迅速做降维处理然后调整分辨率;第二点,将冷数据挪到成本比较低的存储设备上。
- 第二个挑战来自于可靠性。我们的监控系统可靠性本质上应该比整个网站可靠性高一些,为达到这个目标做了很多冗余的设计,如采用主动和被动式监控相结合的方式。我们有两个不同的监控系统它们互相监控对方的状态,如果一个监控系统宕掉,另外的监控系统可以探测到这个情况。同时我们还结合了一个主动和被动的监控,所谓的主动就是随时不断地去探测目标是不是还存活,比如每分钟送一个探测的数据包看有没有返回信息。
- 第三个挑战是属于查询速度。现在的平均图表打开时间大概是0.5到5秒。
为了加快这个速度,我们做了几件事情。首先是把数据分片,有两种分片的准则:
一、按数据类型分片,比如说来自JAVA或者Python的数据, 会被发到不同集群去;
二、按时间分片,1小时内的数据是最热门的数据,因为大家访问率最高最有价值,我们就将它们放在单独的基于SSD的集群里并且作一个拷贝;超过一周的数据用户可能很少去访问,我们就放到另外一个基于普通硬盘的集群里。
其次我们现在也在开发新的技术做一个全内存的时序数据库,就是把所有这些最新的,如24小时内的时序数据全部放在一个集群机器的内存里,这样每次查询数据不需要经过硬盘,速度可以得到几十倍的提高。
日志搜索
日志搜索工具
我们提供的第二个工具是日志搜索,日志搜索的架构与前面的大同小异:从各个机器上的进程、日志文本里得到最新的日志,通过中间的pub/sub送到后台,后台做索引,有一些UI的工具方便用户查询。
后台我们用的是两个系统, Sumologic 和 ElasticSearch。我们每天处理500到800G字节的日志。在这个查询系统里用户可以定义一些警报系统,如果返回来一些结果满足某一种模式就可以触发一个警报。
我们过去的经验表明在日志设计里最有意思的一点就是怎么样让原始的日志记录对运维更有价值—当运维人员或者开发者拿到这个日志的时候,他可以根据这个日志迅速找到问题的根源。
日志的标准化
我们对公司使用的每一个编程语言都开发了一个标准的API模块,用户所有的日志都是通过这个API模块产生的。
API模块里定义了一些很有价值的上下文信息,比如是哪一个文件、哪一行代码产生的这个日志记录,它对应的进程号还有对应的用户请求,以及用户请求的ID。所有这些信息在API模块里被自动的记录下来,这样程序开发者不需要再去费脑筋想这些事情。
API模块直接把这些日志输出去,并且把输出的格式统一为JSON格式,使得后台的处理和查询非常方便。
分布式跟踪系统
微服务的体系结构
第三个工具的背景源于我们基于微服务的体系结构,我们有一百多个微服务,它们相互之间被调用,对用户的请求做出响应。当有很多这样的微服务时,运维人员很难理清它们之间的调用关系从而理解问题的根源,因为不可能读所有的源代码后画一个图。而且调用关系是随时变化的,每天新代码的发布可能就会导致关系的改变,所以我们需要有一种工具能够自动地记录这种调用关系 。
服务间的调用关系
比如有一个客户端,它先调用了一个微服务,第一个微服务又调用了第二个服务,三个模块之间它们有一些用户的请求。它们的这些流动,可以看到数据是从客户端先到第一个服务,第二个服务又调一个请求给第二个服务,第二个服务返回一个信息,第一个服务接到之后然后返回到客户端。
通过这个工具我们可以根据跟踪用户的请求是怎么在这两个服务之间被调用的就可以得到类似下图的数据结构,这是一个瀑布式的数据结构,可以看到各个服务是怎么一层层调用的、每一层调用的时间关系和对应的上下文的关系,一些信息都可以被记录下来,这就是分布式跟踪系统得到的结果。
分布式跟踪系统
设计这样的系统需要有一个库来自动把这些调用关系记录成某种数据结构,同时在后台对这些数据做统一处理。
在我们的系统里Python、JAVA都有分别对应的库,来把这些事件的调用记录下来并存到当地的硬盘上。这些调用数据通过pub/sub最后被写到ElasticSearch数据库里。这种数据的应用场合有很多,可能还有一些新的应用还没有挖掘出来,我们正和很多其他组合作来找到更多的应用。一个最直接的应用是帮助理解服务之间被调用的关系,从而帮助工程师理解我们的后台是怎么设计的。
第二点,我们的跟踪系统所用到的数据结构已经成为所有跟性能v(performance)有关的数据的标准,这些跟性能有关的数据可以来自于移动终端,可以来自于一个浏览器端,也可以来自于后台服务器微服务的数据。只要遵循这个标准,我们可以统一的处理它们,将它们串起来。
第三个应用场合,可以通过层层调用的关系,发现最影响用户请求性能的服务即瓶颈服务,得到这个瓶颈服务的信息后通过提高它的性能可以提高整个用户请求的性能。曾经有个工程师通过这个跟踪系统的数据,发现他写的一个服务里,多次不必要地调用了另外一个服务,他纠正了这个错误从而提高了性能。我们也可以用这个跟踪系统服务来计算每个服务消耗的时间。当一个机器上运行多个服务时,结合跟踪系统的数据和系统指标数据, 可以算出每个服务消耗的CPU时间的百分比。
一站式仪表板
我们正在做一个仪表板,利用这个信息,我们想将这个仪表板推广成公司一站式的仪表板,说它是一站式,因为它把跟踪系统结果和前面的指标数据可以结合起来,可以看到整个公司从前台的Web服务器到后面的各个服务之间是怎么流通的、流量是多少、每个服务的成功率是多少等。
如果某个服务的成功率低于99.9%就把它显示成红色,这样运维人员马上就知道它是有问题的,我们准备把它推广为一站式的解决方案,每次出问题时运维人员可以通过它迅速了解全局的情况和问题根源。
经验与展望
上面介绍了三个不同的监控模块,下面总结下过去的一些经验、面临的挑战和对未来的展望。
面临的挑战和对策
工程师对数据的读写规律难以预测
第一个挑战是来自于工具的使用者,就是运维和软件开发人员,他们对工具的使用是很难预测的,可能有100、200个人在使用我们的工具,遇到故障时他们每个人都会疯狂地查询数据,这就会导致我们后面的资源不够用了。
这些不可预测的使用情况使得监控系统本身的容量设计非常困难,如果仅仅为了满足一个月发生一次的故障排查而弄一千台机器是一种浪费行为。
我们的对策是尽量让系统能够很快的扩缩,另外在权衡可靠性、可用性和成本时候我们更偏向于可靠性,尽量用更冗余的容量来换取更高的可靠性。
90%的数据从未被读取
第二个挑战,90%的数据从来没有被读取过,这个数字可能是不准确的,但实际上确实是这样,大量的数据是没有必要被产生的,而且也没有人会用到它们。
根源在于工程师在写代码产生这些数据的时候,他们可能采用了很大一个采用率,但这是没有必要的而且还是非关键的系统,没必要去做测量,很多代码过段时间就没有用处了但工程师一般不会去删除它们。
对这个挑战我们只能通过教育不断跟他们讲:他们给我们送了多少数据、在这个月里面被使用多少次,并给他们一个成本上的估值让他们回去检查代码,尽量让工程师解决这些问题。
工具新性能的推广困难
第三个挑战是来自于新性能的推广,就算在同一个楼里也很难说服其他工程师,而且有时候工程师与工程师之间也不是很想相互去问。
我们的对策是尽量用那些比较专业化的用户界面的解决方案,借用这些比较直观性的用户界面,来帮助工程师更轻松使用我们的工具。比如指标的数据我们用一个专门提供图表公司的产品,他们画的图比我们自己画的前端图漂亮。下面是我们组自己设计的基于ElasticSearch的图表。
三个不同的工具
时序指标数据
前面讲了三个不同的工具,第一个是时序指标数据,第二是日志,第三是分布式跟踪系统,这三个工具其实是反映了同一个系统的不同的方面。比如时序指标数据,一般是用计数器、延迟、测量值等。
它的好处是可以看到一个总的指标并且成本很低,传输这样一个数据不需要消耗太多的CPU和带宽。但它缺乏服务与服务之间关系的描述,而且很难从里面了解到如果有单个失败的请求是怎么导致的。
日志
日志里面的数据顾名思义就是程序产生的一些错误和一些用户关注的事情的描述,它能描述单个事件,有很丰富的上下文,但是缺乏总体的描述,不能够很便宜很廉价的把所有的事件描述都索引。
分布式跟踪系统
第三个是分布式跟踪系统,好处在于可以从刚开始用户请求进入系统,一直到用户得到反馈,整个系统调用的关系,可以得到这样一个很准确的时间的关系,还有中间调用时上文的关系。但是对用户请求性能有影响,最多只能做0.1%的采样。
监控系统下一步
集成化
我们下一步正在做的事就是想把这三种不同的数据结构和数据放在一起,我们给用户提供一个集成化的功能更强大的监控工具,我们要把相关的信息,只要他们是描述同一个事件、同一个服务、同一个容器、同一个虚拟机的都放在一起,每次用户就是我们的运维人员,排错的话他们可以从同一个地方看到数据。
第一个例子,在一个前端的工具上我们可以把来自于同一个服务的时序指标和关联的日志并排放在一起,当服务出现很低的可利用率,日志的图片就在右边,运维人员可以迅速从右边看到那些错误产生的原因,他们就不用在日志系统和时序数据的系统里相互切换了。
第二个例子,用户的请求有一个独特的ID,我们可以用这个独一性的ID把这个日志和跟踪数据结合起来。如果一个用户请求的响应时间很慢,根据这个ID可以到日志的数据库里面找到对应的日志,日志里面有很多上下文信息,就可以确定问题的根源。根据和专门提供监控系统开发商的沟通中了解,所有的这些开发者都在不断提供一个集成式的监控系统。
智能化
我们下一步也想做一些智能化监控工具的开发,在过去短短几个月之内我们组就收到了好几个初创公司的合作请求,他们在做一些在我看来算比较智能化的监控工具的开发,相信很多公司可能都在做同样的事情,这是一个大势所趋。
我们可以智能化的来关联我们收到的数据,以快速发现问题的根源,我们的报警系统也可以得益于智能化,比如同一个问题可以导致几百个警报全部送出来,形成警报风暴,但如果智能化处理这些警报,可能发现没有必要送100个而是送1个就可以了,这样可以避免运维人员的疲劳。
另外警报一旦被触发,到底送给谁,谁可以来解决这个警报所指向的问题,也需要一个智能化的推断,然后根据过去的经验、技能包,推送到合适的组里去。
原文发布时间为:2018-01-23
本文作者:孟晓桥