向左偏移是一种在软件开发生命周期的早期强调测试、监控和自动化的软件开发和操作方法。向左偏移方法的目标是通过尽早发现问题并迅速解决,从而预防问题的发生。
当您尽早发现可扩展性问题或错误时,解决它将更加迅速和经济高效。将低效的代码移动到云容器可能会产生高昂的成本,因为它可能会激活自动扩展并增加您的月账单。此外,在您能够识别、隔离并修复问题之前,您将处于紧急状态。
【squids.cn】 目前可体验全网zui低价RDS,免费的迁移工具DBMotion、SQL开发工具等
问题描述
我想向您展示一个案例,在这个案例中,我们成功地避免了一个可能在生产环境中引发重大问题的应用程序潜在问题。
我正在审查最近应用更改后的UAT基础设施的性能报告。它是一个使用MariaDB作为后端的Spring Boot微服务,在Apache反向代理和AWS应用负载均衡器后面运行。新功能已成功集成,并且所有UAT测试用例都已通过。然而,我注意到MariaDB性能仪表板中的性能图表与部署前的模式有所偏离。
以下是事件的时间线。
8月6日14:13,应用程序与包含嵌入式Tomcat的新Spring Boot jar文件一起重新启动。
应用在迁移后重启
在14:52,MariaDB的查询处理速度从0.1增加到88次查询/秒,然后增加到301次查询/秒。
查询速率增加
此外,系统CPU的使用率从1%提高到6%。
CPU使用率上升
最后,JVM在G1 Young Generation垃圾收集上花费的时间从0%增加到0.1%,并保持在该水平。
JVM上的GC时间增加
该应用程序在其UAT阶段异常地发出300个查询/秒,这远远超出了其设计的范围。新功能导致数据库连接增加,这就是查询增加如此剧烈的原因。然而,监控仪表板显示,在部署新版本之前,有问题的措施是正常的。
解决方案
这是一个使用JPA查询MariaDB的Spring Boot应用程序。应用程序旨在在最小负载下在两个容器上运行,但预期可以扩展到十个。
Web - app - db拓扑结构
如果单个容器每秒可以生成300个查询,那么如果所有十个容器都在运行,它可以每秒处理3000个查询吗?数据库是否有足够的连接来满足应用程序其他部分的需求?
我们别无选择,只能回到开发者的桌面上检查Git中的更改。
新的更改将从一个表中取出几条记录并处理它们。这是我们在服务类中观察到的。
List findAll = this.xRepository.findAll();
不,使用Spring的CrudRepository中的findAll()方法而不进行分页是不高效的。分页有助于通过限制抓取的数据量来减少从数据库检索数据所需的时间。这是我们的初级RDBMS教育教给我们的。此外,分页有助于保持低内存使用量,以防止由于数据过载而导致应用程序崩溃,以及减少Java虚拟机的垃圾收集工作量,这在上述问题陈述中提到。
此测试仅使用一个容器中的2,000条记录进行。如果这段代码要移到生产中,在最多10个容器中有大约200,000条记录,那么那天它可能会给团队带来很大的压力和担忧。
应用程序通过向方法添加WHERE子句进行了重建。
List findAll = this.xRepository.findAllByY(Y);
正常功能得到了恢复。每秒的查询数量从300减少到30,投入垃圾收集的努力恢复到原来的水平。此外,系统的CPU使用率也降低了。
查询速率恢复正常
学习和总结
任何在网站可靠性工程(SRE)中工作的人都会对这一发现给予高度重视。我们能够在不必提高为Severity 1标志的情况下对其采取行动。如果这个有缺陷的包在生产中部署,它可能会触发客户的自动缩放阈值,即使没有额外的用户负载,也可能导致启动新的容器。
从这个故事中,我们有三个主要的启示。
首先,从一开始就启用可观察性解决方案是最佳实践,因为它可以提供一个事件历史,该历史可以用来识别潜在的问题。没有这个历史,我可能不会认真对待0.1%的垃圾收集百分比和6%的CPU消耗,代码可能已经发布到生产中,带来灾难性的后果。扩展监控解决方案的范围到UAT服务器帮助团队识别潜在的根本原因,并在它们发生之前预防问题。
其次,性能相关的测试用例应该存在于测试过程中,并且这些应该由在可观察性方面有经验的人进行审查。这将确保代码的功能被测试,以及其性能。
第三,云原生的性能跟踪技术很适合接收关于高利用率、可用性等的警报。为了实现可观察性,您可能需要具备适当的工具和专业知识。编码愉快!
作者:Pandian Ramaiah
更多技术干货请关注公众号 “云原生数据库”