微盟APM系统之数据流处理优化篇
发布于 3 年前 作者 qiang90 3212 次浏览 来自 分享

从2020年微盟APM系统大规模投入使用以来(链接:https://developers.weixin.qq.com/community/develop/article/doc/000aaed6f98b28093f3a5265151c13),微盟各个业务线的小程序的公众号的流量也从2020年初的日均百万级别人次(UV)上涨了两倍多。同时随着人均驻留时长大幅度提升、业务复杂程度大幅度加大,人均产生的调用链、运行时日志也较初上线时翻了三倍多。这就意味着,原有的APM系统架构要面对提升的流量,就会产生高额的费用。为此,我们计划将微盟APM系统(代号MARS - Monitoring & Automatic Reporting System)的数据处理架构进行优化和升级,目标是应对更高的流量并且降低服务端成本,同时也希望借此拓展MARS的功能、效率、以及灵活度等等。

上图为MARS的最初数据处理的流程图。从中我们可以发现,这个模式虽然存在直观、简单、开发成本低等优势,也存在以下问题:

1、Node.js应用直接请求进入ElasticSearch导致流量没有统一收口

2、统一化服务对机器要求高,且每次修改风险大

3、数据进入ElasticSearch未做队列、聚合等处理,失败率高

4、失败日志查阅不方便,难以定位问题

5、没有合理的环境隔离

鉴于以上问题,我们认为需要对数据校验和消费进行分离,才能够在每次修改时做简单的增量发布,从而实现对接各种内部系统或者不同数据库实现如周数据环比等新的业务需求。在微盟,我们有一套非常成熟的基于Kubernetes的OMS系统,我们在此简称OMS Kubernetes。我们认为OMS Kubernetes已有较为完善的DevOps和日志系统功能,还有比较良好的扩容能力(当然在消费者服务上为了避免新加入consumers引发kafka rebalance,因此设置为手动扩容),因此新的系统应该被搭建在OMS Kubernetes之上,实现资源最大化利用的同时竟可能的复用已有的内部系统。

通过规划,我们认为新的系统可以按照以上描述的,从原有的直接从数据源发送数据并且写入ElasticSearch的模式修改为,由统一的网关服务生产、校验数据以后进入Kafka,然后在消费者内对数据进行小队列的聚合和处理后再发送至ElasticSearch内。

通过以上系统的改造,我们首先能够获得服务器承压能力和成功率的大幅度提升。以下为老APM服务的压测结果:

从上图可以看出,老的APM系统的承压能力基本上取决于ElasticSearch的承压能力,在面临大规模流量访问时,虽然一开始可以维持2000+的TPS,但是很快TPS大规模下降,并且响应速度非常不理想。最终在单台压力机,请求1分钟的情况下,虽然有多台黑石物理机为载体,就已经出现无法承压的表现,错误率1.57%,平均TPS 908,平均响应时间854毫秒。

上图为最终优化版本的新版DEV环境下的MARS系统(0.5核2GB Pod),虽然在DEV下的Gateway服务的载体性能较多台黑石机弱了数百倍,但是依然可以实现几乎相同的1.65%的错误率的TPS 649,虽然平均耗时有较大的提升,到了2955毫秒。并且,新的服务没有出现之前1分钟不到就出现无法访问的情况,能够在高压下依然维持600上下的TPS。

我们将相同的服务上线(结果见下图),设置为20个1核2GB的Pods(固定配置,无自动扩容),得到了可喜的0错误,TPS 38073,平均耗时13毫秒的结果。实际上20个1核2GB的Pods在性能和费用上还远不上原先单台黑石物理机,更不要说是多台了。因此除了性能上新的架构较原有有了质的飞跃,成本上也有大幅度的削减。鉴于此,我们将线上的扩容能力设置为20-100(实际上我们认为初始为10台可能已经可以满足90%以上的业务场景)。

当然,在多次压测过程中,我们发现了Node.js服务的一些缺陷。如Node.js可以在短时间内接收大量请求,并且响应速度极高,但是在收到一定的请求以后会进入“装死”模式,既对新的请求不作出任何响应,直到CPU和内存占用降低到一定的比率下。鉴于这个问题的存在我们做出了以下的性能优化改进:

有效

1、提升OLD内存使用

2、判断同时处理的异步请求达到阀值后切换为同步响应

3、允许更长的监控检测响应时间

无效

5、CPU占有率提高后切换为同步响应

6、内存占有率提高后切换为同步响应

7、连续网络请求达到阀值后切换为同步响应

8、CPU占有率或内存占有率提高后切换为同步响应

9、5+6+7的权重算法

我们认为在Node.js对系统性能的技术可能因为其Runtime特性和实际请求时的event loop处理逻辑是脱钩的,因此出现了5、6、7、8、9方案无效的情况。使用actix框架(Rust)编写的程序在和DEV相同配置的的Pod(0.5核2GB)内可以避免错误率的出现,并且响应时间有明显降低,但是鉴于现有的OMS Kubernetes并不支持Rust应用,且其生态相对于Node.js应用不是非常成熟,因此我们将服务端逻辑由Node.js往Rust的迁移定到了下一期的规划内。

1 回复

有数据,有图表,条理清晰【手动点赞】

回到顶部