微服务架构下的立体监控系统设计和实现

背景

GOPS全球运维大会(北京站)听到了不少干货。特别受益的是来自腾讯SNG事业部聂鑫分享的
《从0到1到N,腾讯监控体系全透视》

在他的主题分享中,他将腾讯这些年的监控系统的发展历程概括为点监控-->面监控-->深度监控

看到他这页幻灯片的时候,有一种醍醐灌顶的感觉。因为在听他分享的时候,我们的系统才刚刚完成架构微服务化没多久,我们上线了调用链:分布式追踪系统来解决在微服务分布式系统中排查跟踪特定问题,但我们的监控系统还没有针对架构微服务化后进行相应的进化。比如,大部分监控系统停留在点监控的层面,少数进行关联多个服务的面监控也做得比较初级,需要人工分析和干预。

点监控比较好理解,就是对系统布置监控点,根据阈值触发告警。

面监控则是对告警信息进行时间和空间关联,有效消除毛刺告警,使告警更加准确。因为告警本身有时效性,时效性源于告警延时,连续性可能是干扰,因此只进行时间关联是不够的。链路相关性(空间相关性)和时间相关性一起决定准确性。

深度监控其实有点追深度学习的热点,从分享看,实际就是对面监控的链路相关性进一步完善,以及根据收集到的系统进行使用机器学习进行简单的分类。

参加会议回来以后,我们明确了自己监控系统的进化方向,根据自身系统的特点进行了一些取舍,确定了立体监控的方案。

立体监控方案目标

所谓「立体监控」即指在我们当前系统点监控为主的情况下,尽可能复用当前监控的探针,进行时间和空间(服务链路之间)维度上的扩展,实现对整个系统时空上的监控。

立体监控需要消除点监控带来的监控毛刺,如服务存在依赖情况下,级联告警通过立体监控分析融合后,应该只对最后一级进行告警。

立体监控可以快速的定位系统故障,定位粒度根据不同监控类型可以做到微服务级别、接口级别、数据库实例级别、缓存实例级别等。

立体监控方案设计和实现

对于微服务,我们通过data bus将需要进行监控的信息发送到kafka进行收集。这种方式在调用链分布式追踪系统也有使用。不得不说,data bus是架构微服务化后非常重要和实用的基础组件。

为了尽可能降低各个微服务集成监控组件的侵入性,我们通过修改基础库的方式进行集成。比如,微服务使用了MySQL数据库,那么我们就修改微服务使用的数据库驱动来对数据库进行监控,一旦发生错误或warning信息,将消息写入data bus;某个微服务需要调用腾讯的某个接口,我们就对修改我们的http客户端基础库,将错误和超时消息写入data bus实现对该接口的监控。

因此,我们的微服务监控集成几乎不需要研发人员的介入,只需要运维人员更新服务依赖库,然后重新发布上线即可。事实上,我们在微服务监控集成上就没有安排独立的发布上线时间,都是在研发上线feature或hotfix时搭车上线的,将近两百个微服务在2周内完成集成。需要注意的是,基础库的修改一定是由团队中相对资深的开发人员来做,并且测试一定要做到位,否则会引起大规模的问题。

对于k8s集群、数据库、redis等基础设施的监控沿用以前的点监控数据,只是将事件统一上报到了Event Collector事件收集服务。Event Collector除了收集事件数据,也对一些不符合通用规则的数据进行过滤。

Event Analyzer事件分析服务根据Event Collector收集到的事件,进行时间和空间上的分析监控结果,并发送告警通知。

在事件分析上,时间维度非常简单,选取一个时间窗口内的事件信息即可(我们当前根据经验设定的是1min)。空间维度方面,则相对麻烦一下。我们没有采用腾讯使用的全链路分析算法。主要是因为该算法需要预生成链路拓扑图。而微服务架构中,各个微服务的增加、减少和变更是非常频繁的,预生成拓扑图有点反模式,也会产生一定的成本。我推测腾讯之所以觉得预生成拓扑图不是问题,跟它当前架构没有完全微服务化以及内部严格的管理流程有关。

因为不想预生成链路拓扑图,分享中给出的链路面积计算公式也就无法使用。另一方面,因为腾讯给出的全链路分析算法其实没有完备的理论证明,在我们数据量没有腾讯庞大的情况下,我们是否能用该算法取得同样效果是缺乏信心的。

