跨全端SDK技术演进
简介: 细想,团队进行跨平台开发已有三年有余,也是集团里面C++方向里比较早涉及该领域的部门之一,伴随业界跨平台技术发展与演进,我们也沉淀了一整套基于C++的跨平台技术体系,本文将以消息SDK为例,详述这一技术演进历程,希望能给想做跨平台的,尤其是刚步入跨平台开发的同学和团队,一些借鉴和启发,帮助大家少走一些弯路。 此文为本系列文章第一篇, 第二篇:跨桌面端之Web容器演进 第三篇:跨桌面端之组件化实践
关于为什么要选择跨平台的实现方式
Write Once, Run AnyWhere.
越来越多的业务需求都有统一的业务诉求,按照传统的方式,在开发、测试、维护上的成本都是乘以N的,体验也很难做到一致性,特别是复杂的业务,实现成本高,导致功能不能很快的上线,各端侧对齐存在成本,综合来看,这样或者类似的业务基于研发效率等考虑,选择用跨平台的实现方式是非常有必要的。
多角色的运营,多场景的触发,多重能力的支持,导致我们的消息系统十分的复杂,历史发展下的多通道消息系统底层由于历史发展衍生出3个子系统分别是:
- BC消息 - 最早的阿里旺旺就是基于此
- AMP消息 - 淘宝天猫的各类运营基于此,衍生出来的主要业务包括商家群、淘友、达人业务等,
- IMBA消息 - 主要是号方面相关的消息,包括BC通知类的消息、达人运营,品牌号运营等
分别在不同的BU维护,而这些在多平台运营下都是需要的,比如多角色的融合,多载体运行的诉求,每个载体又有多种平台。
基于以上背景,研发一个高可用、高复用、可定制的跨终端消息模块是非常有必要的。
关于语言的选择
选择编译型语言还是解释型语言,我觉得是没有绝对而言的,具体选择哪个要根据面对业务形态,适配的终端类型等多方面抉择而言,这里说下我们选择C++作为跨平台开发的首选语言一些背景。
- 我们团队本身是客户端的业务型团队,当前需要跨平台的业务主要是消息以及消息衍生业务的开发、维护和创新。
- 主要的终端包括移动IOS、移动安卓、MAC、WINDOWS。
- 主要载体包括淘宝app、天猫app、千牛app、淘特app、1688app、ICBU app等等。
C++作为天然的跨平台语言,可以高效无缝的调用系统能力,有丰富的技术生态,综合组内的技术栈,是比较契合我们的。
其实也跟集团里其他几个有类似需求的团队聊过,目前选择比较多的也是C++技术栈,本文也将以C++作为跨平台选型语言为主要来讲述。
即使是对于客户端而言,可选择跨平台语言也是众多的,通常跟随着跨平台技术方案一起来看会比较好一些,没有绝对的对和错,只有是否适合你。
关于基础库的选择
既然选择了C++作为我们跨平台开发的基础语言,那么面临的第一个问题是需要有一个功能较为完备,且符合当前诉求的基础库。我们调研了市面上几个主流的基础库
再结合集团内当时的现状,特别考虑移动端的现状:
- 包大小问题
- 集团中多种中间件(mtop、db、accs等)要不然已然跨终端,要不然在各端上都有较为优秀的独立sdk提供,基于第一点考虑,这一部分不需要在基础库里二次建设。
综合以上因素,集团内没有合适的足够小的且满足需求的c++基础库,因此我们当时决定自研一个基于C++ STD的符合移动端现状的轻量级跨终端基础库。
这里是跨终端轻量级基础库(LITE)的一个功能集合图,在对这部分进行设计的时候,主要考虑的几个设计原则:
- 基础能力要圈覆盖,
- 综合考虑包大小,性能 以及耗电量等
- 除了提供默认实现外,当系统层面有比较好的能力、或更优解时时,复用端上的能力,通过统一的方式嫁接。举个例子,集团中间件mtop,accs等,亦或者诸如Crypt模块,我们期望用比较简单的方式去实现,调用了Openssl的加解密接口,熟悉Openssl的同学都知道他的库大小在1M左右,同时IOS系统直接就提供Openssl能力,所以在做这一部分的时候我们提供了默认实现,同时开放统一接口接入系统能力,从而实现包大小最优。
总结一下设计原则9个字:最小够用可扩展原则。
平台 |
包大小(kb, 基础功能) |
说明 |
ANDROID |
43kb |
动态库,v8a |
IOS |
116 |
静态库,实际占app大小 |
Windows |
47kb |
x86 |
包大小情况如图(未包含淘宝天猫基础客户端能力,包含后略增加60k左右)。
目前Lite库已经作为淘系C++基础库集成在集团的近100个App里,除了包大小优势外,稳定性也极佳,百万分之1左右的崩溃率(淘宝双端统计),同时与淘宝天猫架构组合作,无缝提供淘宝天猫客户端基础能力(log、埋点、键值存储等)。
关于跨平台的架构选择
通常技术还是为业务服务,还是贴近业务来讲述,能更有体感一些,这样也更直观的把我们遇到的问题和背后思考透漏给大家,作为参考,还是以消息为例:
我们面临的问题和诉求:
- 屏蔽通道,以统一的数据模型方式对外提供:底层需要对接3个服务端(多通道),同时每个server端提供的能力、功能又高度相似,需要抽象后统一屏蔽提供给上层,此外相关数据需要跨通道或者屏蔽通道存储。
- 调用方线程不统一:业务部分需要处理来自不同线程的高并发(于客户端而言)请求。
- 多语言:接入层需要适配不同平台,ANDROID-JAVA,IOS、MACOS-Object C,WIN-C++。
- 多维度支持定制:
- 业务定制:业务上需要面对不同的APP可以有不同的功能定制,这里还包括支持通道的可配置,业务能力的可定制等,举个例子:在淘特里无群聊服务,但是在淘宝里这一部分又是需要的,在千牛里需要有商家群,但不需要有淘友关系群,等等基于业务、以及包大小考虑的定制。
- 线程调度定制:基于耗电量、系统资源、平台特性等考虑,需要线程调度方案的可定制。在移动端对耗电量比较敏感且系统资源有限,但是PC端上对性能要求会更高一些,如何在统一的方案里支持线程调度的平台级、甚至是业务级别定制。
- 网络流量管理定制:对网络能力一方面要有统一的监控,方便判断MTOP的各种API调用情况分析,另一方面需要有统一的切面能力,在MTOP的调用上做二次业务级别的网络流量接口优化定制。
- DB管理定制:基于FD、平台特定等考虑,需要DB管理可以根据不同的平台有不同的定制策略,在移动端采用单用户一库多表的形式,在pc端性能最大化采用多库多表甚至需要支持不同app的不同db管理方案可定制。
- 基础能力复用:对于集团通用的基础组件,需要有统一的能力从外部获取从而方便c++层使用。
- 稳定性保障:是否方便做单元测试,设计上如何避免单元测试对内部代码的入侵。
基于以上,我们设计了MessageSDK的架构大致如下:
来整体看下上面的设计是如何解决这些问题的。
总体分5部分,Service层,业务层,数据层,数据通道层以及基础服务层。从上到下看整个架构设计
- Service层:也就是我们通常说的Wrapper层,其目的是为了翻译业务层C++的接口,提供三种方式的直接接入,Java,Oc,C++,需要说明的是这一层不要做除语言转换外的任何代码,一来方便问题排查,wrapper不做额外的处理和问题排查,二来业界也有不少自动化实现语言翻译的工具,有关这部分我们后面部分详细聊。
- 业务层:业务逻辑的一个组合,以消息为例,按模块分为三个子模块第一个消息模块,第二个profile模块,第三个群模块,模块与模块之间相对独立,做强制隔离,代码无耦合,功能可定制化
- 数据层:分为两部分本地存储以及网络存储,其目的是屏蔽数据来源以统一的方式提供给业务层,让业务不感知通道来源,同时在这一层还吃掉所有的耗时操作,IO以及网络请求,其中Adpter主要是屏蔽通道之间的差异,这一部分支持整体可替换,目的提高扩展性,可定制接入三方通道
- 数据通道层:这一部分就是数据来源的通道,主要有SYNC,WXNet,DB等
- 基础服务层:是一个跨平台的c++基础库。
其实客户端按层分割的设计理念,无论是在PC时代还是现在的移动互联,都不是什么显而易见的事儿,主要关注下这里面的差异点也可以说是这种框架设计的优点。
- 便捷:service我们只做语言层面的胶水,缩短后期排查问题的整个链路,方便后期排查和定位问题。同时自动化的实现也再次降低了维护成本。
- 开放:上图右侧是Openpoint能力,主要是通过一些标准化的开放点去开放一些能力,让接入方做更多的业务属性,简单来说【每个业务有特定的开放点,用统一的形式开放出去】
- 定制:
- 业务定制:模块与模块之间相互完全独立,代码无耦合,强制隔离,实现功能的可定制化,让业务方可以自由的进行业务形态组合的同时做到包大小最优,
- 线程调度定制:统一线程调度处理方案,抽象线程配置策略,多app可自由配置,上层可选择平台级线程调度最优方案。
- 网络流量管理定制:网络调用处统一切面处理,一方面对瞬时相同请求做拦截合并,大幅度降低服务端压力,另一方面针对业务级别做原子调用的合并定制,减少服务端查询量,此外切面处进行统一打点处理,方便客户端做调用流量监控。
- DB管理定制:同线程调度定制,统一DB管理分配方案,抽象库分配策略,多app可自由配置,上层可选择平台级线程调度的最优方案。
- 扩展:对外提供整体能力,又可以动态替换,目的是提供一种能力让接入方可以放入自己的数据通道,从而实现一个业务的扩展,此方法也极大的方便了后期做统一的单元测试。
于CPP程序员而言,线程模型是非常重要的,好的设计可以从架构上就避免掉后期一系列隐秘的bug,这里包括一系列问题,比如:
- 在移动端上,通常调用者不关心调用线程,但是在数据层又需要做统一的数据修改和聚合能力
- 业务层频繁调用,过多的锁除了可能会出现死锁外,也不利于性能最大化。
- 部分接口如果IO、NET时间过长可能导致整个流程中断,或异常。
来看下跨终端SDK架构设计的线程模型:
- 接入层:不限制调用线程,降低接入成本
- 业务层 : 按模块做隔离,单独运行在自己的业务线程里,在biz层做业务无锁话的同时,做到单业务无锁化,多业务并行化
- Model层 : 主要是做IO、网络操作,目的是为了业务线程IO、网络无阻塞
整个线程模型的特点:纯异步,可定制,单业务无锁化,多业务并行化,IO网络无阻塞。
C++工程脚手架及C++工程标准化
C++作为天然的跨平台语言,可以高效无缝的调用系统能力,有丰富的技术生态。但是实际面向Android、iOS、Windows、Mac等多平台的开发过程并不顺滑,主要存在以下问题:
- 平台特性差异、开发语言、开发工具链、编译打包等
- 多平台下项目配置维护成本高
- 胶水(语言转换层)代码人工接入成本高、重复性工作大、门槛高(主要是对于C++开发者)
- 业务及技术框架选型困难
- 构建发布方案规范化较差、集团研发平台对跨平台构建发布的设计不足
我们在想,SDK开发流程是否可以是一个可被SOP的过程?如果有统一的跨平台SDK开发SOP流程,特别是对于新入此行的同学,当然是非常友好的。想想coder如果可以上来就可以写业务代码,不用关心框架,工程模型,打包方案等等,是不是美滋滋。
为了解决上述共性问题,结合之前我们在消息SDK上的相关经验,我们启动了Eyas(雏鹰)项目。
Eyas旨在进一步结合集团技术能力,降低跨终端开发成本,为其提供标准化的作业流程,包括跨平台基础库组件化、业务框架通用化、配置一体化、语言转换层代码工具化,以及发布能力统一化等一整套解决方案,让开发者们可以在轻量级认识跨终端的同时,更专注于业务本身。
Eyas的中文是雏鹰,我们希望通过Eyas,可以一起在跨终端的蓝海中探索无限可能,同时可以孵化出更多跨平台的模块,让开发者低成本开发跨平台SDK,保证多平台业务一致性,提升业务开发效率的同时降低测试成本。
为了让开发者可以更快的上手跨平台的开发,我们拟定了一套跨平台SDK开发的作业流程,同时在每一步都提供了对应的解决方案,所有的解决方案均提供工具化的方式来高效、低成本的辅助开发者们进行跨平台SDK的开发。下图是MTL4上C++跨平台研发工作流:
其中 IDL(接口描述)的编写 以及 功能代码编写,需要开发者根据实际业务进行开发。我们从项目创建、代码生成、编译选项和构建四个维度分析。
▐ 创建项目
跨终端团队在以往的桌面端开发中积累了很多SDK开发经验,也有一套成熟的SDK框架代码,但是我们在孵化新SDK时候,还是要花一定时间在SDK的通用代码的拷贝上,无法快速的复制出一个新的SDK项目。
开发者都是懒惰的,为了尽可能的复用代码,提升开发效率,开发者发明了宏,也发明了模板编程。为了支持复用SDK框架通用代码和项目配置,我们提供了基于项目模板创建项目的工具,快速实现项目工程从0到1的过程。
其实对于刚涉足到跨终端开发的开发者,创建了可以编译不同平台产物的项目就已经开启了跨平台的大门。
▐ 代码生成
代码生成即语言胶水层代码工具化,由于平台开发的语言差异,需要有一层胶水代码来进行语言的翻译,胶水代码本身是没有业务逻辑的,并且耗费开发成本,人工编写代码也会带来出错的风险。我们使用胶水代码自动化来解决该问题。
胶水代码自动化的原理:
根据接口的idl描述生成接口文件和胶水代码
JNI: C++ <-> Java交互的胶水代码
ObjCPP: C++ <-> ObjC交互的胶水代码
我们基于djinni(地址:https://github.com/dropbox/djinni)进行了二次开发,提升安全性的同时增加了多项feature,更容易对复杂项目做模块定制化能力。
▐ 编译配置+依赖管理
支持以下能力:
- 使用GN管理工程和源码文件,确保多端的C++项目配置一致。
- 统一多平台业务模块定制化能力。
- 支持多平台下不同IDE编码和调试。
- 结合集团技术能力,统一依赖管理解决方案,支持通过一份配置文件管理多平台下的依赖。
跨全端SDK技术演进的更多相关文章
- 【大数据和云计算技术社区】分库分表技术演进&最佳实践笔记
1.需求背景 移动互联网时代,海量的用户每天产生海量的数量,这些海量数据远不是一张表能Hold住的.比如 用户表:支付宝8亿,微信10亿.CITIC对公140万,对私8700万. 订单表:美团每天几千 ...
- 基于深度学习的目标检测技术演进:R-CNN、Fast R-CNN,Faster R-CNN
基于深度学习的目标检测技术演进:R-CNN.Fast R-CNN,Faster R-CNN object detection我的理解,就是在给定的图片中精确找到物体所在位置,并标注出物体的类别.obj ...
- PouchContainer 容器技术演进助力阿里云原生升级
点击下载<不一样的 双11 技术:阿里巴巴经济体云原生实践> 作者 | 杨育兵(沈陵) 阿里巴巴高级技术专家 我们从 2016 年开始在集团推广全面的镜像化容器化,今年是集团全面镜像化容器 ...
- 为什么 K8s 在阿里能成功?| 问底中国 IT 技术演进
作者: 曾凡松 阿里云云原生应用平台高级技术专家 张振 阿里云云原生应用平台高级技术专家 导读:本文描述了阿里巴巴在容器管理领域的技术演进历程,解读了为什么 K8s 最终能够大获成功的原因,以及到今年 ...
- 阿里云杨敬宇:边缘计算行业通识与阿里云ENS的技术演进之路
近日,阿里云杨敬宇在CSDN阿里云核心技术竞争力在线峰会上进行了<5G基础设施-阿里云边缘计算的技术演进之路>主题演讲,针对5G时代下,行业和技术的趋势.边缘计算产业通识以及阿里云边缘计算 ...
- 高德AR & 车道级导航技术演进与实践
2020云栖大会于9月17日-18日在线上举行,阿里巴巴高德地图携手合作伙伴精心组织了"智慧出行"专场,为大家分享高德地图在打造基于DT+AI和全面上云架构下的新一代出行生活服务平 ...
- 从 0 到 1,Java Web 网站架构搭建的技术演进
初始搭建 最开始,就是各种框架一搭,然后扔到 Tomcat 容器中跑,这时候我们的文件.数据库.应用都在一个服务器上. 服务分离 随着系统的上线,用户量也会逐步上升,很快一台服务器已经满足不了系统的负 ...
- 从0到1,Java Web网站架构搭建的技术演进
俗话说得好,冰冻三尺非一日之寒,滴水穿石非一日之功,罗马也不是一天就建成的,对于开发人员来说,一个好的架构并不是一蹴而就的. 初始搭建 最开始,就是各种框架一搭,然后扔到 Tomcat 容器中跑,这时 ...
- 一文读懂前端技术演进:盘点Web前端20年的技术变迁史
本文原文由作者“司徒正美”发布于公众号“前端你别闹”,即时通讯网收录时有改动,感谢原作者的分享. 1.引言 1990 年,第一个Web浏览器的诞生:1991 年,WWW诞生,这标志着前端技术的开始. ...
- 关于大型网站技术演进的思考(二十)--网站静态化处理—web前端优化—中(12)
Web前端很多优化原则都是从如何提升网络通讯效率的角度提出的,但是这些原则使用的时候还是有很多陷阱在里面,如果我们不能深入理解这些优化原则背后所隐藏的技术原理,很有可能掉进这些陷阱里,最终没有达到最佳 ...
随机推荐
- 基于泰凌微TLSR825x的物联网解决方案之ibeacon开发总结
一 概念 iBeacon 是苹果公司2013年9月发布的移动设备用OS(iOS7)上配备的新功能.其工作方式是,配备有 低功耗蓝牙(BLE)通信功能的设备使用BLE技术向周围发送自己特有的ID,接 ...
- github无法访问?vscode 无法使用github登录同步? 改 hosts 吧
一.无法访问 github.com ? 想要去 github.com 上拿来主义,结果访问不了,或者 npm 时一直失败? 是什么原因不用问,直接使用 https://tool.lu/ip/ 查询到 ...
- Markdown的习题
markdown的使用说明 习题1: 将这段话改为2级标题 习题2 试着在你的'Typora'中编辑下面的内容: 这是第一行 这是第2行 这是补充内容 这是第3行 习题3 将下面的内容改为指定的格式要 ...
- Rust使用Sauron实现Web界面交互
目录 简介 架构 Application 和组件 简单入门示例 先决条件 创建新项目 编译库文件 引用库文件 运行项目 界面交互示例 创建项目 编译库文件 引用库文件 引用库文件 运行项目 参考资料 ...
- elasticsearch中runtime_mapping实战
背景:需要根据一个实时计算处理的结果值进行排序,数据从es中查询.(基于业务背景:佣金排序) es版本:7.17.1:spring-data-elasticsearch版本:4.3.9 方式一:mys ...
- C#文件加密解密
加密后内容 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.D ...
- KingbaseES特殊权限介绍
用户需求:新建一个用户B,需要能够查询A用户的所有表,并且对以后新建的表也要有select权限. 对于现有的表可以通过动态sql批量进行授权,但是未来新建的表要如何进行授权呢? 查询了帮助文档发现通过 ...
- KGIS支持的扩展介绍
1.postgis postgis的基本核心功能,仅支持地理图形(矢量要素),在其他Extension前启用. 2.postgis_raster 对栅格数据的支持. 3.postgis_topolog ...
- 怎样更直观的查看KingbaseES数据库日志
数据库日志相关参数:默认设置 log_destination = 'stderr' # Valid values are combinations of # stderr, csvlog, syslo ...
- 关于 ThreadLocalRandom 随机数生成器
ThreadLocalRandom 线程安全随机数获取. 示例随机整数:java.util.concurrent.ThreadLocalRandom.current().nextInt(); 线程Th ...