客户端动态降级系统

6600909dc06a4dd9a102933d90ac2fc2.jpeg

41f2186e9ce2e22a8bdd74c6fb1005ea.gif

本文字数:4576

预计阅读时间:20分钟

c716a54f88dbc8768458a0efdc5e857f.png

01

背景

无论是iOS还是Android系统的设备,在线上运行时受硬件、网络环境、代码质量等多方面因素影响,可能会导致性能问题,这一类问题有些在开发阶段是发现不了的。如何在线上始终为用户提供一个相对顺畅的用户体验,是客户端开发需要考虑的一个问题。

02

服务降级、熔断

服务端有降级机制和熔断机制,在设计客户端降级系统时可以参照服务端现有方案。例如发生性能问题或网络拥堵的情况,需要减少设备和网络的负担,等恢复后再进行策略升级。

服务端降级机制,当服务端出现整体负载较大,或因为特殊原因出现数据错误,则会触发降级。不同的情况对应不同的降级策略。例如数据原因导致的,可以不去读DB数据库,直接返回缓存数据。从用户的角度来看,可能是数据更新不及时,但可以正常显示。

服务端熔断机制,熔断机制是比降级更严重的情况,当服务端中某个微服务不可用,或响应时间过长,则会触发熔断,不再调用这个服务。从用户的角度来看,可能是头像不能显示,或者页面部分模版未显示,购物车商品结算不能使用优惠券等。

03

方案简述

首先,我们需要捋清楚,客户端需要处理的问题都有哪些。我将其分为两类,性能和网速,性能又可以细化为CPU、内存、电量三类,这三类都会对App的运行造成影响。同样的,我们不能直接把性能分为好和坏两种,而是需要通过枚举的方式,将其细化为不同等级。

这里以iOS系统为例,我们需要对iOS设备CPU、内存、电量、网速进行实时监控,可以设定一个合理的间隔区间。在发生前面的性能问题时,通过对不同类型的问题进行阈值计算,从而得出对应的等级。如果级别发生变化,则通过通知的方式,告诉业务方降级或升级。

当发生降级时,业务方进行对应的降级处理,例如降低网络请求的图片尺寸。通过业务降级处理,降低系统性能消耗,让CPU、内存逐步恢复到正常区间,再进行业务升级,恢复原有业务处理规则。

通过上述方式,来保证发生性能或网络问题时,用户依然可以较为流畅的使用App,并且App内功能的正常使用不受影响。

04

整体设计

动态降级系统的设计,主要分为三个部分,职责划分如下。

DynamicLevelManager:调用monitordecision完成分级计算,当级别发生变化时,通过通知的方式告知业务方。

DynamicLevelMonitor:监控关键性能指标,由manager定时调用。

DynamicLevelDecision:由manager将收集到的性能指标交给decisiondesicion对于指标进行统一计算,并决定性能级别,并返回给manager

8ae50dffd87b0dfb0e108129c6c6457b.png

下面是脱敏后的伪代码,主要是表达清楚设计思路。 demo代码也可以直接跑起来,如有需要可以直接 copy拿去用。

05

DynamicLevelManager

DynamicLevelManager为动态降级系统的核心类,后面都称为manager,当App启动时通过openLevelAnalyze方法注册监听,从而开启一个由dispatch_source_t实现的loop,每隔1.5秒执行一次,执行时会触发dispatch_source_set_event_handler的回调方法。dispatch_source_t由手机硬件时钟触发,不受主线程卡顿影响,监听相对精确很多。

/// 开启动态降级监控系统
- (void)openLevelAnalyze {
    self.sourceHandle = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
    dispatch_source_set_timer(self.sourceHandle, dispatch_time(DISPATCH_TIME_NOW, 0), 1.5 * NSEC_PER_SEC, 0);
    dispatch_source_set_event_handler(self.sourceHandle, ^{
        /// 计算综合性能级别
        CGFloat cpuUsageValue = [[DynamicLevelMonitor sharedInstance] cpuUsageForApp];
        NSInteger memoryUsageValue = [[DynamicLevelMonitor sharedInstance] useMemoryForApp];
        CGFloat batteryUsageValue = [[DynamicLevelMonitor sharedInstance] batteryUsageForApp];
        [[DynamicLevelDecision sharedInstance] calculatePerformanceLevelWithMemoryValue:memoryUsageValue
                                                                               cpuValue:cpuUsageValue
                                                                           batteryValue:batteryUsageValue
                                                                        completionBlock:^(MemoryUsageLevel memoryLevel, CPUUsageLevel cpuLevel, BatteryUsageLevel batteryLevel, MultiplePerformanceLevel performanceLevel) {
            /// 判断级别是否发生变化,发送性能降级或恢复原有等级的通知
            if (performanceLevel != self.currentPerformanceLevel) {
                [self postPerformanceNotifiWithPerformanceLevel:performan
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值