但是,思想是可以借鉴的。通过讨论,我们一致认为所谓的链路分析其实就是关联性分析,而关联性分析那就毫不犹豫的使用Google Page Rank算法:

如上图所示,我们将服务(1, 2, 3, 4)之间的告警事件作为一个超级链接指向,然后计算PR值,那么,PR值最大的是我们认为出现问题可能性最大的服务。理论证明这里略过,这个锅我们扔给Google背即可。

需要说明的是,任何一个复杂的系统在出现故障时,往往不是一个组件或服务出现问题,很可能是多个服务同时出现问题。那么在计算PR时,可能就是面对多个独立的PR有向图。这个时候独立图之间的关系处理就可以根据历史数据进行机器学习,以进一步给出故障原因,然后根据预案快速处理故障,恢复服务。

Event Analyzer也提供了一个页面,可以查看历史的告警信息链路:

也可以对链路流量(边越粗流量越大)进行监控和分析:

总结

立体监控上线后,运维方面以前只能从点入手排查问题转变为直接根据Event Analyzer的聚合告警信息联系对应服务的开发者解决问题。同时,发现了很多以前被经验标记为系统抖动没有重视的潜在问题。至此,我们的微服务架构在调用链和立体监控的双重加持下,又完成了一次进化。

Ubuntu 14.04开启nginx http2支持的方法

再过不到两个月,Ubuntu18.04就要出来了,但是手上还有一些老机器还停留在14.04?:

没有足够的时间和动力来升级这几台老机器,但是一些常用的软件准备顺手升级一下。最基本的自然是升级nginx支持http2. http2的优势可以参见《当我们在谈论HTTP队头阻塞时,我们在谈论什么?》以及《低延迟与用户体验杂谈》

Ubuntu 14.04开启nginx http2支持的前置条件

  1. nginx >=1.9.5
  2. openSSL >= 1.0.2

第一个条件大家一般都不会漏掉。但是第二个条件一般是http2无法成功开启时才发现。这是因为随14.04一起分发的openSSL版本是1.0.1f. 那么要开启http2支持,有两种方式:

  1. 使用他人编译好的ngingx with http2 support package安装;
  2. 升级本地openSSL版本,然后从源码编译安装。

而随Ubuntu 18.04一起分发的openSSL版本为1.1.0g, 因此不存在这个问题。

使用packaege安装(懒人专用)

这里需要注意一下,很多为提供14.04提供nginx安装包的源虽然可以让你安装更高版本的nginx,但是大多是使用openSSL 1.0.1编译的,因此无法支持http2, 比如jessis, nginx mainline为14.04提供的安装包是使用1.0.1编译的,因此不支持http2的。这里我们使用ondrej提供的源。

  • 卸载已经安装的nginx(会保留配置文件,take is easy):

  • 添加ondrej nginx安装源:

如果出现如下错误:

应该是终端编码问题,尝试使用LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/nginx解决。

  • 更新源,并安装:

从源码安装

修改nginx配置开启http2

设置nginx支持http2最关键是在https端口添加http2指令:

一个网站的参考配置模板如下:

小结

nginx开启http2的支持不要忘记了对openSSL最低版本的要求。其实http2已经不再时髦啦,http2+TLS1.3才是未来,可以参见《低延迟与用户体验杂谈》。后面会讲讲docker+nginx开启http2和TLS1.3的方式,这种方式即可以方便的尝试各个nginx版本,同时也不会破坏本地的nginx环境。

macOS无法打开app应用程序的解决办法

macOS Sierra以后(EI Capitan, High Sierra),默认只允许打开来自Mac App Store或苹果的有效开发者发布的应用。你可以在「System Preferences -> Security & Privacy」查看当前状态:

如果是从网络下载安装的app,在打开时可能会遇到这两个问题:

  • YOUR_APP is from an unidentified developer, Are you sure you want to open is?
  • YOUR_APP is damaged and can’t be opened. You should move it to the Trash.

可以尝试在终端中执行sudo spctl --master-disable(需要输入密码)以允许打开任意来源的app:

如果执行成功,「Anywhere」选项为选中状态。「Security & Privacy」状态如下:

如果需要关闭「Anywhere」选项,则在终端执行sudo spctl --master-disable.

注:打开该「Anywhere」选项有安全风险,请确保你在打开该选项是了解app的来源,只信任自己清楚来源的app.