作者|中国移动云能力中心PaaS产品部陈奕帅近年来,“云原生”频频出现在人们的视野中。随着云原生成为下一代云计算的技术“核心”,业界正在从关注“云原生概念”转向关注“云原生落地实践”。云原生技术的发展势头不可阻挡,未来仍将是云计算领域的热门话题。我们知道,现代“云原生”是一套符合云计算发展趋势的应用设计理念方法论。其关键技术包括微服务架构、容器、容器化编排、服务网格等技术。那么当我们把大系统拆解成一个个模块独立部署,以容器化的形式部署时,得益于这个团队,我们可以更快、更持续、更快速地开发和交付系统。但是任何事情都有两个方面。我们在从解决方案或技术“好的”一面“获利”的同时,也要避免解决“坏”的一面所带来的风险和后果。其中比较大的是微服务后系统复杂度的指数级增长,给运维和故障排查带来了巨大的挑战。01微服务架构演进史在真正进入微服务可观察性这个话题之前,我们需要先了解一下微服务架构的演进史。整体来看,整体架构的演进过程大致经历了单体应用架构、垂直应用架构、分布式SOA架构、微服务架构的演进。下面以一个电子商务系统为例(以下图片均来自网络),主要比较各种架构在运维上的差异。示例电子商务系统大致分为三个主要模块:主业务模块(用户管理、商品管理、订单管理)、内容管理模块(CMS管理)、系统管理模块(后台管理)。单体应用架构如图所示,单体应用架构将所有模块揉成一个应用程序,所有模块耦合在一起。系统的健康状态通常是“所见即所得”(整体功能可用表示应用处于健康状态),监控和告警指标通常由JVM的一些参数反馈,应用日志的生成和收集相对统一和集中,排查问题的环节通常比较短(大部分问题可以直接从日志定位到应用中的某一行代码分析原因),维护和监控并不困难。但通常某个子模块出现问题,会导致整个项目不可用,无法横向扩展,过于臃肿,无法适应大型项目和应用。然后逐渐演变为垂直应用架构。与单体应用架构相比,垂直应用架构对整体系统进行了拆分。优点是可以根据实际情况对某个子系统进行横向扩展,避免一个系统出现故障对其他系统的影响。缺点是拆分后系统相对独立,不能相互调用(区别于微服务,只是独立拆分),也导致重复业务的开发,如订单管理、商品管理、用户管理等管理如图中箭头所示,后期维护成本较高。在运维方面,主要难点在于日志的管理和问题发生点的增加。例如,出现问题可能是CMS和后台管理系统共同引起的,需要同时解决两个系统的故障。但是随着业务规模的扩大,会导致重复代码和重复修复工作的激增。我们需要把这部分的逻辑抽离出来,然后慢慢过渡到分布式SOA架构。分布式SOA架构分布式SOA架构也可以认为是微服务架构的雏形,其中表现层对应我们通常所说的消费者或控制器层,负责控制服务层的哪些服务需要被调用对于页面操作(例如:下订单,会用到user、order、product这三个服务,这三个服务是抽象出来的,独立存在于服务层),而服务层是对页面的具体业务逻辑实现表示层调用。上图中的服务层模块应该包括用户管理、产品管理、订单管理、CMS管理、后台管理等模块,基于SOA的分发通常包括注册中心(例如:图中的ESB总线或像DUBBO这样的框架)。作为微服务架构的雏形,注册中心的加入在解决横向扩展问题的同时,不仅解决了服务间的注册发现和调用,还使得公共模块和逻辑服务相互独立。但与此同时,运维监控的压力也大大增加。还有更多与性能和警报有关的服务。同时,也要关注登记中心的健康状况。日志的分布比较分散。当业务出现故障时,故障排除环节变得冗长。对于复杂的业务问题,我们通常需要同时获取展示层、注册中心、服务层的日志,分析它们之间的关系,才能更好的定位问题。这对于运维和应用性能提升都是一个挑战。另外,服务之间的依赖和调用关系复杂,服务提供者和调用者的接口耦合,业务切分不够精细,也让微服务架构登场了。微服务架构我们现在所处的微服务架构通常由网关和功能独立的微服务组成。服务可以相互调用,它们的可用性可以由容器和容器编排能力提供。服务分工更细,职责更明确。服务可以使用RPC和REST相互调用,同时为前端提供HTTP接口。由于服务的完全拆分,服务的开发可以分散到各个小团队进行独立开发、部署和升级。并且每个微服务都可以根据业务的实际运行情况进行横向扩展,但同时微服务过多,服务治理成本变高。同时还要考虑分布式事务、容错等技术。从运维的角度来看,业务日志变得更加分散。全局微服务的监控和告警更加困难。最后,在排查业务问题时,链接变得很长。如果没有全局的trackingid,只能通过日志的时间戳,无论是业务性能优化还是故障排查,都会变得非常困难。也就是业界不断讨论的研究问题,微服务的可观测性。02什么是微服务的可观察性?从上一节的架构演进可以看出,随着服务越来越拆解、越来越独立,运维难度和系统复杂度成倍增加。为了改进,我们不得不面对以下问题:随着模块之间的调用关系从进程内函数调用转变为通过网络进行进程间调用,如何检测和保证网络的可靠性。调用链接的时间越来越长,流量越来越不可控。如何有效地解决问题或提高应用程序性能。现代微服务的实践和部署往往与Kubernetes、Docker、ServiceMesh等云原生技术相结合,使得开发团队更难感知底层基础设施的状态。传统上,对于系统监控,我们往往会关注CPU、内存、网络、应用接口请求量、接口响应量等,但对于微服务系统,这并不能帮助我们掌握整个系统的运行情况。它就像轮胎、水箱和油箱。当这些东西分开独立放置的时候,我们可以比较容易判断它们的状态,但是当这些东西组合成一个“系统”的时候,比如汽车,汽车会如何运行,在这个过程中,观察它的状态就成了重要的一环影响小车的稳定性,微服务系统同样适用。微服务的可观察性是解决数据流经客户端输入后,透明地了解各个服务之间数据采集、传输、存储的状态,进而解决系统运行过程中的故障预测问题。为了确保感知这些数据流的状态,业界普遍认为有几种类型的数据可以用作可观察性的支柱:Metrics、Logging和Tracing。其中,Metrics是一个原子,在一段时间内组成一个单一的逻辑度量、计数器或直方图,例如服务调用的QPS、响应时间、错误请求发生率,目的是建立一个集中的度量系统,注重技术指标的收集与整合观察;日志用于记录离散事件,如应用程序调试信息或错误信息,目的是构建一个中心化的日志系统,专注于各种微服务日志的统一收集、存储和检索;Tracing请求范围内的处理信息,比如一个远程方法调用的执行过程和耗时,目的是形成一个分布式的跟踪系统,关注微服务间串行请求的调用,然后进行跟踪和处理APM分析。有了以上信息,我们就可以对现有系统进行分类。比如ZipKin和Jaeger专注于Tracing领域,Prometheus专注于Metrics领域,ELK和Loki专注于Logging领域。但是,每个系统也在不断地将其他领域的特性融入到自己的系统中。比如Jaeger遵循了一些OpenTracing规范,但是CNCF已经开始将OpenTracing和OpenCensus合并到OpenTelemetry项目中,未来还会有更多。某些Tracing功能和Metrics系统同时出现。Prometheus虽然一开始专注于指标的收集和管理,但也开始集成一些Tracing的能力。业界对于微服务可观察性的一个解决方案是先使用loki+Grafana统一收集和管理分布式日志,使用Prometheus和Grafana存储和展示Metrics,最后使用Jaeger等跟踪系统。分布式跟踪的存储和显示。基于此,我们大致可以得到如下问题分析环节:首先我们通过邮件或者其他方式收到告警信息,然后去Grafana图表查看某段时间指标是否异常,然后向下钻取可以在Prometheus中查看异常指标的详细信息,可以获取异常对应的时间或者节点,根据时间从Loki获取日志信息中的requestid或者全局traceid,node和servicelabel,然后通过这个traceid在Jaeger这样符合OpenTelemetry规范的系统中搜索调用链,获取某个服务的异常或者性能响应详情,最终排除问题记录问题。这是一种比较常规的微服务排查方法。虽然在一定程度上解决了可观测性问题,但还是比较繁琐。业界也出现了像exemplar这样的组件,可以将单独的组件串联起来,或者各个厂商也在尝试推出像尔达云这样的一站式解决方案,让上面提到的Logging、Tracing、Metrics不断发展。中心圈很近。03总结微服务架构和云原生的发展,让我们更加从容地面对大数据时代的大型系统开发。这个行业变得越来越复杂。起初,行业内每个问题都有相应的独立解决方案,但逐渐趋向于提供一站式平台体系,可以串联起来。微服务的可观察性一直是困扰整个应用稳定性的问题。在以后的文章中,我们也期待与大家分享更多相关的技术细节和实战文章。
