微服务架构是目前各大互联网公司普遍采用的软件架构方式。在微服务架构中,系统被拆分为多个小的、相互独立的服务,这些服务运行在自己的进程中,可以独立的开发和部署。在业务快速变化时,微服务单一职责、自治的特点,使系统的边界更加清晰,提升了系统的可维护性;同时,简化了系统部署的复杂度,可以针对某个微服务单独升级和发布;在业务增长时,也可以方便的进行独立扩展。
微服务架构虽然带来了很多好处,但也带来了新的问题。在以往的单体应用中,排查问题往往通过查看日志定位错误信息和异常堆栈;但是在微服务架构中服务繁多,出现问题时的问题定位变得非常困难。另外,微服务往往通过组合已有的服务来创建新服务,一个服务的故障很可能会产生雪崩效应,导致整个系统的不可用。因此,如何监控微服务的运行状况、当出现异常时能快速给出报警,这给开发人员带来很大挑战。
本文将介绍我们基于Prometheus搭建微服务监控系统的一些实践经验,及爱奇艺号在微服务监控方面的一些探索和实践,从爱奇艺号的业务特点出发,结合现有的开发运维技术栈确定监控的对象和指标,并有针对性地自研了一些关键组件和服务,实现服务的全面监控和统一报警。
在微服务架构中,不同维度有不同的监控方式。
在上述4中监控方式中,健康检查是云平台等基础设施提供的能力,日志则一般有单独的日志中心进行日志的采集、存储、计算和查询,调用链监控一般也有独立的解决方案进行服务调用的埋点、采集、计算和查询,本文主要讨论第4种监控方式。
由于微服务架构自身的特点,使得传统的一些监控方案不再适用。在传统应用监控中,Zabbix是最常用的监控方案。Zabbix的优点在于成熟可靠、强大的社区支持、多年积累的经验和方案。但Zabbix的缺点也很明显,首先是使用难度高、学习曲线陡峭;其次,Zabbix的监控维度是主机,无法适用于微服务的云原生环境。
经过调研,我们最终采用了Prometheus。选择Prometheus的主要原因:
由于采集的数据有可能丢失,Prometheus并不适合对采集数据要求100%准确的场景。实际上,对于监控系统的场景,偶尔的数据丢失完全可以接受。
爱奇艺号是爱奇艺专注视频内容的创作、分发和变现的平台,承载了自媒体、网大、网剧、儿童、动漫、知识、网络综艺、纪录片、文学、轻小说、漫画等内容,是爱奇艺内容生态的重要一环。
爱奇艺号整体采用微服务架构,内部依据功能、领域等角度划分为不同的微服务,外部流量先经DNS、QLB、前置机、网关等层完成统一鉴权、负载均衡、限流等操作后路由到系统内部不同的微服务实例。系统内部微服务除专有的MySQL、Redis、MQ等资源外,共享服务注册/发现、配置中心等服务治理能力。
系统整体架构,如下图所示:
爱奇艺号服务于内容创作者,服务质量直接决定了创作者的使用体验,影响内容创作的热情,进而影响内容生态的健康,因此对服务质量有很高要求。同时,爱奇艺号作为前台业务,依赖公司许多的内部服务和中台服务,服务的稳定性直接影响了自身服务的质量。
基于爱奇艺号的业务特点,在搭建微服务监控系统时,重点关注自身服务接口和第三方服务接口的监控。
我们基于Prometheus搭建了适合自身业务特点的微服务监控系统。Prometheus已提供非常丰富的组件,同时我们也开发了部分组件,满足我们的监控需求。
微服务监控系统的整体结构,如下图所示:
监控系统一般采用分层的方式划分监控对象。在我们的监控系统中,主要关注以下几种类型的监控对象:
对于应用服务和第三方接口监控,我们常用的指标包括:响应时间、请求量QPS、成功率。
容器环境监控
微服务应用部署在爱奇艺内部的应用云平台(QAE)上。在云平台中,一台主机上会同时存在多个容器实例,采用主机监控的方式采集到的资源使用和性能特征实际上是主机的指标数据,而非运行的容器。Prometheus虽然支持使用cAdvisor进行容器监控,但cAdvisor需要安装在主机上,而QAE是一个公共平台,自行安装部署其他软件并不现实。好在QAE提供了开放的API,很好的解决了这一问题。
QAE平台自身内建了监控功能,包括容器级和应用级两个层级,除了可以在QAE平台通过页面查看,也支持通过HTTP接口暴露出监控数据,这就为我们进行统一的监控数据采集提供了可能。
我们开发了一个QAE容器监控数据采集的服务,qae-monitor。qae-monitor服务通过自定义Prometheus Collector的方式,实现对QAE监控数据的收集。服务定时调用QAE平台的HTTP接口抓取容器监控数据,并整理成Prometheus的数据格式。
qae-monitor本身也通过Micrometer向外暴露监控数据采集端点,Prometheus通过该端点抓取采集到的监控数据。
应用服务监控
基础监控数据主要是指应用服务实例的运行时状态、资源使用情况等度量指标。Micrometer默认提供了非常丰富的应用度量指标,只要接入了Micrometer就可以直接采集到这些数据,主要包括:
第三方接口监控
微服务架构中,可以通过调用和组合已有服务的方式创建新服务,第三方接口会直接影响到自身服务,因此第三方服务接口的调用情况同样值得关注。在如何采集第三方服务接口的监控数据上,主要有两种方案:
我们最终选择了第二种方案,主要原因是:首先我们的技术方案比较统一,都采用HTTP协议进行服务调用,且使用的HTTP客户端组件(fluent-hc)也是基于Okhttp3进行的二次封装,方便统一修改。其次,Micrometer支持通过SDK的方式自定义监控指标数据的采集,也提供了众多常用的组件埋点方案,Okhttp3即是其中之一,进一步简化了第三方接口的监控数据采集难度。
具体而言,Micrometer提供了OkHttpMetricsEventListener组件,用于收集Okhttp的监控数据。我们只需要在构建Okhttp实例的时候传入OkHttpMetricsEventListener实例即可;也可以传入一个EventListener.Factory实例,在工厂的创建方法中返回OkHttpMetricsEventListener实例。Okhttp在3.11.0的版本中才正式加入了EventListener功能,使用时需要注意Okhttp的版本。
通过第三方接口监控的维度,我们可以方便地将自身服务与所使用到的第三方服务关联起来,以统一的视图展示服务用到了哪些第三方服务接口、这些第三方服务接口的响应时间和成功率是多少。当服务出现异常时,对于定位问题有很大帮助;同时,一些内部的服务可能监控报警并不全面,第三方监控也能帮助他们提升服务质量。
Prometheus采用的Pull模型需要知道哪些是被监控的目标对象。在Prometheus中配置监控目标分为静态和动态两种,常用的包括静态文件配置、文件服务发现、Consul服务发现等。此外,Prometheus还支持DNS、微软Azure、亚马逊EC2、谷歌GCE、Kubernetes等多种服务发现方式。
静态配置的方式最为简单,但在实际生产环境中并不可取。容器每时每刻都可能进行着创建和销毁,不可能通过静态配置方式设置监控目标。我们最开始选择了Consul的服务发现,它引入了集中的注册中心,微服务启动时向注册中心注册服务实例,Prometheus便可以从注册中心查询到服务实例作为监控目标。不过,我们最终并没有采用Consul,主要原因有两点,一是微服务接入Consul需要涉及代码改动,虽然改动不大,但大量服务的接入仍有不小的成本;二是还需要再单独部署和维护一套Consul环境,带来新的维护成本。
Prometheus服务发现的原理很简单,通过第三方提供的接口,Prometheus查询到需要监控的目标列表,然后轮训监控目标获取监控数据。由于QAE是私有云平台,Prometheus无法直接提供支持,但基于以上原理,我们可以实现类似的服务发现机制。
我们开发了基于文件的服务发现prom-sd-qae。prom-sd-qae是一个独立程序,部署在Prometheus服务所在的机器。它定时通过QAE平台的HTTP接口抓取容器服务列表,按Prometheus要求的格式在本地磁盘生成JSON或YAML文件,其中定义了所有的监控目标列表。Prometheus定时从文件中读取最新的监控目标,并从中拉取监控数据。
这一方案在两次刷新监控目标之间,可能会发生监控目标的销毁和创建,此时存在短暂的过期监控目标;不过,该方案兼顾了服务发现的动态性与简便性,依然不失为一种简单有效的选择。
Prometheus允许基于PromQL定义报警的触发条件,Prometheus周期性的对PromQL进行计算,当满足条件时就会向Alertmanager发送报警信息。
在配置报警规则时,我们将每个服务的报警规则定义在一个group下,每个group定义了多条报警规则,包括:响应时间报警、接口成功率报警、QPS报警、第三方接口报警等。这样的好处是以服务为维度将报警规则聚合在一起,查看和配置时更方便;另外,同一个报警规则下不同服务的报警阈值可能不同,这样也可以独立配置。下图是一个报警规则示例:
Alertmanager在接收到报警后,可以对报警进行分组、抑制、静默等额外处理,然后路由到不同的接收器。Alertmanager支持多种报警通知方式,除常用的邮件通知外,还支持钉钉、企业微信等方式,也支持通过webhook自定义通知方式。
爱奇艺的统一报警平台实现了报警话题、报警内容、报警渠道、报警订阅的统一处理,我们充分利用了统一报警平台,开发了Alert-proxy报警代理服务。Alertmanager通过webhook方式将报警发送到Alert-proxy,Alert-proxy再投递到统一报警平台,最终发送到最终热聊、邮件、短信等接收端。Alert-proxy会将报警投递到统一报警平台一个默认的报警话题Topic,也支持投递到其他的Topic上。可以为不同服务、不同报警级别单独设置Topic,实现更精确的通知触达和聚焦。
报警涵盖了服务HTTP接口、第三方HTTP接口,也包括了JVM和容器的状态,目前已基本满足需求。
监控是一个老生常谈但又常谈常新的话题,与业务特点、技术栈、方案选型有很大关联,看待问题的角度不同最终的方案也不尽相同,到底什么样的方式是最合适的,这都是仁者见仁、智者见智,只有适合自己的才是最好的。
本文是现阶段微服务监控的一些实践总结,随着业务和技术的不断发展,未来还有许多方面需要不断地探索和改进,例如报警规则优化、自动化报表、系统智能化监控等,使监控更加全面、强大和智能,进一步提升服务质量和稳定性,助力业务快速发展。
原文链接: https://mp.weixin.qq.com/s/u9DGTaHPORuUO5AaN5UgLw