写点什么

高德客户端及引擎技术架构演进与思考

2019 年 11 月 19 日

高德客户端及引擎技术架构演进与思考

2019 杭州云栖大会上,高德地图技术团队向与会者分享了包括视觉与机器智能、路线规划、场景化/精细化定位、时空数据应用、亿级流量架构演进等多个出行技术领域的热门话题。现场火爆,听众反响强烈。我们把其中的优秀演讲内容整理成文并陆续发布在「高德技术」公众号上,本文为其中一篇。


2019 杭州云栖大会高德技术专场讲师系列:



阿里巴巴高级无线开发专家宋照春在高德技术专场做了题为《高德客户端及引擎技术架构演进与思考》的演讲,主要分享了高德地图客户端技术架构沿着「上漂下沉」、「模块化、Bundle 化」的思路演进所做的一系列架构升级中的经验和思考。


以下为宋照春演讲内容的简版实录


主要分享三个方面的内容:


  • 融合

  • 架构治理

  • 动态化


一、三管齐下 深度融合


高德最初有两个端,车机版的高德导航,手机版的高德地图,两个团队,一个是 2B,一个是 2C,分别是汽车业务和手机业务。当时在引擎/技术上,分为离线引擎和在线引擎,但两个团队之间交流比较少,各自有自己的研发、产品和测试,而作为一款端上的 APP,两块业务都需要有地图渲染、路线规划、导航以及定位等通用能力。从公司层面看,存在较大的重复建设,整体研发效率较低。



于是我们做了一件事:利用技术手段,打通端上引擎,打造一套能同时支撑多端的 APP 能力。具体到执行层面,先从 A 团队拉一部分人到 B 团队一起建设,建设完之后再从 B 团队拉到 A 团队。在同时支撑好主线业务发展的情况下,通过一年左右时间,完成了引擎上的融合,做到同时支撑手机、车机以及开放平台。



这样就从引擎的维度,实现了渲染、定位、规划和引导的统一。具体来说,我们的各大引擎有好多套代码,好几个开发团队,每个团队有各自的开发方式和开发环境(Linux,Windows,Mac OS)。各种开发环境,工程配置文件大量重复,修改非常繁琐。


为此,我们通过两种方法:


  1. 建立了一套构建系统Abtor,通过一个配置系统实现统一构建,能够同时支持多个子引擎,在构建集成效率上得到了很大的提升;

  2. 对基础库进行了整体重构,形成了一套涵盖了文件I/O、KV存储、多线程框架&异步框架、归档、基础容器等一系列标准能力的基础库,同时也做了引擎核心架构的统一。



二、架构治理


通过引擎的融合同时支持多端,在研发效率上实现比较大的收益。而通过技术的抓手来实现团队的融合,对公司发展而言,这其实是更大的收益,团队融合的意义在于人才拉通和复用,组织效率得到了较大提升。


随着高德业务的快速发展,业务上持续扩品类,需求量激增,高德地图从最初的驾车导航,到后来的步行、骑行、摩托车导航等等,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 个月以内,线上质量和测试质量都得到了极大的提升,崩溃率从万分之八降低到十万分之八。


三、动态化


随着高德地图业务发展沿着扩品类、在垂直品类做精做细,景区、酒店、银行商铺、充电桩等个性化定制需求凸显,对前端展现提出了更高的要求,对“快速应变”要求也更高了。


实际上,在 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,代码量发展到超大规模的时候,通过架构治理,满足业务快速增长的诉求,解决大规模业务体量下的架构合理性问题,消除架构瓶颈;第三个阶段通过动态化的技术,实现多端归一,以及动态发版能力,为业务发展提供更大的助力。


作者介绍


宋照春,阿里巴巴高级无线开发专家。


本文转载自公众号高德技术(ID:amap_tech)。


原文链接


