内容来源:2018 年 3 月 10 日,极光研发中心ios高级工程师沈孝星在“饿了么技术沙龙・第22弹 【移动专场】”进行《极光 iOS SDK 架构及性能优化经验分享》演讲分享。IT 大咖说(微信id:itdakashuo)作为独家视频合作方,经主办方和讲者审阅授权发布。
阅读字数:2076 | 6分钟阅读
摘要
随着移动互联网的快速发展,移动端设备及用户的数量急剧增长,对产品的性能提出了更高的要求,尤其对 SDK 产品来说,需要不断地重构改进。本次分享主要介绍极光 iOS 平台上 SDK 架构演变过程,以及针对网络通讯、本地缓存等的优化。此外,还将针对 APP 开发给出一些性能优化建议。
嘉宾演讲视频及PPT回顾:http://suo.im/5jcOf4
SDK架构优化
旧架构
2016年以前我们的产品还是比较单一的,只有极光推送和极光IM。它们分别对应JPush和JMessage结构,这两个结构都有Network、Model、Cache。
JPush SDK由单独的类库承载,实现了如数据通道,任务列表,用户活跃,用户新增等功能。JMessage业务依赖于JPush的底层实现,拥有JPush的全部功能,但与JPush是各自独立的,且不能同时集成。
旧架构弊端
2016年极光的产品结构发生了比较大的变动,新增了一些SDk,后续还会引入新的SDK。这样的话继续采用旧架构就会出现一些弊端,首先各自独立的SDK不容易管理,尤其是在代码上,稍有变动所有的SDK都要进行同步;第二点是空间占用大,单单JPush SDK的大小就达到了286K,而如果要集成多个SDK相应的大小就会成倍增加;第三点是需要重复集成,重复注册SDK;第四点是占用没必要的线程,每个SDK都要依赖自己的线程运行,多个SDK就会占用多个线程,这样就造成了线程的浪费;最后每个SDK注册都会开启一个通道与后台通信,这样不仅会增大后台的压力还会消耗更多的资源。
新架构
将JPush一分为二,一个是JPush自有的业务,另一个是一些基础组件以及核心功能。我们将第二部分封装成了新的SDK,命名为JCore。JCore负责核心通用的功能,上层SDK各自在JCore之上运行自有业务,它的机构更加清晰,利于扩展,并且能够共享资源,以减少重复动作。后续如果要对基础的组件或功能进行针对性优化的时候会更加方便,因为只需要去修改JCore就行了。
JCore内有一些基础组件,包括线程、通道、https、日志、缓存等。除此之外还有一部分公共业务被抽取出来,比如注册登录、数据上报、用户信息上报等。
新架构劣势及存在问题
虽然是新架构但也存在一些劣势及问题。比较大的问题就是核心包的更新,在对JCore进行问题修复的时候,测试的成本会比较高,因为涉及到多个SDK,且每个都要验证。另一方面发布体验也不好,原来只需要针对某一个SDK更新发布,现在则要对多个SDK一并发布。其次相对于旧版本集成繁琐。最后由于JCore是基于JPush的,核心包可能还存在一些性能问题。
性能优化
长连接
客户端到服务器端很多公司都会做负载均衡,我们采用的做法是这样的。在服务器和客户端有一个sis通信,通过它获取到最优地址。除此之外还有一套缓存机制,sis的请求结果会被缓存下来。
在整个过程中有一套优先选择可用的,排除不可用的策略。获取到的sis通信是成功的话就直接连接到最优地址,而失败的话则尝试读取缓存的最有地址,还不行就通过SRV的查询得到可用地址,最后实在不行就设置超时时间等待重连。这样的流程基本上就保证了比较快的接入,大致在50毫秒内能接入成功。
另外sis的过程可能会有失败的错误信息等,这些信息会通过UDP的协议传输到后台,然后后台会给出反馈,根据这些反馈就可以做进一步的优化。
除了接入服务我们还对长连接的通信进行了优化,之前通信的读写是和工作线程在一起的,一般情况不会有问题,但是在工作线程进行比较耗时的操作时就会产生影响。现在则将长连接单独提到一个线程中,数据在线程中缓存,根据数据队列与工作线程同步。
本地缓存
本地缓存方面之前的做法是在工作线程内进行数据的读写,任何体量的数据都共用一个文件。但是这样的单线程操作,容易堵线程,达到一定数量后,读写耗时会较长,且在某种情况下,容易丢失数据。
因此我们在本地缓存方面做了一些优化,对数据进行分类,采用多线程任务队列的处理方式,对轻量的数据采用轻量级系统存储,而大型的数据单独写文件,每一个数据都写一个文件。
APP开发的优化建议
- 把握架构设计合理性,多做结构优化分析。
- 复杂的逻辑简单化,简单的逻辑更容易实现及维护
- 权衡利弊,不同的场合用适当的方法解决
- 多回头看看自己写的代码,或许能发现一些问题
有问题可以在评论区讨论,以上为所有分享内容,谢谢大家!