Serverless架构在今天已经不再是新鲜的事物。该架构具有多个特点:较低的运营和开发成本、能快速上线、自动扩展、安全性高和适合微服务等。各大云服务商也提供了各自的Severless解决方案。然而,尽管Serverless架构在某些方面表现出色,但在当前轰轰烈烈的“微服务”进程中,它仍然不是一种主要的选择。除了由于本身特性导致的使用场景受限外,我想乏善可陈的关于Serverless最佳实践的总结也是一个重要的因素。
我有幸参与了一项基于AWS搭建的Serverless (FaaS) 系统的开发工作,该系统提供了一组核心服务。通过几次系统故障调研和性能优化的实际体验,我发现系统监控在Serverless架构中至关重要。所以本文将从Serverless系统监控的角度来展开一些讨论。
先分享一个真实发生的故事:
我们在对上文提到的FaaS 系统做一次部署时,由于API测试不通过导致流水线构建失败。调查发现是因为测试运行时间过久导致请求使用的令牌过期。这一发现直接指向了系统的性能问题。我们回溯大量流水线构建记录后发现,API测试所耗时长在近一个月以来逐日递增。在调查了CloudWatch中各项观测指标后发现:从一个月前开始,Lambda的调用次数始终保持在最大并发量,并且Lambda一直处于高执行时延状态。最终找到根因在于一个会触发Lambda执行的消息事件由于某个bug被大量复制,并且该事件在被Lambda处理后原样发回SQS,导致发生死循环。
尽管这个问题发生在非生产环境,但带来的影响依然是非常大的:首先,测试环境性能明显降低。另一方面,AWS是按使用收费。该问题导致一个月以来,Lambda,SQS,RDS,DynamoDB和CloudWatch等AWS服务被持续不断地使用,因而产生了高额的账单。
上述故事中反映出来的问题可能有很多方面,但缺乏监控与告警无疑是导致该问题持续近一个月而没有被发现和解决的罪魁祸首。那么,在Severless系统中,一般有哪些需要监控的指标呢?其实AWS 的CloudWatch已经给出了部分答案。不同于需要监控CPU/内存使用率等指标的长生命周期服务,Severless服务的一大特点就是不需要开发和运维人员过多关注底层资源的分配和管理。那么与之相对应地,针对Severless (FaaS) 而言,有以下一些值得关注的指标需要监控并配置告警。
一般Severless系统的函数都有最大执行时间的限制。而且从系统的设计原则上讲,一次函数调用也不应执行过长的时间。当监控到较多的长时延函数调用时,表明系统出现了异常情况,且极有可能导致性能问题。同时,长时延也意味着成本的增加。函数执行时延的异常增高通常有如下原因:
所以函数执行时延的异常增高,通常就是系统某一部分出现问题的信号。
调用次数表示某一时间范围内函数的调用次数,它能够反映当前函数的活跃程度以及整体上的执行情况。调用次数的突然变化也会反映系统中的异常情况。另外,监控各个函数的调用情况也有助于我们合理配置该函数的最大并发量。
Severless系统的自动扩容就依赖于函数的调用情况。当多个请求进入系统,而当前函数实例正在处理请求,系统会自动创建新的实例来处理其他请求。这个过程会一直持续到有足够的函数实例来处理所有请求,除非达到最大并发量。一旦达到最大并发量后仍有待处理请求,则认为发生了瓶颈(Throttles)。出现瓶颈则是一个非常明显的需要告警的情况,因此为瓶颈这一指标配置告警通常是非常有效的做法。
无论是函数调用错误或者是函数执行异常都说明系统出现了非预期的行为,都需要尽快处理使系统恢复正常。但需要说明的是,如果系统出现的是性能问题,则不一定会导致错误率提高。所以不能仅依靠这单一指标来衡量系统的健康状态。
以上是我认为的针对FaaS系统最基本的和最重要的三个指标。合理配置这几个指标的监控与告警,可以提前发现大多数非业务问题的系统异常,进而及时调查和解决问题避免更大的损失。
当然,除了函数,Severless系统还会依赖于大量云平台提供的其他服务。以AWS为例,一个典型的Severless架构通常会使用到API Gateway, SQS, SNS, DynamoDB和RDS等服务。而每个服务都有对应的需要关心并监控的指标,从学习了解的角度,有个技巧是直接去看CloudWatch提供了哪些已经被自动监控的指标,进而深入了解每个指标所代表的含义和所反映的深层次问题。了解得越清楚,在配置监控和告警时会更得心应手,收到告警后也有助于快速定位问题。
除了针对各个基础服务的各类指标进行监控外,监控云平台各个账号的账单也是避免损失的一大法宝。Severless系统中很多问题都会导致账单的异常增加,而通常我们的精力都会放在系统问题的调查和修复上,后知后觉地才发现这一实打实的经济损失。大多云平台都提供了成本管理功能。如AWS可以监控账单信息,并配置通知告警。甚至还可以配置预算操作,当账单达到某些条件时自动执行一些预先定义好的行为,以达到止损的目的。
最后需要强调的是,除了监控各项服务的基础指标外,监控业务指标以及由业务指标导向的技术指标也是监控中非常重要的一环,毕竟任何软件系统提供具体业务都是第一位的。在这一方面,Severless架构和其他类型架构没有太多本质上的差别,所以不在此过多讨论,但这也是设计系统监控架构时必不可少的。
尽管云服务商已经提供了很多基础指标的监控,但由于函数的事件驱动以及短生命周期特性,使我们很难从这些基础指标中读到一个完整的“故事”。若是我们想基于这些基础监控去分析系统性能瓶颈,或者尝试调研特定业务问题,则会面临重重困难。当然,很容易想到的方式是分析日志来进行分析和调研,但以我们实际经验来看,尝试从大量日志中发现性能瓶颈绝不是一个简单的事情。
我们曾对上述FaaS系统尝试进行整体性能调优,以及针对特定业务场景的性能优化。需要做的事情大致分为以下步骤:识别性能瓶颈,对发现的瓶颈排列优先级,依次尝试优化,本地验证局部优化效果,测试环境验证特定业务场景下的优化效果,生产环境验证整体性能提升和特定业务场景优化效果。在整个调查、修复和验证过程中,遇到了很多痛点,其中最为明显的就是寻找瓶颈和验证优化后效果两个方面:
由于每个请求都会有若干个函数依次进行处理,其中整个过程还会包括消息队列中事件的写入和读出,数据库的连接和数据读写,第三方服务的访问等过程。而我们所能采用的手段只能是首先分析日志进行初步定位,然后再本地调试进行更为精确地定位。因为现有日志缺少一些必要信息,所以需要增加日志。但这样做,一方面带来了额外的工作量,另一方面也会带来大量的“噪音”,增加了分析日志的复杂程度。更重要的是,记录大量日志有可能影响函数本身执行的性能,也会增加监控系统的成本。另外,本地调试也不是一件容易的事情。由于函数依赖于很多第三方服务或者云平台其他服务,本地需要隔离掉或提供虚拟的依赖。即使使用单元测试来观察特定事件处理过程的执行性能,因为要关注特定业务场景,也需要花费大量时间准备测试数据。
由于依赖过多,每次修复后都需要部署到个人测试环境中,而部署过程会花费较多的时间。另外,想要端到端地去验证整体和局部性能的提升效果,也只能通过写复杂的查询命令来从日志中进行统计。在部署到生产环境后,想要统计特定业务场景下的性能提升也是很大的一个挑战。由于日志主要关注局部过程,很难通过日志提取出特定业务场景并得到统计意义上的结果,所以迟迟无法衡量优化后的真实效果。
虽然以上问题最终都通过各种手段得到了一定程度上的解决,但过程显然不是轻松愉快的。以上问题的症结在于单单依靠日志无法完整地贯通端到端过程,各处日志信息格式不统一,不能方便地聚合各个服务中的监控信息。
分布式监控系统就是可以有效解决这一类问题的技术手段。它通过采用统一数据模型和API,从各个系统子服务/函数中收集数据,统一聚合和分析处理,以良好的可视化方式进行结果的呈现。构建良好的分布式监控系统可以从端到端的视角提供请求跟踪,过程分析,甚至实时调试等功能。所以在业务场景较为复杂的情况下,为Serverless系统应用分布式监控工具应该成为一种必然的选择。
以AWS为例,它提供了原生的监控工具X-Ray。X-Ray具备端到端跟踪功能,可以监控到Lambda,RDS,DynamoDB,SQS和SNS等服务中的元数据,并提供应用程序的端到端和跨服务视图。Service map 则提供了应用程序中的服务间汇总数据的连接视图,其中包括平均延迟和故障率等。其他如延迟检测,数据注释和筛选等也是非常实用的功能。当然,还有很多其他类似的工具也能达到相同的目的,我们在使用中根据具体需求进行选择就好。
本文只是抛砖引玉,没有过于深入的讨论,目的是想总结与记录在Serverless系统中试水的所见与所得。或许我们遇到的很多问题,有可能是因为Severless架构目前并不适用于我们所面临的复杂业务。但我想说,实践是最好的老师,体验和经历这些痛点才会让人更有动力去思考和解决这些问题。监控系统单拎出来也是一个庞大的话题,希望能通过本文让我们更多地回过头去思考监控的目的,总结那些切实帮助和启发到了我们的实践。
文/Thoughtworks刘龙飞
原文链接:https://insights.thoughtworks.cn/serverless-system-monitoring/