https://mp.weixin.qq.com/s?__biz=Mzg4MzIwMDM5Ng==&mid=2247484387&idx=2&sn=fa5861004462f0c4486d9facb6cda690&chksm=cf4a5b00f83dd216af5268da64a4ded17714985000be65e13c67acf6f3613d20fc882d3e4125&scene=27#wechat_redirect


2019 年 11 月 19 日 08:001567

评论

发布
暂无评论
发现更多内容

在wildfly 21中搭建cluster集群

程序那些事

程序那些事 wildfly wildfly21 集群部署 集群架构

甲方日常 76

句子

工作 随笔杂谈 日常

二十多岁的年纪是怎么成功四面字节跳动,最终拿到offer的?

Java架构之路

Java 程序员 架构 面试 编程语言

姐夫半夜不睡觉,竟躲在厕所看这“57道Redis面试题”?

Java架构之路

Java 程序员 架构 面试 编程语言

GitHub标星力推!我掏空了各大搜索引擎,给你整理了188道Java面试题,满满干货记得收藏

Java架构之路

Java 程序员 架构 面试 编程语言

手把手教你写!2021年Android工作或更难找,最全的BAT大厂面试题整理

欢喜学安卓

android 程序员 面试 移动开发

软件测试必须掌握的http网络协议知识

测试人生路

软件测试

Spring Cloud 2020.0.0 正式发布,对开发者来说意味着什么?

阿里巴巴云原生

阿里云 容器 开发者 云原生 架构师

架构大作业一

Geek_michael

极客大学架构师训练营

LeetCode题解:剑指 Offer 40. 最小的k个数,快速排序,JavaScript,详细注释

Lee Chen

算法 LeetCode 前端进阶训练营

速来围观!阿里P8大牛写出的JDK源码剖析及大型网站技术架构与业务架构融合之道

Java架构之路

Java 程序员 架构 面试 编程语言

架构师训练营 - 大作业1

阿甘

与前端训练营的日子 --Week09

SamGe

学习

Demo分享丨看ModelArts与HiLens是如何让车自己跑起来的

华为云开发者社区

人工智能 智能车 hilens

支持 gRPC 长链接,深度解读 Nacos 2.0 架构设计及新模型

阿里巴巴云原生

云计算 阿里云 开源 微服务 云原生

SpringBoot,来实现MySQL读写分离技术

Java架构师迁哥

面试官:Android事件分发机制及设计思路,跳槽薪资翻倍

欢喜学安卓

android 程序员 面试 移动开发

云上可靠性测试:让我们一起给开发找点事儿

华为云开发者社区

安全 云服务 可靠性

K8S 资源可视化利器:Kubectl-Graph

郭旭东

Kubernetes Kubernetes Plugin

测开之函数进阶· 第4篇《匿名函数》

清菡

测试开发

架构师训练营 - 大作业 2

阿甘

Java岗四面字节跳动成功之前,我都刷了那些面试题以及做了那些准备!

Java架构之路

Java 程序员 架构 面试 编程语言

扫地阿姨看完都学会了!万字长文总结Android多进程,满满干货指导

欢喜学安卓

android 程序员 面试 移动开发

架构大作业二

Geek_michael

极客大学架构师训练营

突破2.8万美元关口,比特币为何“疯涨”? ​

CECBC区块链专委会

比特币 比特币数字货币

7. JDK拍了拍你:字符串拼接一定记得用MessageFormat#format

YourBatman

Spring Framework 类型转换 MessageFormat DateFormat

CAP 原理 <笔记>

raox

极客大学架构师训练营

JAVA并发编程原理与实战

Geek_53983e

原理 java 并发 实战

冰河又一MySQL力作出版(文末送书)!!

冰河

MySQL 高可用 高并发 高性能 MySQL架构

为移动应用产业开辟出海新航路,华为应用市场是如何“破冰”的?

脑极体

PostgreSQL 13 RPM中有哪些新功能?

PostgreSQLChina

数据库 postgresql 开源

2021年,算法还“香”吗?

2021年,算法还“香”吗?

高德客户端及引擎技术架构演进与思考-InfoQ