2019杭州云栖大会上,高德地图技术团队向与会者分享了包括视觉与机器智能、路线规划、场景化/精细化定位、时空数据应用、亿级流量架构演进等多个出行技术领域的热门话题。现场火爆,听众反响强烈。咱们把其中的优秀演讲内容整理成文并陆续发布出来,本文为其中一篇。前端
阿里巴巴高级无线开发专家宋照春在高德技术专场作了题为《高德客户端及引擎技术架构演进与思考》的演讲,主要分享了高德地图客户端技术架构沿着「上漂下沉」、「模块化、Bundle化」的思路演进所作的一系列架构升级中的经验和思考。前端框架
如下为宋照春演讲内容的简版实录:多线程
主要分享三个方面的内容:架构
1、三管齐下 深度融合框架
高德最初有两个端,车机版的高德导航,手机版的高德地图,两个团队,一个是2B,一个是2C,分别是汽车业务和手机业务。当时在引擎/技术上,分为离线引擎和在线引擎,但两个团队之间交流比较少,各自有本身的研发、产品和测试,而做为一款端上的APP,两块业务都须要有地图渲染、路线规划、导航以及定位等通用能力。从公司层面看,存在较大的重复建设,总体研发效率较低。异步
因而咱们作了一件事:利用技术手段,打通端上引擎,打造一套能同时支撑多端的APP能力。具体到执行层面,先从A团队拉一部分人到B团队一块儿建设,建设完以后再从B团队拉到A团队。在同时支撑好主线业务发展的状况下,经过一年左右时间,完成了引擎上的融合,作到同时支撑手机、车机以及开放平台。模块化
这样就从引擎的维度,实现了渲染、定位、规划和引导的统一。具体来讲,咱们的各大引擎有好多套代码,好几个开发团队,每一个团队有各自的开发方式和开发环境(Linux,Windows,Mac OS)。各类开发环境,工程配置文件大量重复,修改很是繁琐。布局
为此,咱们经过两种方法:性能
1.创建了一套构建系统Abtor,经过一个配置系统实现统一构建,可以同时支持多个子引擎,在构建集成效率上获得了很大的提高;测试
2.对基础库进行了总体重构,造成了一套涵盖了文件I/O、KV存储、多线程框架&异步框架、归档、基础容器等一系列标准能力的基础库,同时也作了引擎核心架构的统一。
2、架构治理
经过引擎的融合同时支持多端,在研发效率上实现比较大的收益。而经过技术的抓手来实现团队的融合,对公司发展而言,这实际上是更大的收益,团队融合的意义在于人才拉通和复用,组织效率获得了较大提高。
随着高德业务的快速发展,业务上持续扩品类,需求量激增,高德地图从最初的驾车导航,到后来的步行、骑行、摩托车导航等等,App所承载的业务发展很是快,而原有的架构治理模式的问题也逐渐暴露出来。
首先就是App的代码规模变得特别大。当时一个仓库达到了10G以上,由此致使的一个典型的问题就是编译慢,编译出一次安装包须要一个小时。伴随代码规模的另外一个问题是团队规模快速增加。代码增加和大团队并行开发,最终致使合版慢,每次迭代,客户端合版须要2天。
代码膨胀致使的架构腐化问题特别突出,因此测试质量以及线上的质量有段时间也比较差。此外,从产品提出需求到上线,平均须要45天,版本迭代周期很长。
为解决以上架构问题,咱们采起了三个手段:升级Native基础组件,搭建Native容器和页面框架,Bundle化分拆(微应用)。
下面重点介绍下页面框架和微应用。
页面框架主要借鉴和融合了Android和iOS的生命期管理机制。从高德地图App架构看,下层模块是一套标准地图,全部上层业务都要基于地图模块开发。为确保上层业务低耦合、一致性,咱们设计了一个页面框架。
如上图,左边的Activity是Android的系统页面控制器,右边的UIViewController是iOS的系统页面控制器,经过虚线链接比较,咱们发现两端的页面状态设计基本相同。
因此,咱们在设计本身的页面框架时沿用了这些系统页面状态,同时从命名上也保持一致,这样可让Android和iOS原生开发的同窗更容易理解和上手。
咱们吸收了双端各自的优势。好比,Android端页面有四种启动模式,可是iOS 端并无这些,咱们就把Android的四种启动模式运用到了iOS端;iOS端有Present特性,可是Android端没有,那么也把这种特性融合到Android端的页面框架中;最后,还有一些小设计,好比Android的onResult设计,也能够借鉴融合到iOS端。
此外,咱们还作了微应用,所谓微应用,首先是模块化,就是把大模块仓库大模块拆成一个个小的Bundle,除了实现模块化,还主要实现如下几个目标:
粒度:以业务为单位,以业务线为分组
编译:二进制级别的产物,可独立编译、出包时连接
依赖:松耦合,以“服务”为导向,不关心模块归属
而Native容器层面,要实现四个核心目标:路由管理、服务管理、UI生命期管理、微应用管理。
经过一年时间的Bundle化改造,高德地图单端App完成了300多个页面的建设,拆分了100多个Bundle。
从收益来看,总编译时间从原来的60分钟下降到了8分钟,合版周期从原来的3天降到1天,需求上线周期降到了1个月之内,线上质量和测试质量都获得了极大的提高,崩溃率从万分之八下降到十万分之八。
3、动态化
随着高德地图业务发展沿着扩品类、在垂直品类作精作细,景区、酒店、银行商铺、充电桩等个性化定制需求凸显,对前端展示提出了更高的要求,对“快速应变”要求也更高了。
实际上,在2015年,高德就开始作动态化。最先的时候业内就有React Native,团队作了技术调研,发现不能彻底知足业务上的须要,尤为是性能方面。最后咱们决定自研一套动态化技术。
具体来讲,就是经过一个核心C++引擎,把两端业务(Android、iOS)用一套JavaScript代码解决,实现双端归一,Android实现业务动态化发布。
架构层面,最下面是高德App核心的地图引擎,咱们在上面搭建了一套动态化应用引擎,经过C++来实现。应用引擎的做用是为了承上启下,上面承载动态化业务,下层完成地图引擎的直接打通。众所周知,GUI的核心是DOM树,因此应用引擎不但要实现和JavaScript引擎的整合,还要负责DOM树的核心逻辑计算。
其次,动态化的技术和前端Web技术一致:样式、布局。应用引擎负责完成样式的布局计算、DOM树Diff、事件生成。而GUI的绘制,经过Diff事件,交由原生的Android以及iOS去完成。这样,全部的GUI都是原生的组件。
在之上,咱们搭建了一套前端框架,前端框架采用当前前端响应式框架作,前端框架之上又搭建了一套前端的UI卡片库和UI组件库,让上层业务可以更高效的开发。
而对于一些经过动态化的技术没法实现,或者性能上存在卡点的功能,咱们就经过Native扩展能力来支撑,这样,完整的动态化的业务可以直接运行在Android以及iOS上。
JS去执行代码以后,前端框架会产生虚拟的DOM树,最后提交到C++引擎,造成C++的DOM树。C++引擎去完成布局、样式计算,Diff计算,将每一个节点的属性和坐标交给Android以及iOS,由Native来完成最终UI的渲染。
整体来讲,动态化的特色:首先是它与主流前端框架融合,充分融合了大前端的生态;第二,性能、扩展性较好。由于采用C++实现整个核心逻辑,静态和动态的语言绑定技术,可以保证地图引擎的能力可以直接透出到上层,或者从上层可以直接call底层的C++能力;第三,多端归一和动态化,充分利用Native优点,接近原生Native体验。
动态化技术改造完成以后,双端不一致的问题下降了90%,开发、测试成本下降30%,发版周期从T+30到T+0。
最后,总结下高德客户端及引擎技术架构演进的几个重要阶段:第一个阶段,经过在线&离线引擎的融合拉通,让高德最核心的导航能力提到提高;第二阶段,在客户端发展成为“巨型”APP,代码量发展到超大规模的时候,经过架构治理,知足业务快速增加的诉求,解决大规模业务体量下的架构合理性问题,消除架构瓶颈;第三个阶段经过动态化的技术,实现多端归一,以及动态发版能力,为业务发展提供更大的助力。