应用研发平台EMAS

应用研发平台EMAS 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 个人简介什么都没有

个人动态

应用研发平台EMAS 发布了文章 · 1月14日

开发更便捷 阿里云推出一站式应用研发平台 EMAS 2.0

1月13日,阿里云一站式应用研发平台EMAS 2.0正式发布,本次将全新发布包括Serverless、低代码开发平台Mobi、AI工具箱、业务组件等产品服务,同时推出面向中小微企业和开发者的免费套餐扶持计划。开发者可在云时代以更低成本、更便捷地完成应用的开发和维护。

低代码开发平台 Mobi

低代码开发平台Mobi是一站式可视化的应用研发平台,提供应用前后端的搭建、托管、运维服务,适用于H5、全平台小程序。帮助应用开发者跨越底层技术壁垒,聚焦于业务场景实现,大幅降低开发门槛和成本,提升开发效率和投入产出比。 以独立应用、独立资源占用的方式标准化输出。

低代码研发平台Mobi支持可视化应用搭建IDE、模型设计、物料管理、集成管理、模型版本管理、调试预览,以及应用运维环境管理、产物版本管理、日志记录、性能监控,同时还有数据监控看板、数据分析等产品功能。

小程序Serverless

小程序Serverless提供包括云函数、数据存储、文件存储等一整套后端服务。开发者通过API方式即可获取云函数、数据存储、文件存储、音视频、图像处理等服务,不需要关心服务器或底层运维设施,可以更专注于代码和业务本身。帮助企业快速、低成本地实现一云多端的业务战略。

EMAS 新能力

从服务开发者提高开发效能、应用质量,到更好的帮助客户实现业务增长、变现等核心诉求;近期还将推出视频点播/直播的音视频能力、云码广告的流量变现能力、AI工具箱(OCR)、号码认证平台服务等,尽请期待。

开发者扶持计划

阿里云此次还升级了开发者扶持计划,EMAS 2.0公共云版本将全面升级为订阅服务模式,面向广大开发者,提供免费的的开发者版,包括DevOps、平台服务、用户增长在内的相关板块的一系列免费服务支持。面向一定规模的企业,将提供企业版订阅服务,提供增值产品能力以及专属钉钉技术支持。EMAS 2.0的订阅模式将会更大规模地让利开发者,帮助大家开启云端技术,智造未来应用。

EMAS产品负责人杨镔表示,EMAS 2.0将全面利用云计算的服务模型优势,结合阿里巴巴经济体的多元能力沉淀,为开发者提供更完善的应用研发服务。并基于全新的六大核心技术理念(一云多端、云端一体、云原生、低代码、AI驱动、链接业务)进行此次升级。

  • 一云多端,Multiexperience

提供多样化用户体验,面向包括移动端、Web、小程序、PC、IoT、AR/VR等场景实现无缝、一致的数字用户旅程。

  • 云端一体,One-Stop

一站式提供端开发工具与后端应用构建和托管基础设施,企业仅需具备前端技术栈的专业人才即可低成本完成端到端应用开发。

  • 云原生,Cloud Native

通过DevOps,Serverless等云原生标准技术赋能端应用开发,实现高效率研发、自动化交付、低成本运维。

  • 低代码,Low Code

通过可视化应用搭建引擎实现低成本的应用开发和维护,为开发者提供Pro Code和Low Code两种应用研发引擎。

  • AI驱动,AI Driven

全面开放阿里巴巴智能AI算法能力,通过端SDK、API实现各种用户端场景下的快速集成以及端计算能力。

  • 链接业务,Linking Business

开放行业插件系统,提供包括零售、金融、本地生活、多媒体在内的多种业务能力。

截止到目前为止,EMAS已累积了近20w的开发者和企业用户,为数十万的APP的日常运营保驾护航。

了解更多EMAS产品 https://www.aliyun.com/product/emas

加入应用研发平台EMAS开发者交流群,钉钉群号:35248489

查看原文

赞 0 收藏 0 评论 0

应用研发平台EMAS 发布了文章 · 2020-12-22

App性能测试揭秘(Android篇)

阿里云 云原生应用研发平台EMAS 李嘉华(千瞬)

简介: 性能测试在移动测试领域一直是一个大难题,它最直观的表现是用户在前台使用 App 时的主观体验,然而决定体验优劣的背后,涉及到了许许多多的技术变迁。阅读此文,带你揭秘App性能测试。

前言

性能测试在移动测试领域一直是一个大难题,它最直观的表现是用户在前台使用 App 时的主观体验,然而决定体验优劣的背后,涉及到了许许多多的技术变迁。

  • 当我们习惯于诺基亚时,智能机出现了;当我们学会native开发时,hybrid来了;当各种 hybrid 框架下的巨型应用倾向成熟时,小程序出现在了我们眼前;紧接着直播、iot、ar、vr、人工智能,新的技术与应用场景正在以无法想象的速度向前发展。性能测试技术在快速变化的场景与开发技术面前,面临着巨大的挑战,当我们还在纠结如何测试 a 时,b 就已经出来了。
  • 性能测试本身,有发展日渐成熟的解决方案,如线上性能监控APM、线下性能采集工具;有基于各个应用场景衍生的测试技术,如压力测试、稳定性测试、功耗测试等;也有基于各项性能指标(内存、cpu、电量、流量)而来的各种专项测试能力。

我们致力于打造线上线下一体的性能解决方案,希望能够帮助开发者发现、定位与解决一系列移动端性能问题。本文将着重介绍 EMAS 性能测试平台的能力与规划,还是那句话:功能决定现在,性能决定未来

通常我们在采集 Android 设备性能数据时,都是通过 adb shell 获取各项系统数据,对采集效率、数据准确度等影响很大。阿里云移动测试做了大量技术优化创新,目前性能测试采集间隔为1s,并且同时做到了无侵入、低延迟、低功耗。

在介绍技术方案之前,这里将本文的方案(app_process)与 adb shell 的方案做一组简单的数据对比。

  • 采集的所有性能数据为:cpu、memory、fps、network
  • 开发环境: java + ddmlib
  • 测试电脑:MacBook Pro (Retina, 15-inch, Mid 2015) 上进行测试
  • 测试设备:OPPO R17/Android 8.0

image.png

尽管对比的样本数不多,且不同实现方式也会有些许差异,但基于 app_process 的性能采集方案依然有很明显的优势:

  • 性能数据误差更小。相比之下性能与精度的提升是显而易见的,在部分手机上app_process的cpu开销甚至低于1%;
  • 数据采集更及时、响应更快。由于 app_process 接口的高效性,我们在每一秒钟都会监控被测应用的 pid,实际上性能数据对 APP 重启等动作的响应是实时的;
  • 兼容性更好。ps、top等命令在不同的设备上可能存在数据格式上的差异,这类不同机型的适配问题在本文方案中是不存在的。

1. APP_PROCESS

在Android系统中,zygote 通过 fork()调用一个app_process进程作为App的载体,我们同样也可以通过app_process运行一个普通的 java 程序,这个java程序可以像 App 一样通过 binder 跨进程与 system_server 通信,实现并调用一些 Android 系统服务的接口,同时,通过app_process启动的程序拥有shell等同的权限,这样可以完成一些 app 无权限但是 adb 能够完成的命令。

通过下图我们简单理解一下 Android Binder 与本文的基本原理,更多细节可以自行搜索学习。通常来说,如果我们的 App 能够获取到一个 Manager(如 ActivityManager),那么 System_Server 中必然存在对应的 Service(如 ActivityManagerService),那么我们就可以通过 ActivityManagerProxy 与它通信。
image.png

2. 性能指标

目前 移动测试 性能测试平台支持采集的性能指标如下:
image.png

2.1 内存

指标说明

  • TotalPss: 应用实际占用物理内存
  • NativePss: native进程申请分配的物理内存
  • SwapPss: 动态内存交换区,zRAM 交换可通过压缩内存页面并将其放入动态分配的内存交换区来增加系统中的可用内存量。由于这是以牺牲 CPU 时间为代价来增加少量内存,所以 swapPss的异常变化可能对系统性能造成影响。(https://source.android.com/devices/tech/config/low-ram.html))

原理

通过adb shell dumpsys meminfo pid,我们可以获得如下内容

Applications Memory Usage (in Kilobytes):
Uptime: 543447125 Realtime: 543469686
** MEMINFO in pid 23178 [com.huawei.browser:sandboxed_process0:com.huawei.browser.sandbox.SandboxedProcessService0:6] **
                   Pss  Private  Private  SwapPss     Heap     Heap     Heap
                 Total    Dirty    Clean    Dirty     Size    Alloc     Free
                ------   ------   ------   ------   ------   ------   ------
  Native Heap       99       96        0     2028     6656     4327     2328
  Dalvik Heap        4        0        0      754     3078     1030     2048
 Dalvik Other        4        4        0      366
        Stack        8        8        0       26
    Other dev        4        0        4        0
     .so mmap      535        4        0      319
    .jar mmap      114        0        0        0
    .apk mmap        2        0        0        0
    .dex mmap      622        0        4     2617
    .oat mmap      409        0        0        0
    .art mmap      259       16        0     2183
   Other mmap       14        0        0        6
      Unknown       28       28        0      455
        TOTAL    10856      156        8     8754     9734     5357     4376
 App Summary
                       Pss(KB)
                        ------
           Java Heap:       16
         Native Heap:       96
                Code:        8
               Stack:        8
            Graphics:        0
       Private Other:       36
              System:    10692
               TOTAL:    10856       TOTAL SWAP PSS:     8754

在 Android 10 以下的设备中,我们可以通过activityManager.getProcessMemoryInfo(pids) 获取进程相关的内存信息,Android 10之后的系统对这个接口加了一些限制,数据更新时间为5分钟,需要直接调用meminfo service 来dump获取这部分内容。

2.2 CPU

指标说明

ProcessCpu:测试进程CPU使用率
SystemCpu:整机CPU使用率

原理

通过读取/proc/stat文件,我们可以看到下面的内容

cpu  2490696 175785 2873834 17973539 12823 680472 230184 0 0 0
cpu0 621631 33199 739364 12893642 10736 365458 86720 0 0 0
cpu1 623944 30576 688904 677748 609 145744 93230 0 0 0
cpu2 519768 33948 650022 685194 703 78117 23873 0 0 0
cpu3 499978 33082 547153 687802 650 81072 21360 0 0 0
cpu4 32586 4853 41910 774975 36 2097 1025 0 0 0
cpu5 30950 5003 40730 776693 19 2060 999 0 0 0
cpu6 99227 22708 109219 722048 23 3970 2140 0 0 0
cpu7 62610 12414 56531 755434 44 1952 836 0 0 0
intr 209333749 0 0 0 0 35952688 0 11796562 7 5 5 17537 80 2431 0 0 0 1069962 0 35 1334360 0 0 0 0 0 11 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 34984538 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 505 50695 1174791 345 0 0 0 11301652 24660 0 111 0 0 0 0 0 0 0 0 0 0 0 86153 54 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1099230 0 18 1814 0 0 23 514624 1300943 248469 0 0 0 0 0 97168 60709 1641967 609754 38618 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 519 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1556 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 3548401 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 18 0 0 163911 192365 0 0 0 0 1018 0 1 0 2 0 2 0 2 1 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 56891 4227 147 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 751521 0 0 200 0 0 0 0 0 0 0 0 0 0 0 0 0 27 26 26 0 34 50 330 34 0 0 0 0 0 0 0 0 1223 0 11 0 0 0 26

对于上述cpu数据来说,每行CPU的数字依次表示

user (14624) 从系统启动开始累计到当前时刻,处于用户态的运行时间 
nice (771) 从系统启动开始累计到当前时刻 system (8484) 从系统启动开始累计到当前时刻,处于核心态的运行时间 
idle (283052) 从系统启动开始累计到当前时刻,除IO等待时间以外的其它等待时间 
iowait (0) 从系统启动开始累计到当前时刻,IO等待时间 irq (0) 从系统启动开始累计到当前时刻,硬中断时间
softirq (62) 从系统启动开始累计到当前时刻,软中断时间
  • 我们可以得到 cpu 运行时长为 cpu = user + nice + system + iowait + irq + softirq,而总时长为 cpu_total = cpu + idle
  • 由于我们的采集间隔几乎等于1s,于是过去1s的设备整体 cpu 使用率为 (cpu - cpu_pre) / (cpu_total - cpu_total_pre)

通过读取/proc/pid/stat文件,我们可以看到下面的内容

6873 (a.out) R 6723 6873 6723 34819 6873 8388608 77 0 0 0 41958 31 0 0 25 0 3 0 5882654 1409024 56 4294967295 134512640 134513720 3215579040 0 2097798 0 0 0 0 0 0 0 17 0 0 0

这里数据较多,依次表示

pid=6873 进程(包括轻量级进程,即线程)号
comm=a.out 应用程序或命令的名字
task_state=R 任务的状态,R:runnign, S:sleeping (TASK_INTERRUPTIBLE), D:disk sleep (TASK_UNINTERRUPTIBLE), T: stopped, T:tracing stop,Z:zombie, X:dead
ppid=6723 父进程ID
pgid=6873 线程组号
sid=6723 c该任务所在的会话组ID
tty_nr=34819(pts/3) 该任务的tty终端的设备号,INT(34817/256)=主设备号,(34817-主设备号)=次设备号
tty_pgrp=6873 终端的进程组号,当前运行在该任务所在终端的前台任务(包括shell 应用程序)的PID。
task->flags=8388608 进程标志位,查看该任务的特性
min_flt=77 该任务不需要从硬盘拷数据而发生的缺页(次缺页)的次数
cmin_flt=0 累计的该任务的所有的waited-for进程曾经发生的次缺页的次数目
maj_flt=0 该任务需要从硬盘拷数据而发生的缺页(主缺页)的次数
cmaj_flt=0 累计的该任务的所有的waited-for进程曾经发生的主缺页的次数目
utime=41958 该任务在用户态运行的时间,单位为jiffies
stime=31 该任务在核心态运行的时间,单位为jiffies
cutime=0 累计的该任务的所有的waited-for进程曾经在用户态运行的时间,单位为jiffies
cstime=0 累计的该任务的所有的waited-for进程曾经在核心态运行的时间,单位为jiffies
priority=25 任务的动态优先级
nice=0 任务的静态优先级
num_threads=3 该任务所在的线程组里线程的个数
it_real_value=0 由于计时间隔导致的下一个 SIGALRM 发送进程的时延,以 jiffy 为单位.
start_time=5882654 该任务启动的时间,单位为jiffies
vsize=1409024(page) 该任务的虚拟地址空间大小
rss=56(page) 该任务当前驻留物理地址空间的大小
Number of pages the process has in real memory,minu 3 for administrative purpose.
这些页可能用于代码,数据和栈。
rlim=4294967295(bytes) 该任务能驻留物理地址空间的最大值
start_code=134512640 该任务在虚拟地址空间的代码段的起始地址
end_code=134513720 该任务在虚拟地址空间的代码段的结束地址
start_stack=3215579040 该任务在虚拟地址空间的栈的结束地址
kstkesp=0 esp(32 位堆栈指针) 的当前值, 与在进程的内核堆栈页得到的一致.
kstkeip=2097798 指向将要执行的指令的指针, EIP(32 位指令指针)的当前值.
pendingsig=0 待处理信号的位图,记录发送给进程的普通信号
block_sig=0 阻塞信号的位图
sigign=0 忽略的信号的位图
sigcatch=082985 被俘获的信号的位图
wchan=0 如果该进程是睡眠状态,该值给出调度的调用点
nswap 被swapped的页数,当前没用
cnswap 所有子进程被swapped的页数的和,当前没用
exit_signal=17 该进程结束时,向父进程所发送的信号
task_cpu(task)=0 运行在哪个CPU上
task_rt_priority=0 实时进程的相对优先级别
task_policy=0 进程的调度策略,0=非实时进程,1=FIFO实时进程;2=RR实时进程

通过app_process更优雅

实际上我们并不确定上述数据格式在不同的系统版本或者机型上是否存在兼容性,这也是潜在的风险。
而通过 app_process 我们可以直接反射调用Process的 readProcFile 接口,很容易获得 utime 与 stime,这样就完全消除了兼容性问题风险。

  • 由于我们的采集间隔为1s,可以计算进程cpu使用率为 ((utime + stime) - (utime_pre + stime_pre)) / (cpu_total - cpu_total_pre)

接口调用伪代码如下

Method readProcFile = android.os.Process.class.getMethod("readProcFile", String.class, int[].class, String[].class, long[].class, float[].class);
readProcFile.setAccessible(true);
readProcFile.invoke(null, statFile, PROCESS_STATS_FORMAT, null, statsData, null);
readProcFile.invoke(null, "/proc/stat", SYSTEM_CPU_FORMAT, null, sysCpu, null);

2.3 流量

指标说明

recv:被测应用的下行流量
send:被测应用的上行流量

原理

通过读取 /proc/pid/net/dev 文件(低版本直接使用接口TrafficStats.getUidRxBytes()),我们可以获得如下数据,其中wlan0表示wifi流量,rmnet0表示sim卡流量

解析/proc/%d/net/dev示例结果
Inter-|   Receive                                                |  Transmit
face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
rmnet4:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet_tun03:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet_r_ims01:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet_tun02:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
dummy0:       0       0    0    0    0     0          0         0     1610      23    0    0    0     0       0          0
rmnet2:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet_tun11:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet_ims00:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet_tun10:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet_emc0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet_tun13:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet_tun00:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet_tun04:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet5:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
wlan0: 1241518561  840807    0    0    0     0          0         7  7225770   73525    0    6    0     0       0          0
rmnet_r_ims00:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet3:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet_tun01:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
sit0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet_tun14:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
ip_vti0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
ip6tnl0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet1:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
ip6_vti0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet_r_ims11:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet_r_ims10:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet6:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
rmnet_tun12:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
lo: 3796620     292    0    0    0     0          0         0  3796620     292    0    0    0     0       0          0
rmnet_ims10:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0

2.4 流畅度

指标说明

fps:用户可见的每秒显示帧数
jank:卡顿发生次数

FPS 原理

关于 fps 的统计存在很多个版本,基于不同方案统计的 fps 其含义完全不一样。
这里主要讲讲 移动测试 在 fps 上的选择与方案:

Choreographer

Choreographer 需要在 App 中实现,常见于 APM 等性能监控方案上,简单介绍一下原理:

  1. Vsync 信号一般来说由硬件产生,负责产生硬件 Vsync 的是 HWC;
  2. DispSync 将 Vsync 生成VSYNC_APP 和 VSYNC_SF 信号,之后由 Choreographer 和 SurfaceFlinger 使用;
  3. SurfaceFlinger 收到 VSYNC_SF 信号,开始第 N-1 帧的合成与绘制;
  4. App 收到 VSYNC_APP 信号,开始第 N 帧渲染;

由于大部分设备都是60HZ的刷新频率,所以VSYNC信号的周期通常是16.6ms,这个信号周期的长短可以很直观的反映应用代码实现的性能。但如果App处于“静止”状态,VSYNC信号依然会持续产生,这时GPU绘制可能并未实际发生,这个统计值通常高于我们视觉看到的帧数。fps 的定义为“每秒显示帧数”或“赫兹”,一般来说FPS用于描述影片、电子绘图或游戏每秒播放多少帧。

所以我更加倾向于Choreographer采集的VSYNC信号是一个流畅度指标(SM),而非真实FPS。

SurfaceFlinger

SurfaceFlinger 接受来自多个数据源的数据缓冲区数据,通过GPU合成并发送给显示设备。这是我们通常描述的 fps,也是客户真实可视可体验到的的帧数数据。

在安卓系统中,WindowManagerService 会对每一个 contentView 创建相关的UI载体Surface,SurfaceFlinger 主要负责将这个 Surface 渲染到手机屏幕上。

除了 Android 主窗口的焦点Activity 与相对应的 ContentView 之外,还存在一种特殊的 SurfaceView, 他会独享一个 Surface,这个 Surface 独立渲染非常高效,支持 OpenglES 渲染。也就是说可能会出现两类窗口fps。一个是Activity窗口帧率和SurfaceView窗口帧率。

一般来说,游戏、视频类应用都是通过这种 SurfaceView 来进行绘制,为了能够尽可能准确的获取被测应用的帧率,我们默认优先获取 SurfaceView 的 FPS。

如下是 优酷视频 我们能获取到的 Surface 如下:
image.png

然后,再通过dumpsys SurfaceFlinger --latency SurfaceView com.youku.phone/com.youku.ui.activity.DetailActivity 可以准确获取到视频窗口的帧绘制信息。

采用以上方法统计 fps 通常会有以下疑问:

  • SurfaceFlinger必须始终显示内容,所以当上层并没有新的缓存数据时,SurfaceFlinger会继续显示当前数据,因此通过这种方法统计出来的 fps 值一般较低,静态页面可能为0,这样的 fps 值是否具有迷惑性;
  • 比如上图的视频应用只有 25fps,我们滑动时可能都有 40+ fps,这个数据能说明什么样的问题;
  • fps 波动范围这么大,fps 值怎样才可以描述应用的流畅程度。

回答上面的问题,首先要需要重新定义 FPS != 流畅度。

这里引用苹果 WDDC2018 开发者大会的一个分享(https://developer.apple.com/videos/play/wwdc2018/612/))。左图试图以 60fps 运行程序,实际只能达到40fps,而右图实现了稳定的 30fps,右图的流畅度是明显要高于左图的,这种现象称为 Micro Stuttering。
image.gif

这里不再深究 Micro Stuttering 的产生原因,回到 FPS 本身,首先 FPS 并不是越高越好,也不是越低就越差。它反映的是一种视觉惯性现象,FPS 值应当是越稳定越好。正如前面优酷视频的例子中,FPS 基本稳定在25左右,同样的在各类视频应用中,我们发现 FPS 几乎都是稳定在 20+,这已经足够给我们带来良好的观看体验了。

视觉惯性

视觉预期帧率,用户潜意识里认为下帧也应该是当前帧率,比如我们玩游戏一直是60帧,用户潜意识里认为下帧也应该是60帧率。刷新一直是25帧,用户潜意识里认为下帧也应该是25帧率。但是如果60帧一下跳变为25帧,就会产生明显的卡顿感。

电影帧

电影帧率一般是24帧。电影帧单帧耗时为 1000ms/24≈41.67ms。电影帧率是一个临界点。低于这个帧率,人眼可以感觉出画面的不连续性。

JANK 原理

既然 fps 无法完整的描述应用的流畅度,那么是否可以有一个指标表示应用的流畅程度,换言之,能否描述应用的卡顿程度。答案是 jank。

理解 jank,就一定要理解 google 设计的三重缓存机制(如下)。三重缓存指的是A、B、C三个缓存结构,当 GPU 未能在一次 VSync 时间内完成B的处理,此时display、gpu、cpu 同时在处理A、B、C三个缓存,实现资源最大化的利用。
image.png

我们可以通过 dumpsys gfxinfo packageName 获取到的 janky frames如下。这里的Janky frames是当一帧的时间大于16.67ms时,就计为一次 Janky frame。

从上文提到的三重缓存机制我们可以进行分析,B先导致了一次视觉上的jank,C理论上也是jank(跨VSync),但是由于此时屏幕上显示的是B,C虽然delay了一帧,但是 C 看起来仍然是紧跟着B显示在屏幕上,而且 A 顺利的在16.67ms完成了绘制,实际上用户视觉上只少看了一帧,而Janky frames 是 2。我们发现,当 Janky frames 高达近 40% 甚至 50% 时,我们依然感受不到卡顿,这个值并不是理想中的反映流畅度的指标。

Applications Graphics Acceleration Info:
Uptime: 171070276 Realtime: 962775383
** Graphics info for pid 13422 [com.zhongduomei.rrmj.society] **
Stats since: 152741070392878ns
Total frames rendered: 110
Janky frames: 7 (6.36%)
50th percentile: 9ms
90th percentile: 13ms
95th percentile: 18ms
99th percentile: 36ms
Number Missed Vsync: 2
Number High input latency: 0
Number Slow UI thread: 6
Number Slow bitmap uploads: 3
Number Slow issue draw commands: 0

基于以上考虑,我们重新定义 jank 的计算方式:

  • 视觉连续性问题:帧时长 > 前三帧平均时长*2
  • 卡顿问题:帧时长 > 电影帧时长 * 2

假设应用按照电影帧 41.67ms 运行,若帧时长大于 2*41.67ms,意味着在缓存机制下,依然必现一次卡顿问题。

3. 其它接口

通过app_process,我们还能够完成很多其它有趣的事情。

  • 获得已安装应用列表。通过 android.content.pm.PackageManager,我们可以获得所有已安装应用,同时获得所有应用的图标,也可以提前获得应用程序的所有Service,目前小程序大多使用 Service 层来做逻辑处理、数据请求以及接口调用,提前确认要测试的 Service 可以更加精确的完成小程序测试;
  • 获得更多的设备硬件信息,如gpu信息等等;
  • 获取设备视音频流;
  • 部分实现静默安装等。
查看原文

赞 0 收藏 0 评论 0

应用研发平台EMAS 发布了文章 · 2020-12-16

EMAS远程日志 - 移动端问题排查利器

简介: 远程日志是什么?具体做了哪些事情?内部是怎么实现的?本文将从 功能、架构、体验优化三个方面来介绍一下远程日志发展过程及展望。

阿里云 云原生应用研发平台EMAS 张月(此间)

前言

当 App 发布到用户手里之后,开发者对 App 运行状态的感知就只能通过各类业务和稳定性监控了。这些监控平台会把线上问题(如崩溃堆栈、异常网络请求等)及业务数据采集到服务端,然后给用户提供聚合 Metrics 等 BI 数据。但这个过程很容易丢失细节,不能直观反映问题发生原因,导致线上问题很难排查分析。

可能聪明的你会想,我把所有的日志都上报到后端不就行了?但是这样会给 App 带来很多无意义的网络消耗,也会造成比较大的网络和存储的压力。阿里云远程日志( https://www.aliyun.com/product/emascrash/tlog )在这个场景下应运而生,通过将日志存放 App 本地,需要时拉取的方式,在牺牲了一点实时性的情况下,解决了上报日志费流量存储,不上报日志没办法查问题的困境。

远程日志具体在里面做了哪些事情?内部又是怎么实现的?接下来我就会从 功能、架构、体验优化 三个方面来介绍一下远程日志发展过程,最后再聊聊我们的展望。

功能

如前言介绍的一样,我们会把日志先存在 App 本地,当需要的时候再拉取上来做分析查看。整个过程可以简单拆解成如下几步:
image.png

移动端特性

  • C层面实现:性能提升,一份代码多端支持
  • 加密存储:使用非对称加密方式,日志存储上报更安全
  • 日志轮转:最长支持7天日志存储,每天最大存储 10M
  • MMAP机制:避免缓存日志丢失,提升性能 (注:MMAP 机制是将文件直接映射成内存的操作,避免页缓存到文件的拷贝,详情可移步:https://www.cnblogs.com/huxiao-tee/p/4660352.html )

后端特性

远程日志的定位是异步拉取,把问题日志从移动设备端拉回来分析。结合不同使用场景,用户对设备精准度、拉取及时性、拉取成功率等不同侧重的特点,我们在拉取模式和产品联动上做了不同的实践。

拉取模式

精准拉取:指定设备列表

举个例子,一个风和日丽的上午,你刚到公司,发现老板满脸不爽的告诉你昨天晚上他 App 崩溃了。那摆在眼前就是两条路,要么搞定这个问题,要么“提桶跑路”。这个时候远程日志出场了,你可以熟练的输入老板的设备Id,做一次日志拉取,查查老板 App 的日志定位原因,解决问题。
image.png

这个模式下,用户使用面临了两个体验问题:

  • 拉取速度慢。下发拉取任务后,需要终端用户重新打开App才能完成日志上传,但这个时间很不可控。
  • 拉取成功率低。下发拉取任务会有部分设备inactive,导致没办法接受拉取指令,导致日志无法上传。

针对这个问题,我们在拉取上做了相关的优化,实现了智能筛选的功能。

智能筛选:指定筛选条件

用户不需要指定目标设备列表,而是关心某个或几个维度下的设备详细日志。那用户可以设定拉取的设备组合条件,系统自动帮用户选取设备。

为了加快设备拉取速度以及拉取成功率,远程日志在选取设备增加了如下策略:

  • 自动筛选最近启动的设备拉取。
  • 自动调整筛选出的设备池,扩大拉取规模,最多扩大到原始规模的8倍等。
    image.png

联动崩溃数据

在端上问题发生的场景中,大多数是因为崩溃或者异常行为。为了给与对这种场景支撑,我们提供了崩溃分析数据联动的支持,打破了「崩溃分析」 和「远程日志」两个产品之间的数据孤岛,提供了问题排查的更多的可能性。

数据联动:崩溃设备列表

通过崩溃分析提供崩溃设备列表,可以帮远程日志直接划定待拉取设备范围,用户更加省力,通过 EMAS 「崩溃分析」中的列表页一键跳转拉取。
image.png

这个方式极大简化了用户在排查崩溃相关问题时选定设备列表的工作,但对于每个崩溃问题还是需要创建拉取日志任务。这个拉取过程还是存在一个时间上的迟滞感,这不仅会打断工程师的排查思路,也会消磨排查问题的积极性。我们能否免除拉取动作,直接把崩溃问题对应的设备日志准备好呢?「智能拉取」就是为了解决这个场景的问题。

智能拉取:提前拉取

我们加深了前面的数据联动,对于首现和 Top 崩溃问题,每天7点定时创建任务,开发同学上班的时候基本上都已经拉取成功了,极大的提升了开发同学的问题排查效率。
image.png

架构

image.png

体验优化

除了在内功上打磨,产品的使用体验上我们也做了相当多的优化,也和大家分享一下。

  • 任务消息通知,让你能够第一时间感知日志上报
  • 整合任务详情与日志详情页面,查看任务日志更方便
  • 完善任务、设备、日志查询筛选
  • 任务时间线透出,感知任务生命周期
  • 顶部菜单栏变侧边栏,控制台与EMAS风格统一
  • 拉取任务持久化,容错性更好。
    image.png

image.png

到此,远程日志的现有的功能、架构和体验介绍就此结束了,接下来说说我们对未来的规划。

展望

增加上报形式

目前都是通过服务端下发任务,端上接受任务上报这种「被动上报」的模式,有一定的局限性,我们接下来希望对客户端在某些情况下「主动上报」日志,比如连续Crash,或者用户在App内反馈问题时上报做相应的支持。

丰富采集数据

现在我们的日志打印仅限于用户日志,还需要支持更多的无痕埋点,记录用户操作路径和网络IO等操作,让日志数据更丰富,能够通过日志复现用户操作流水,机器状态的变化。

更多产品联动

「崩溃分析」是我们产品联动的第一站,除了崩溃和异常,对品质有追求的App开发者也越发重视性能问题,毕竟「功能决定现在,性能决定未来」,后续我们也会思考和如何将「性能分析」产品和远程日志打通,更好的服务我们的用户。

移动研发平台 EMAS

阿里巴巴应用研发平台 EMAS 是国内领先的云原生应用研发平台(移动App、H5应用、小程序、Web应用等),基于广泛的云原生技术(Backend as a Service、Serverless、DevOps、低代码等),致力于为企业、开发者提供一站式的应用研发管理服务,涵盖开发、测试、运维、运营等应用全生命周期。
欢迎大家移步使用:https://cn.aliyun.com/product/emas

查看原文

赞 0 收藏 0 评论 0

应用研发平台EMAS 发布了文章 · 2020-12-11

云上的移动性能测试平台

1. 功能决定现在,性能决定未来

性能测试在移动测试领域一直是一个大难题,它最直观的表现是用户在前台使用 App 时的主观体验,然而决定体验优劣的背后,涉及到了许许多多的技术变迁。

  • 当我们习惯于诺基亚时,智能机出现了;当我们学会native开发时,hybrid来了;当各种 hybrid 框架下的巨型应用倾向成熟时,小程序出现在了我们眼前;紧接着直播、iot、ar、vr、人工智能,新的技术与应用场景正在以无法想象的速度向前发展。性能测试技术在快速变化的场景与开发技术面前,面临着巨大的挑战,当我们还在纠结如何测试 a 时,b 就已经出来了。
  • 性能测试本身,有发展日渐成熟的解决方案,如线上性能监控APM、线下性能采集工具;有基于各个应用场景衍生的测试技术,如压力测试、稳定性测试、功耗测试等;也有基于各项性能指标(内存、cpu、电量、流量)而来的各种专项测试能力。

我们致力于打造线上线下一体的性能解决方案,希望能够帮助开发者发现、定位与解决一系列移动端性能问题。本文将着重介绍 EMAS 性能测试平台的能力与规划,还是那句话,功能决定现在,性能决定未来。

2、云上的性能测试工具

通常我们在进行专项测试(内存、cpu、电量、流量等)时,需要准备测试机型、测试包、测试环境、测试数据,会遇到以下问题:

  • 机型样本数不够多。
  • debug包不一定真实反应生产包的性能,但Android Studio需要debug包才能测试。
  • Android/iOS 测试环境的搭建与跨平台困难。
  • 大量测试数据整理分析。

以上这些问题很容易导致整个测试效率的低下,甚至无法实施落地。
image.png

基于EMAS云真机的调试能力,MQC在云上提供了更加完美便捷的性能测试工具。

云真机天然提供多达600+款测试机型,支持调试测试所有已安装应用,不依赖任何本地环境配置,测试数据一键上传统计。

同时,EMAS性能测试工具有以下特点:

  • 基于 app_process 与 instruments 协议实现的移动双端、跨平台性能采集;
  • 无侵入、短间隔(采集间隔稳定1s),低延迟(性能数据延迟小于100ms)、低功耗(对设备性能影响低于1%);
  • 应用+进程的测试方案,满足hybrid、小程序的测试需求。
    image.png

image.png

  1. 云上数据看板

==========

性能数据的意义在于它将我们常见的各种问题通过技术的手段进行度量与量化,可以帮助我们在产品功能上线前,尽可能的发现潜在的性能问题和风险。MQC性能测试平台将存储于云上的数据,以尽可能多的维度可视化给用户,把好版本发布前的关口。

3.1 任务

用户使用云真机进行的每一次测试任务与性能数据,都会直接保存成测试任务,方便再次查看与确认历史数据。
image.png

3.2 用例

在实际的测试过程中,我们很容易发现,不同应用场景的性能数据是完全没有可比性的,在统计方法上只看性能数据的平均值也很难直接给出定性和定量的判断,没办法影响开发、产品的决策。

即便看似相同的场景,不同的产品决策也可能带来很大的性能数据差距:比如大多数云盘的相册基于流量与性能的考虑,显示的都是压缩后的图片;而我们的本地的一些相册软件,显示的基本都是原图,这样产品上的选择便导致了内存开销上巨大的差异。

数据看板在最初设计的时候就吸取了功能自动化用例平台时的建设经验,将每一次性能测试任务分用例存储,并且按照不同的用例维度对性能数据进行统计。在 EMAS 移动测试 控制台,不同子账号查看和管理相同的app与用例,满足多用户云端协作的需求。

3.3 多维度聚合

在用例维度的基础上,MQC 性能测试平台提供了多个维度的数据统计、聚合与分析能力。

• 设备分级

根据设备硬件性能打分,划分为高、中、低三个级别。
由于不同等级机型对 APP 实际性能指标的影响较大,这个因子可以较大程度减少硬件性能对指标置信度的影响。

• 应用版本

对于性能指标来说,通常有三种问题判断标准:

  • 基于行业技术经验定义的基线指标,这通常是技术决策者基于用户体验、性能要求、大数据分析给开发提出的底线标准;
  • 同行业 APP 性能指标横向对比,学习行业内优秀的技术实现一直是互联网快速发展的重要原因之一;
  • 同 APP 不同版本间的纵向对比,快速的发现新版本的优化效果,新功能对 APP 的影响等。
    image.png

• 指标分布

指标分布可以帮助开发者快速判断指标区间,定位可能的异常任务与异常指标区间,更加有针对性的去查阅任务报告。
image.png

4、未来规划

• 丰富指标:我们将继续完善更多性能指标的采集方案,如电量、GPU、温度等;
• 行业指标:MQC 将基于云上开发者数据、专家测试数据,整理并统计各个行业性能指标作为参考分享出来;
• 性能基线:上文提到,通常性能指标的观察标准有三,同行业APP性能指标;同APP不同版本性能指标;基于技术方案与行业数据的性能标准。性能基线的定义可以更好的约束开发者对极致性能体验的追求,最大可能降低性能问题出现的概率,如OOM、ANR问题。

最后附上演示视频,请点击下方链接查看
https://developer.aliyun.com/live/245866

查看原文

赞 0 收藏 0 评论 0

应用研发平台EMAS 发布了文章 · 2020-11-27

EMAS 移动 DevOps 解决方案 —— Mobile DevOps

阿里云 云原生应用研发平台EMAS 彭钊(州牧)

简介: DevOps这一优秀的软件交付理念在服务端已经有很多相关的实践,那么是否也可以应用到移动端进行交付呢?基于移动端和服务端场景的差异,移动DevOps跟服务端DevOps又有哪些不同和挑战?本文分享阿里云云原生应用研发平台EMAS在建设云原生Mobile DevOps过程中的思考、遇到的挑战以及解法,解密其设计架构和技术细节。

一、Mobile DevOps 介绍

  1. 什么是移动 DevOps

1)大家所熟知的DevOps

在2020年这个时间节点上,DevOps已经不再是什么新鲜概念,相信大家或多或少都有些自己的理解,但当要我们去准确描述什么是DevOps时,好像又很难讲的清楚。实际上DevOps至今业界也没有可以让大家一致认可的定义,之所以很难被准确定义,是因为DevOps其实是一种理念甚至是一组理念的集合,很难被具象化。“DevOps”这个词本身从字面可以理解为软件从Dev(Development,开发)到Ops(Operations,运营)的全生命周期,但DevOps的准确定义到底是什么?在众多的DevOps定义中,个人认为Azure DevOps的定义[1]较为精确和具体:

DevOps 是开发 (Dev) 和运营 (Ops) 的复合词,它将人、流程和技术结合起来,不断地为客户提供价值。
DevOps 对团队意味着什么?DevOps 使以前孤立的角色(开发、IT 运营、质量工程和安全)可以协调和协作,以生产更好、更可靠的产品。

通过采用 DevOps 文化、做法和工具,团队能够更好地响应客户需求,增强对所构建应用程序的信心,更快地实现业务目标。

这个定义里有几个关键信息总结一下:
① 人、流程、技术的结合
② DevOps使让以前孤立的角色可以协调和协作
③ DevOps是一种理念,既要树立文化,也要有自动化工具的支持
④ 目的是更快的生产更好、更可靠的产品

2)从DevOps到移动DevOps

对于DevOps大家平时讨论比较多的其实是服务端DevOps,既然DevOps是一种优秀的软件交付理念,为什么不把DevOps也应用到移动端交付呢?这也就是我们今天要介绍的移动DevOps。
因为移动端和服务端场景的差异,移动DevOps跟服务端DevOps会有很大的不同。主要体现在以下几个方面:

移动端应用自动化构建更为复杂

• 构建环境碎片化

Android、iOS两个平台需要基于不同的操作系统和构建工具链搭建构建环境,即便是同一平台构建工具链也存在版本碎片化现象,比如Android构建依赖的Android SDK、Gradle需要多个版本同时支持,iOS构建依赖的Xcode、Ruby版本需要多个版本同时支持

• 移动端构建涉及到证书托管等数据安全问题
• iOS构建依赖的Mac设备为机房非标设备

Mac设备不属于标准服务器无法部署在标准机房,通常需要自建Mac机房,对于可运维性和稳定性也是一个挑战。

自动化构建是DevOps中必不可少的能力,这就要求移动DevOps通过技术手段很好的解决上述客户端自动化构建、一键出包的问题。

移动端碎片化严重,应用交付兼容性是巨大的挑战

不同于服务端部署环境的一致性,移动端应用运行环境碎片化非常严重,兼容性测试覆盖难度远大于服务端。移动端碎片化现象以Android系统尤为严重,主要体现在以下几个方面:

• 手机机型碎片化

Android市场有众多的手机厂商和茫茫多的机型,不同厂商都会对系统做底层“优化”,理论上任何覆盖不到的机型测试都可能会面临兼容性问题,下图是2020.10月份最新的百度统计流量研究院[2]的Android Top机型分布,Top 10的机型市场占用率都不足15%,可见机型碎片化之严重
image.png

• 操作系统版本碎片化

操作系统的差异对应用运行的影响更为直接,系统大版本升级导致应用不兼容的情况屡见不鲜,每次操作系统大版本发布都是对应用兼容性的一次考验;在考虑兼容新系统的同时,还不能放弃老系统的用户。
下图是2020.10月份最新的百度流量研究院的Android版本分布数据,可以看到已经发布一年多的Android 10.0,市场占用率还不足50%,2年以前的操作系统依然占主流
image.png

由于端设备的碎片化问题,就需要移动DevOps具备移动测试能力,自动化完成大量的真机兼容性测试。

移动端应用发布更新周期长

应用新版本可能发布2周更新比例都不会超过50%,不像服务端可以在很短的时间内完成所有服务器的软件发布。发布周期长意味着犯错成本更高,一个有Bug的版本发出去,可能需要很长的时间才能通过更新升级消化完。

这就需要移动DevOps一方面具备完善的灰度发布机制,避免将有问题的应用一次性发布到用户侧;另一方面一旦有Bug的版本已经发出,需要移动DevOps具备热修复能力,可以通过增量补丁包的发布方式更轻量、快速的修复Bug。

移动应用运行在海量移动端设备

不像服务端服务运行在特定的集群内,可以统一管控和运维,移动应用的运行环境在用户的手机上,而且对于手淘这类超级App来讲是亿级海量设备。

这就需要移动监控类产品通过大数据技术来实现移动端运维监控,甚至需要远程日志功能来拉取指定设备上的错误日志来定位排查错误。

基于以上几点,并参考DevOps对软件交付生命周期的定义,总结移动DevOps应用生命周期及各阶段能力要求如下:
image.png

  1. 什么是Mobile DevOps

1)Mobile DevOps 是EMAS移动DevOps理念的具象化实现

首先介绍一下EMAS(Enterprise Mobile Application Studio),EMAS是来自阿里云的国内领先云原生应用研发平台(移动App、H5应用、小程序、Web应用等),基于广泛的云原生技术(Backend as a Service、Serverless、DevOps、低代码等),致力于为企业、开发者提供一站式的应用研发管理服务,涵盖开发、测试、运维、运营等应用全生命周期。更多关于EMAS的介绍详见阿里云官网EMAS详情页
Mobile DevOps是EMAS移动DevOps理念的具象化产品输出,是EMAS的中轴型产品,它联动EMAS所有产品共同实现上述移动DevOps理念。Mobile DevOps将EMAS原本孤立在应用各个生命周期的产品像上图一样实现了联动和完整闭环,实现了EMAS从移动中间件平台向移动研发平台的升级。Mobile DevOps结合以下EMAS产品共同形成EMAS的移动DevOps:
研发域:Mobile DevOps
测试域:移动测试
发布域:Mobile DevOps
运维域:移动监控,移动热修复
运营域:移动推送,移动用户反馈

2)Mobile DevOps的历史

Mobile DevOps是集团内部移动研发平台的商业化输出版本,最早于2017年由阿里云和手淘团队一起研发出输出第一版专有云输出版本,2020年04月上线第一个公共云版本。
下面这张图是Mobile DevOps的发展史,可以说Mobile DevOps的发展史其实就是阿里集团移动研发技术发展史,是阿里巴巴近十年移动技术、工程研发理念沉淀。
image.png

3)Mobile DevOps的现状

专有云已初具规模
Mobile DevOps专有云主要面向大客户,尤其是正在做数字化转型的大客户,这部分客户对安全有很高的要求,基本只能接受专有云部署的模式,同时也愿意为提升研发效能投入成本。
2018年Mobile DevOps以专有云场景正式落地输出,目前已经为多个行业数十家大客户创造价值,赋能企业研发流程数字化转型。
公共云免费公测中
相对于专有云,Mobile DevOps公共云更多的是面向中小微企业,这部分客户对研发效能提升有诉求,但是又对价格敏感,公共云是很好的承接形式;同时阿里集团内部有些对外输出的业务(例如专属钉钉)无法基于集团内部研发平台去做移动DevOps的,Mobile DevOps公共云也是很好的选择。
Mobile DevOps公共云自2020.07开始正式对外免费公测,目前已服务以及众多中小微客户,以及阿里集团内部专属钉钉、政务钉钉、唱鸭等客户。

二、云原生的Mobile DevOps

相对于专有云,公共云场景下建设云原生形态的Mobile DevOps面临更多的技术挑战,本章会跟大家分享我们在建设云原生Mobile DevOps过程中的思考、遇到的挑战以及我们的解法。

  1. 为什么需要公共云的 Mobile DevOps

1)面向中小微客户提供普惠型Mobile DevOps服务

虽然专有云部署具有独享、内网安全隔离等优势,但专有云交付的高成本注定只有行业高端玩家才有能力接受。专有云Mobile DevOps成本投入评估如下:
• 一次性投入:百万级一性采购费用
• 持续投入:至少30 W/年服务器成本 + 20 W/年人力维护成本
基于上述成本计算,专有云第一年、第二年、第三年的的投入成本分别为:150W ,50W,50W 累计200W,这对于中小微客户是无法接受的。
阿里云作为新时代的基础设施,新时代的水电煤,有必要为更多大客户以外的中小微企业提供普惠型云服务。而公共云形态的Mobile DevOps恰好符合这样的理念,基于云原生弹性扩缩容、按量计费的优势,可以极大降低中小微客户使用Mobile DevOps的成本。同时公共云场景下针对中小微客户的特点提供更适合目标客户的DevOps研发流程。

2)联动EMAS产品线为开发者提供一站式移动研发平台

公共云Mobile DevOps的上线,可以有效联动EMAS现有移动测试、移动监控、移动热修复等产品,让EMAS覆盖应用全生命周期,完成EMAS从移动中间件到移动研发平台的升级,提升用户体验和粘性。
EMAS一站式移动研发平台较传统基于开源方案Jekins、Gitlab Runner等自建CI/CD平台,在成本、高可用性、技术支持力度等方面都有明显优势,而且可以一站式覆盖应用构建、测试、发布、运维、运营全生命周期管理,较传统自建CI/CD“烟囱式”的一个个独立开源系统,研发协同效率上也有明显优势。

  1. 公共云 Mobile DevOps面临的挑战

相比专有云内网部署、内部员工使用的场景,公共云形态下的Mobile DevOps会面临更多的技术挑战,主要体现在一下几个方面:

1)安全性

• 租户隔离
公共云面临的第一个问题就是租户隔离,不同客户既要同时使用共享资源,又不能互相看到对方的数据。对于构建这种场景,除了不同客户的构建任务可能会互相影响,构建环境还涉及到用户的代码、证书等私密信息,必须要有完善的方案保证用户构建环境的隔离
• 代码、证书、秘钥等私密数据安全
有构建就必然涉及用户代码、证书、秘钥,这些数据都是极其隐私的数据,公共云存储、传输、使用任何环节出问题都可能会导致用户重大损失。
• 外部攻击
公共云由于暴露在公网任何人都可以使用,还面临恶意黑客攻击的风险,尤其构建场景涉及大量的自定义执行命令,必须要有完善的机制防止黑客执行恶意自定义命令在构建环境内留下后门。

2)高可用性

• 必须支持弹性扩缩容
公共云业务规模增长时,需要业务要能快速扩缩容适应业务增长,否则就会导致服务异常。这就要求云产品在技术实现上符合分布式的架构,尤其是构建集群要支持无状态快速扩容。
• 构建环境的稳定性
构建环境要稳定,避免因攻击或异常使用导致的构建环境被破坏的情况,比如环境变量、构建工具链等。
• 高标准的SLA,实时在线,永不宕机
高标准SLA既是对客户的承诺,也是对阿里云品牌的敬畏。

3)可扩展性

• 应用架构多样化导致的构建流程差异大
专有云客户数量有限,而且有完善的KA客户技术支持服务,所以应用的差异有限且有专人支持接入。但公共云环境下客户众多,应用架构多样性对系统的通用性、扩展性提出了更高的要求。
• 研发流程多样化
公共云不同客户研发团队规模、研发文化、研发流程都有差异,也对Mobile DevOps研发流程扩展性提出了更高的要求。

  1. 我们的解法

针对以上公共云Mobile DevOps面临的挑战,我们从以下两个方面通过技术手段去解决:

1)基于流水线的通用构建架构

流水线架构将构建做到通用化,基于流水线自定义编排构建流程,基于任务插件扩展流水线业务能力,很好的解决了上述的可扩展性问题。此架构具有以下特色:
• 通用构建架构,支持全平台构建能力
• 基于YAML自定义编排构建流程
• 流水线可视化编排
• 流水线支持任务插件无限扩展

2)基于容器化/虚拟化构建集群

使用容器化(Linux)/虚拟化(Mac Os)方案可以彻底解决各种因资源共享带来的安全性和稳定性问题,每个构建任务起全新的容器/虚拟机运行,构建任务完成后容器/虚拟机立即被销毁,不仅可以有效隔离任务间运行环境,构建环境也“常用常新”,可以有效避免构建环境被破坏的问题;另外搭建稳定的无状态 容器化/虚拟化 构建集群,可以保证构建服务的高可用性。
下面第三、四章节,我们会对这两个点分别展开详述,解密其设计架构和技术细节。

三、基于流水线的通用构建架构

  1. 技术预研

业界基于流水线设计的友商产品其实并不少,尤其是国外同类产品较多,比如 Azure DevOps PipelineGithub Actions 两款优秀的流水线产品,这两款产品在功能丰富度、易用性、文档、用户规模几个方面综合考虑较其他产品具有不少优势。
Azure DevOps前身是Visual Studio Team Services(VSTS),是一款已经有十几年历史的软件研发协作平台了,其Azure Pipeline产品在2018年4月发布[3];Github Actions产品在2019年8月发布[4],是微软收购Github后发布的一个重量级产品。总体来说两者都属于比较新的平台,Azure Pipeline也不过2年多的时间。
预研中发现一个有意思的现象,由于Github已经是微软子公司,两个流水线产品不仅设计概念上相似,技术预研中发现二者的Mac虚拟化方案也是彼此技术共享的,甚至Mac虚拟化集群机房也是共享的。差异上Github Actions相对Azure Pipeline更为精简优雅一些,另外Github Actions依旧延续Github开源的风格,其流水线插件都是开源的,虽然上线仅1年多,已经有5000+开源插件。从插件的角度这是一座金矿,如果这批插件都能直接在Mobile DevOps用起来,基本流水线的功能插件就跟开源社区对齐了。考虑到未来支持这批开源插件的可能性,最终Mobile DevOps设计架构上也更加拥抱开源社区的Github Actions。

  1. 流水线的核心概念

image.png

• Trigger
触发器,主动触发一次流水线执行
• Pipeline
流水线,被触发运行的最小单位。一个流水线可以包含1个或多个Job
• Job
Job是被调度的最小单位,按Job被调度到的执行环境不同可分为Agent(构建集群)和Agentless(服务端)两种Job;
多个Job之间有可以无依赖并行运行,也可以有依赖顺序执行。多个Job之前的关系可以用一张DAG图表示;
每个Job可以包含1个或多个Step
• Step
Step 是被执行的最小单位。每个Job由多个顺序执行的Step组成
• Task
Task是预定义规格和功能的任务插件,可以在Step中被声明引用执行,一个Step只包含一个Task

  1. 流水线的技术架构

image.png

流水线由以下几个核心系统组成:

1) Pipeline流程引擎

负责流水线的触发、编排、状态流转执行,以及流水线元数据信息维护。
流水线触发器模块
触发器模块负责触发一条流水线的执行,支持手动、定时器、事件(git event,webhook回调等)三种触发方式。触发器是流水线执行的唯一入口,在这一层可以做调用方的校验和检查,同时支持传入不同的触发参数控制流水线的执行和调度过程。
流水线编排模块
流水线编排定义了一套用于描述一条流水线的DSL语言,基于这套DSL语言可以准确定义一条可被调度和执行的流水线。
流水线执行模块
流水线执行模块主要确保流水线中所有Job都被按正确的依赖关系被并行或顺序执行,并实时更新流水线流转实时状态。

2)Job调度引擎

Job是流水线中被调度的最小单位,Job调度引擎主要负责每一个从流水线流程引擎产生的Job被调度到正确的构建集群机器上。

3)集成引擎

流水线中的任务插件有两大类,一类是Agent任务,比如Android、iOS构建,这类任务需要特定的构建环境,所以很自然的想到会被Job调度引擎调度到构建机上;还有一类任务是Agentless任务,比如审批、通知、外部系统调用等,这类任务只要在普通server端即可完成,无需占用宝贵的构建资源,就会被Job调度引擎调度到集成引擎上执行。大部分Agentless任务都跟外部服务集成有关。

4)Channel通道服务

Channel通道主要负责构建集群跟服务端的通信链路和协议实现。主要实现如下功能:
• 构建集群请求统一鉴权
出于安全性的考虑,构建集群跟其他微服务处于不同的VPC,通过网络完全隔离确保构建集群无法直接访问到服务端内网。基于这个背景,上述“流水线技术架构图”中的构建集群访问服务端走的是公网HTTPS请求,这就要对构建机请求做鉴权,Channel通道就是鉴权服务端收口
• 构建集群请求统一收口
构建集群需要跟服务端实时保持心跳、状态上报、拉取任务、上报任务执行状态,Channel是这些请求的收口,负责将不同业务的请求分配到不同的微服务上。

5)构建集群

构建集群主要负责拉取并执行Agent类构建任务,构建集群中运行的服务负责启动跟任务类型匹配的隔离构建环境:
• Linux平台下启动Docker容器
Android构建基于Linux平台,Linux平台下Docker容器化方案是环境隔离的不二之选,基于ACK serverless(阿里云公共云K8S类产品)启动serverless Docker容器,执行完自动销毁回收。基于云原生的ACK serverless实现了构建集群的弹性最大化,不构建几乎不占用任何计算资源,极大的控制了构建成本。
• Mac OS平台下启动虚拟机
由于苹果生态限制,iOS、Mac App构建只能在Mac OS系统下进行,而当前Mac OS没有成熟的类似Docker类容器方案可以使用,最终我们基于虚拟化方案来实现环境隔离。我们自建了基于云架构的Mac虚拟化集群,将Mac物理资源彻底池化,可以快速完成集群弹性扩缩容,完全符合云原生的理念。每次构建都从虚拟化集群中动态创建一台虚机,构建完立即销毁。
值得一提的是,Mac虚拟化集群是我们的技术优势,下面第五章我们将详细Mobile DevOps在Mac虚拟化集群方向的实践。

四、Mac虚拟化构建集群

目前Mobile DevOps的Mac虚拟化集群构建方案在国内处于绝对的领先地位,我们“也许”是国内第一家基于Mac虚拟机化技术实现iOS构建的DevOps平台,国内支持iOS构建的厂商几乎没有,其本质原因其实是Mac虚拟化技术限制:传统的Mac物理裸机构建只能在内部环境使用,根本不具备公共云开放服务的条件。Mac虚拟化构建集群方案是Mobile DevOps的技术优势。
  1. 虚拟化方案选型

受Mac OS平台本身的内核限制,目前Mac OS平台容器化方案极其不成熟,Mac OS平台的环境隔离基本只剩下虚拟化这一条路可以走。
虚拟化类型的选择
两种类型的虚拟化方案如下图所示,两种方案都基于Hypervisor实现,两个方案对比如下:
image.png

虚拟化方案1:
• 无宿主OS直接基于Hypervisor虚拟化VM,资源利用率高,更适合云服务的虚拟化方案
• 对硬件兼容性有更高的要求
虚拟化方案2:
• 在宿主机的OS上再基于Hypervisor虚拟化VM,更适合桌面用户的虚拟化方案
• 由于有宿主机OS,硬件兼容性更好
基于我们Mobile DevOps提供公共云服务的考虑,选择方案1可以更有效的提高资源利用率,硬件兼容性只要选择合适的硬件产品就能规避。
苹果生态安全合规问题
苹果生态封闭且有诸多安全合规限制,Mac平台有如下法务合规限制:

1.MacOS必须运行Apple硬件之上
2.在商业用途下,一个Apple硬件只允许运行一个macOS实例

image.png

从上述4种虚拟化方案对比,只有方案4是兼具苹果生态合规性和兼容性的,而且方案4其实也是上节我们选择的虚拟化方案1。基于上述虚拟化类型和苹果生态安全合规性及兼容性考虑,我们最终选定上述方案4。

  1. 云架构的虚拟化集群

要在云上提供公共的构建服务,仅有虚拟化方案还是不够的,还要有一套符合云架构的虚拟化集群方案,来满足Mobile DevOps对构建集群的诉求:
① Mac硬件资源池化 - 集群中的各个Mac资源应该是无状态的,所有Mac硬件资源共同组成一个资源池,可以被集群统一分配和调度。
② 弹性扩缩容 - 公共云业务规模存在一定的弹性,这就要求虚拟化集群也可以适应业务场景,可以快速弹性扩缩容,跟上业务的增长速度。
③ 高可用 - 在个别Mac硬件设备损坏的情况下,集群可以快速自动响应将任务分配到新的虚机上,提高任务执行成功率。
从单虚机到虚拟机集群,除了上述的Mac硬件资源池化,还要解决硬件资源集群化后新引入的分布式存储和分布式网络问题,从虚拟化单机到虚拟化集群如下图所示:
image.png

五、未来展望

未来展望

目前公共云Mobile DevOps还在公测阶段,还有很多方向需要努力:
• 增加构建错误智能分析、提示的能力。公共云用户众多的情况下,构建错误答疑是巨大的人力成本,后续需要基于关键字匹配,大数据分析,甚至是AI自动错误归类等技术手段直接提示构建错误原因,减少人工答疑成本
• 跟EMAS其他产品加强更多的联动,让Mobile DevOps串联完整的应用研发生命周期
• 跟社区保持更好的亲和性。支持Github Actions、Azure Pipeline等其他平台流水线迁移到Mobile DevOps;任务插件直接支持Github Actions 5000+开源插件,享受开源社区红利
• 加强被集成能力,让Mobile DevOps移动研发平台可以更好的集成到客户现有的研发流程中
• 深度优化应用编译构建效率,减少应用构建时长。终极目标是要云上的应用构建时长大幅短于本地构建,让开发者直观感受到云上构建的优势
如果你对移动构建编译技术、移动研发技术、或者云原生的方向感兴趣,并且你是一个喜欢技术挑战的人,欢迎加入我们,我们的目标是“做国际领先的移动DevOps品牌”。➡️ 点击这里,查看岗位信息。

引用文献:

[1]Azure DevOps:什么是DevOps?
[2]百度统计流量研究院
[3]微软发布Azure Pipelines,开源项目可无限制使用CI/CD
[4]所有开源项目免费使用,GitHub 内置 CI/CD终于来了!

查看原文

赞 0 收藏 0 评论 0

应用研发平台EMAS 发布了文章 · 2020-11-19

什么是低代码(Low-Code)?

阿里云 云原生应用研发平台EMAS 彭群(楚衡)

一、前言

如果选择用一个关键词来代表即将过去的2020年,我相信所有人都会认同是“新冠”。疫情来得太快就像龙卷风,短短数月就阻断了全世界范围内无数人与人之间的物理连接。但好在,我们已经全面迈入互联网时代:N95口罩再厚,也阻挡不了信息比特流的顺畅流通(宅男:B站依然香);居家隔离再久,也妨碍不了钉钉消息的准时送达(社畜:工作依然苦)。逍遥子在9月份的云栖大会上说:“新技术代表的新生产力,一定是我们全速战胜疫情、开创未来最好的原动力。” 那么在后疫情时代,究竟需要什么样的新技术,才能真正解放IT生产力,加速社会数字化转型,Make The World Great Again?我认为是低代码(Low-Code)。

基于经典的可视化和模型驱动理念,结合最新的云原生与多端体验技术,低代码能够在合适的业务场景下实现大幅度的提效降本,为专业开发者提供了一种全新的高生产力开发范式(Paradigm Shift)。另一方面,低代码还能让不懂代码的业务人员成为所谓的平民开发者(Citizen Developer),弥补日益扩大的专业人才缺口,同时促成业务与技术深度协作的终极敏捷形态(BizDevOps)。本文将重点介绍低代码相关背景知识,包括低代码的定义与意义、相关概念、行业发展等,期望能帮助大家更好地认识与理解低代码这个新兴领域。

二、什么是低代码

“Low-Code”是什么?如果你是第一次听说,没准也会跟我当年从老板口中听到这个词后的内心戏一样:啥?“Low-Code”?“Code”是指代码我知道,但这个“Low”字是啥意思?不会是老板发现我最近赶工写的代码很丑很“Low”吧... 想多了,老板怎么可能亲自review代码呢。那难道是指,“Low-level programming”里的“Low”?老板终于发现让我等编程奇才整天堆Java业务代码太浪费,要派我去闭关写一个高性能C语言网络库... 显然也不是,老板哪能有这技术情怀呢。那到底是什么意思?作为一名搜商比情商还高的程序员,能问Google的绝不会问老板。于是我一顿操作后,不假思索地点开了第一条搜索结果。果不其然,这是一条充满自由芳香只有翻-墙才能闻到的Wikipedia词条:Low-code development platform。

Wikipedia定义

2.png

从Wiki的这段定义中,我们可以提炼出几个关键信息:

  • 低代码开发平台(LCDP)本身也是一种软件,它为开发者提供了一个创建应用软件的开发环境。看到“开发环境”几个字是不是很亲切?对于程序员而言,低代码开发平台的性质与IDEA、VS等代码IDE(集成开发环境)几乎一样,都是服务于开发者的生产力工具。
  • 与传统代码IDE不同的是,低代码开发平台提供的是更高维和易用的可视化IDE。大多数情况下,开发者并不需要使用传统的手写代码方式进行编程,而是可以通过图形化拖拽、参数配置等更高效的方式完成开发工作。

Forrester定义

顺着Wiki的描述还能发现,原来“Low-Code”一词早在2014年就由Forrester提出了,它对低代码开发平台的始祖级定义是这样的:

3.png

相比Wiki的版本,这个定义更偏向于阐明低代码所带来的核心价值:

  • 低代码开发平台能够实现业务应用的快速交付。也就是说,不只是像传统开发平台一样“能”开发应用而已,低代码开发平台的重点是开发应用更“快”。更重要的是,这个快的程度是颠覆性的:根据Forrester在2016年的调研,大部分公司反馈低代码平台帮助他们把开发效率提升了5-10倍。而且我们有理由相信,随着低代码技术、产品和行业的不断成熟,这个提升倍数还能继续上涨。
  • 低代码开发平台能够降低业务应用的开发成本。一方面,低代码开发在软件全生命周期流程上的投入都要更低(代码编写更少、环境设置和部署成本也更简单);另一方面,低代码开发还显著降低了开发人员的使用门槛,非专业开发者经过简单的IT基础培训就能快速上岗,既能充分调动和利用企业现有的各方面人力资源,也能大幅降低对昂贵专业开发者资源的依赖。

低代码核心能力

基于上述的定义和分析,不难总结出如下这3条低代码开发平台的核心能力:

4.png

  • 全栈可视化编程:可视化包含两层含义,一个是编辑时支持的点选、拖拽和配置操作,另一个是编辑完成后所及即所得(WYSIWYG)的预览效果。传统代码IDE也支持部分可视化能力(如早年Visual Studio的MFC/WPF),但低代码更强调的是全栈、端到端的可视化编程,覆盖一个完整应用开发所涉及的各个技术层面(界面/数据/逻辑)。
  • 全生命周期管理:作为一站式的应用开发平台,低代码支持应用的完整生命周期管理,即从设计阶段开始(有些平台还支持更前置的项目与需求管理),历经开发、构建、测试和部署,一直到上线后的各种运维(e.g. 监控报警、应用上下线)和运营(e.g. 数据报表、用户反馈)。
  • 低代码扩展能力:使用低代码开发时,大部分情况下仍离不开代码,因此平台必须能支持在必要时通过少量的代码对应用各层次进行灵活扩展,比如添加自定义组件、修改主题CSS样式、定制逻辑流动作等。一些可能的需求场景包括:UI样式定制、遗留代码复用、专用的加密算法、非标系统集成。

不只是少写代码

回到最初那个直击心灵的小白问题:Low-Code中的“Low”,到底是啥意思?答案已经显而易见:既不是指抽象程度很低(相反,低代码开发方式的抽象程度要比传统编程语言高一个level),也不是指代码很low(也相反,低代码所生成的代码一般都经过精心维护和反复测试,整体质量强于大部分手写代码),而是单纯的“少写代码” —— 只在少数需要的情况下才手写代码,其他大部分时候都能用可视化等非代码方式解决。

再往深一点儿看,低代码不只是少写代码而已:代码写得少,bug也就越少(正所谓“少做少错”),因此开发环节的两大支柱性工作“赶需求”和“修bug”就都少了;要测的代码少了,那么测试用例也可以少写不少;除了开发阶段以外,平台还覆盖了后续的应用构建、部署和管理,因此运维操作也更少了(Low-Code → Low-Ops)。

然而,少并不是最终目的:如果单纯只是想达到少的效果,砍需求减人力、降低质量要求也是一样的。低代码背后的哲学,是少即是多(Less is More),或者更准确说是多快好省(Do More with Less) —— 能力更多、上线更快、质量更好,成本还更省,深刻践行了阿里“既要,又要,还要”的价值观精髓。

image.png

平台的职责与挑战

上面说的是低代码给开发者提供的能力与吸引力,那么作为服务的提供方与应用的承载者,低代码开发平台自身应该承担怎样的职责,其中又会遇到多大的挑战?是否就一定要如阿里云所主张的那样,“把复杂留给自己,把简单留给别人”?虽然这句话听起来很深明大义,但不知道大家有没有想过,为什么我们一定要抱着复杂不放,平白无故给自己找事?就不能直接干掉复杂,也给咱阿里云自己的员工留点简单吗?是工作太容易就体现不出来KPI价值了,还是家里的饭菜不如公司的夜宵香?

冥思苦想许久后,我从热力学第一定律中找到了答案:开发一个应用的总复杂度是恒定的,只能转移而不可能凭空消失。要想让开发者做的更少,安心享受简单的快乐,那么平台方就得做的更多,默默承担尽可能多的复杂度。就像一个满身腱子肉的杂技男演员,四平八稳地托举着在高处旋转与跳跃的女搭档;上面的人显得越轻盈越毫不费力,下面的人就得越稳重越用尽全力。当然,不是说上面的女演员就很轻松没压力,只是他们各自的分工不同,所承担的复杂度也不一样。

根据《人月神话》作者Fred Brooks的划分,软件开发的复杂度可以划分为本质复杂度(Essential complexity )和偶然复杂度(Accidental complexity)。前者是解决问题时固有的最小复杂度,跟你用什么样的工具、经验是否丰富、架构好不好等都无关,而后者就是除此之外在实际开发过程中引入的复杂度。通常来说,本质复杂度与业务要解决的特定问题域强相关,因此这里我把它称为更好理解的“业务复杂度”;这部分复杂度不是任何开发方法或工具能解决的,包括低代码。而偶然复杂度一般与开发阶段的技术细节强相关,因此我也相应把它称为“技术复杂度”;而这一部分复杂度,恰好就是低代码所擅长且适合解决的。

为开发者尽可能屏蔽底层技术细节、减少不必要的技术复杂度,并支撑其更好地应对业务复杂度(满足灵活通用的业务场景需求),这是身为一个低代码开发平台所应该尽到的核心职责。

6.png

在尽到上述职责的同时,低代码开发平台作为一个面向开发者的产品,还需要致力于为开发者提供简单直观的极致开发体验。这背后除了巨大的工作量,还得能在“强大”和“易用”这两个很难两全其美的矛盾点之间,努力找到一个符合自己产品定位与目标客户需求的平衡点 —— 这也许是设计一个通用低代码开发平台所面临的最大挑战。

三、低代码相关概念对比

纯代码(Pro-Code / Custom-Code)

“纯代码”可能算是我杜撰的一个词,更常见的说法是专业代码(Pro-Code)或定制代码(Custom-Code);但意思都一样,就是指传统的以代码为中心(Code-Centric)的开发模式。之所以我选择用“纯代码”,是因为如果用“专业代码”会显得似乎低代码就不专业了一样,而用“定制代码”又容易让人误解成低代码无法支持定制的自定义代码。

当然,更准确的称谓我认为是“高代码”(与低代码恰好对应,只是名字太难听,被我嫌弃了...),因为即便是使用传统的代码IDE,有些开发工作也支持(甚至更适合)以非代码方式完成,比如:iOS端开发时使用的SwiftUI界面设计器、服务端开发数据库应用时使用的PowerDesigner建模工具。不过这部分可视化工作在传统开发模式下只是起辅助作用,最后通常也是生成开发者可直接修改的代码;开发者仍然是以代码为中心来开展主要工作。

低代码与纯代码之间的关系,其实跟视频和文章之间很像:

  • 低代码就像是现代的“视频”,大部分内容都由直观易理解、表达能力强的图片组成,因此更容易被大众所接受。但与此同时,视频也不是死板得只能有图片,完全可以添加少量文字(如字幕、标注)来弥补图片表达不够精确的问题。BTW,关于“图”和“文字”之间的辩证关系,可以进一步参考《架构制图:工具与方法论》[1]这篇文章中的相关描述。
  • 纯代码则更像是传统的“文章”,虽然很久以来都一直是信息传播的唯一媒介,但自从视频技术诞生以及相应软硬件基础设施的普及以来,便逐渐开始被抢走了风头。如今,视频已成为大部分人获取信息的主要渠道(从电视电影到B站抖音),而经常读书读文章的人却越来越少。但不可否认的是,文章依然有它存在的意义和受众(不然我也不会费这劲敲这么多字了),即使“市场份额”一直在被挤压,但永远会有它立足的空间。

7.png

如果按上面这种类比关系推导,低代码未来也会遵循与视频类似的发展轨迹,超越纯代码成为主流开发模式。Gartner的预测也表达了相同的观点:到2024年,所有应用程序开发活动当中的65%将通过低代码的方式完成,同时75%的大型企业将使用至少四种低代码开发工具进行应用开发。

但同样地,就像是视频永远无法取代文章一样,低代码也永远无法彻底取代纯代码开发方式。未来低代码和纯代码方式将以互补的形态长期共存,各自在其所适合的业务场景中发光发热。在后面的“低代码业务场景”章节,会详细列出哪些场景在现阶段更适合用低代码模式开发。

零代码(Zero-Code / No-Code)

从分类的完备性角度来看,有“纯代码”自然也应该有完全相反的“零代码”(也称为“无代码”)。零代码就是完全不需要写代码的应用开发平台,但这并不代表零代码就比低代码更高级和先进,它只是做了一个更极端的选择而已:彻底拥抱简单的图形可视化,完全消灭复杂的文本代码。选择背后的原因是,零代码开发平台期望能尽可能降低应用开发门槛,让人人都能成为开发者(注意:开发 ≠ 写代码),包括完全不懂代码的业务分析师、用户运营,甚至是产品经理(不懂装懂可不算懂)。

即便是专业开发者,在技术分工越来越精细的趋势下(前端/后端/算法/SRE/数据分析..),也很难招到一个能独立开发和维护整套复杂应用的全栈工程师。但零代码可以改变这一切:无论是Java和JavaScript傻傻分不清楚的技术小白,还是精通深度学习但没时间学习Web开发的算法大牛,都可以通过零代码实现自己的技术梦或全栈梦。“改变世界的idea已有,就差一个程序员了”,这句玩笑话或许真的可以成真;哦不,甚至都用不着程序员,有idea的人自己就能上。

8.png

当然,所有选择都要付出代价,零代码也不例外。完全抛弃代码的代价,就是平台能力与灵活性受限:

  • 一方面,可视化编辑器的表达能力远不及图灵完备的通用编程语言,不引入代码根本没法实现灵活的定制与扩展(当然,理论上也可以做成Scrach/Blockly那样的图形编程语言,但那样不过是换一种形式在手写代码而已)。
  • 另一方面,由于目标受众是非专业开发人员,平台能支持的操作会更趋于“傻瓜化”(e.g. 页面只支持大块业务组件的简单堆叠,不支持细粒度原子组件和灵活的CSS布局定义),同时也只会透出相对“亲民化”的模型和概念(e.g. 使用“表格”表示数据,而不是用“数据库”),无法支撑强大专业的底层开发原语和编程理念。

9.png

虽然零代码与狭义上的低代码有着上述明显差异,但从广义上来说,零代码可以当作低代码的一个子集。Gartner在其相关调研报告中,就是将“No Code”划在了范围更广的低代码应用平台“LCAP”(Low-Code Application Platform)中。而当前市面上很多通用的低代码开发平台,也都兼具一定程度的零代码能力;比如低代码领域领头羊Mendix,既提供了简单易用的零代码Web IDE - Mendix Studio,也包括一个功能更强大的低代码桌面IDE - Mendix Studio Pro。

HpaPaaS(高生产力应用PaaS)

上文提到,“Low-Code”一词是拜Forrester所赐。作为同样是国际知名调研机构(a.k.a 造词小能手)的Gartner,显然不会轻易在这场可能决定低代码领域江湖地位的新概念作词大赛中认输,于是也于2017年发明了“HpaPaaS”(High-productivity application Platform as a Service)这个听上去更高大上的缩写词。

按照Gartner的定义,HpaPaaS是一种支持声明式、模型驱动设计和一键部署的平台,提供了云上的快速应用开发(RAD)、部署和运行特性;这显然与低代码的定义如出一辙。但事实证明,名字起得太专业并不见得是好事,“HpaPaas”最终还是败给了起源更早、更接地气也更顺口的“Low-Code”:从2019年开始,Gartner在其相关调研报告中也开始全面采用“Low-Code”一词(如LCAP),亲手为“HpaPaaS”打上了 @deprecated 印记。

10.png

图源:https://blog.kintone.com/business-with-heart/difference-saas-iaas-paas-apaas-hpapaas

值得补充的是,“HpaPaaS“这个词也并非横空出世,而是传承自更早之前Gartner提出的“aPaaS”,它俩之间的关系是:HpaPaaS只是aPaaS的一个子类;除了HpaPaaS这种通过低代码实现的高生产力应用开发平台以外,aPaaS还包括面向纯代码的传统应用开发平台(High-control aPaaS,即可控度更高的纯代码开发方式)。

不值得但就想八卦一下的是,“aPaaS”这个词也非凭空捏造,而是与云计算的兴起渊源颇深。相信各位云道中人都已猜到,aPaaS与IaaS/PaaS/SaaS这些云计算远古概念是一脉相承的:aPaaS介于PaaS和SaaS之间,相比PaaS提供的服务更偏应用,但又不像SaaS一样提供现成的软件服务(更详细的说明可参考配图来源文章)。

四、为什么需要低代码

低代码是什么可能并没那么重要,毕竟在这个信息爆炸的世界,永远不缺少新奇而又短命的事物。大部分所谓的新技术都只是昙花一现:出现了,被看到了;大部分人“哦”了一声,已阅但表示不感兴趣;小部分人惊叹于它的奇思妙想,激动地点了个赞后,回过头来该用什么还是什么。真正决定新技术是否能转化为新生产力的,永远不是技术本身有多么优秀和华丽,而是它是否真的被需要,即:为什么需要低代码?如果用不同的主语填充上面这个问句(冷知识:这叫做“延迟主语初始化”),可以更全面地看待这个问题:

为什么「市场」需要低代码?

在这个大爷大妈都满嘴“互联网+”和“数字化转型”的时代,企业越来越需要通过应用(App)来改善企业内部的信息流转、强化与客户之间的触点连接。然而,诞生还不太久的IT信息时代,也正面临着与我国社会主义初级阶段类似的供需关系矛盾:落后的软件开发生产力跟不上人民日益增长的业务需求。

11.png

Gartner预测,到2021年应用开发需求的市场增长将至少超过企业IT交付能力的5倍。面对如此巨大的IT缺口,如果没有一种革命性的“新生产力”体系,很难想象仅凭现有传统技术体系的发展延续就能彻底解决问题。而低代码技术正是带着这样的使命而降临,期望通过以下几个方面彻底革新应用开发生产力,拯救差一点就要迈入水深火热的IT世界:

提效降本 & 质量保障

虽然软件行业一直在高速发展,新的语言、框架和工具层出不穷,但作为从业者我们不得不承认:软件开发仍处于手工作坊阶段,效率低、人力成本高、质量不可控。项目延期交付已成为行业常态,而瓶颈几乎总是开发人员(对机器能解决的问题都不是问题);优秀的开发人才永远是稀缺资源,还贼贵;软件质量缺陷始终无法收敛,线上故障频发资损不断。

相比而言,传统制造业经过几百年工业革命的发展,大部分早已摆脱了对“人”的强依赖:从原料输入到制品输出,中间是各种精密仪器和自动化流水线的稳定支撑,真正实现生产的标准化和规模化。虽然信息化号称是人类的第三次工业革命,但以软件行业目前的状况,远远还没到达成熟的“工业化”阶段。

所以,亲爱的程序员朋友,当你与前端联调了一上午接口,又与产品撕逼了一下午需求,再与自己的bug抗争了一整晚,好不容易遁入梦乡又被一连串报警短信吵醒时,是否有抬头对着星空憧憬过:“I have a dream... that one day,软件开发也能像工业制品一样,批量流水化生产,稳定高效没烦恼。” 事到如今,不管你有没有意识到,这个憧憬正在慢慢变成现实。

12.png

是的,低代码正在将应用软件开发过程工业化:每个低代码开发平台都是一个技术密集型的应用工厂,所有项目相关人员都在同一条产线内紧密协作。开发主力不再是熟知for循环一百种写法的技术Geek,而是一群心怀想法业务sense十足的应用Maker。借助应用工厂中各种成熟的基础设施、现成的标准零件、自动化的装配流水线,开发者只需要专注于最核心的业务价值即可。即便是碰到非标需求,也可以随时自己动手,用最灵活的手工定制(代码)方式来解决各种边角问题。

扩大应用开发劳动力

通过让大部分开发工作可以仅通过简单的拖拽与配置完成,低代码(包括零代码)显著降低了使用者门槛,让企业能够充分利用前面所提到的平民开发者资源。部分纯零代码需求场景下,低代码还能让业务人员实现自助式(self-service)应用交付,既解决了传统IT交付模式下的任务堆积(backlog)问题,避免稀缺的专业开发资源被大量简单、重复性的应用开发需求所侵占,也能让业务人员真正按自己的想法去实现应用,摆脱交由他人开发时不可避免的桎梏。

13.png

至此,应用开发能力不再是少数专业开发者的专利和特权,且今后所需要的技能门槛与拥有成本也会越来越低,真正实现所谓的“技术民主化”(democratization of technology)。

加强开发过程的沟通协作

多方调查结果显示,软件项目失败的最主要原因之一就是缺乏沟通(poor communication)。传统开发模式下,业务、产品、设计、开发、测试与运维人员各司其职,且各有一套领域内的工具和语言,长久以来很容易形成一个个“竖井”(silos),让跨职能的沟通变得困难而低效。这也是为什么当前热门的敏捷开发和DevOps都在强调沟通(前者是协同Biz与Dev,而后者是协同Dev和Ops),而经典的DDD领域驱动设计也主张通过“统一语言”来减少业务与技术人员之间的沟通不一致。

14.png

有了低代码后,这一状况将得到根本改善:上述各角色都可以在同一个低代码开发平台上紧密协作(甚至可以是同一个人),这种全新的协作模式不仅打破了职能竖井,还能通过统一的可视化语言和单一的应用表示(页面/数据/逻辑),轻松对齐项目各方对应用形态和项目进度的理解,实现更终极的敏捷开发模式,以及在传统DevOps基础之上更进一步的BizDevOps[2]。

统一开发平台下的聚合效应

低代码尝试将所有与应用开发相关活动都收敛到同一个平台(one platform)上后,将会产生更多方面的聚合效应与规模收益:

  • 人员聚合:除了上一点所提到的各职能角色紧密协作以外,人员聚合到统一的低代码开发平台进行作业后,还能促进整个项目流程的标准化、规范化和统一化。
  • 应用聚合:一方面,新应用的架构设计、资产复用、相互调用变得更容易;另一方面,各应用的数据都天然互通,同时平台外数据也能通过集成能力进行打通,彻底消除企业的数据孤岛问题。
  • 生态聚合:当低代码开发平台聚合了足够多的开发者和应用后,将形成一个巨大的、连接一切、有无限想象力的生态体系,彻底放飞低代码的价值。

为什么「这个时代」才需要低代码?

如果你了解过市面上各种低代码产品,不难发现其实这个领域的许多玩家在低代码概念诞生之前就已经存在了,比如:低代码领域的另一个巨头OutSystems,早在2001年就已经创立;而去年也被Forrester评为低代码行业leader之一的FileMaker,更是诞生于遥远的1985年(正好35岁,似乎在疯狂暗示什么)。那么,如果低代码像前面说的那么好,为什么以前没有火起来呢?从技术和业务两个角度看,可以归纳为以下原因:

技术成熟度不足

低代码底层的各项核心技术(可视化、模型驱动、RAD、BPMS...)都已经有漫长的发展历史,看上去似乎只是新瓶装旧酒。然而理智的人都知道,任何技术都会遵循所谓的“技术成熟度曲线”(The Hype Cycle),不可能刚一诞生就跳过发育直接秀翻全场,被大规模采纳和投入生产。以模型驱动技术为例,虽然十几年前就已经有体系化的理论研究(e.g. MDA)和配套工具(e.g. EMF),但在当时的技术背景下,由于能力不完备、过于理想化、技术门槛高等原因,一直没能在工业界走向主流。

15.png

而如今这个时代,支撑低代码的那些“老”技术都已经过长时间的发展酝酿与市场检验,而另一些完美互补的“新”技术(e.g. 云原生、响应式Web)也在飞速发展和走向成熟,是时候通过“低代码”这个新酒瓶重新包装上市,为亟需新生产力的传统IT市场带来一场真香之旅了。

业务收益不明显

即使十几年前的低代码技术已经足够成熟,也一定不会在当年的应用开发市场上产生现在这样的影响力。为什么?因为技术都是为业务服务的,而当时的应用开发业务需求可比现在简单多了:没有如今的多渠道(Multi-channel)、多样化体验(Multi-experience)和各种集成与定制需求,也不会奢求如今已成为企业级应用标配的弹性、分布式和高可用,更是缺乏快速变化的IT业务场景来推动持续集成与快速交付。

虽然低代码可以完美解决上述所有问题(e.g. 多端应用生成、云原生架构、API集成能力),但放在当年的市场和业务背景下,加上前面所说的技术不成熟度,整体的投入产出比会很低,不足以让企业大面积采纳低代码解决方案。

16.png

而如今这个时代,企业都快被新技术带来的能力和收益“惯坏了”,动不动就是:我想做一个送菜应用。用户端?安卓、iOS、H5、小程序都来一套。运营端?一般都在电脑上看,但记得手机上也得适配啊。服务端?上云,必须的。哦,我听技术合伙人说现在流行多云架构,也给我整一套哈。运维还要钱?啥是运维?应用有了不就能用了嘛,运维还要花我钱?你当投资者给我的钱是大风刮来的啊!

如果用传统的开发模式,这么全套下来的工时与报价,可能早就吓跑了这群跟产品经理一样天真可爱的人;但现代化的低代码技术,可以圆了上面这位创业者的卖菜梦,用白菜一般的价格,实现白粉一样的价值。当年的程维如果能用上现在的低代码,第一版的滴滴App也就不至于被外包做得乌烟瘴气直接报废了(至少能多扛一阵子...)。

为什么「专业开发者」也需要低代码?

虽然零代码确实是设计给非专业开发者用的,但其所能支撑的业务场景确实有限,无法真正革新传统开发模式,替代那些仍需专业开发者参与的复杂业务场景。而狭义上的低代码却有潜力做到这一点,因为它天生就是为专业开发者而量身定制的。Gartner最近的一项调研报告显示,“66%的低代码开发平台用户都是企业IT部门的专业开发者”。这充分说明了,专业开发者比平民开发者更需要低代码。

屏幕前一批穿格子衬衫的同学要发问了:“低代码都不怎么写代码了,怎么能算是为我们程序员服务呢?”。虽然程序员讨厌重复自己,但重要的事情还是得多说一遍:开发 ≠ 写代码。1万年前蹲在洞穴里的原始人,在用小石子画远古图腾;100年前坐在书桌前的徐志摩,在用钢笔给林徽因写情书;而今天趴在屏幕前的很多人,相信都已经开始用上手写板或iPad涂涂写写了。千百年来,人类使用的工具一直在演进,但所从事活动的本质并没有多大改变。无论是用小石子还是小鼠标,写作绘画的本质都是创造与表达,最终作品的好坏并不取决于当时你手中拿着什么;同样地,应用开发的本质是想法和逻辑,最终价值的高低也不取决你实现时是用的纯代码还是低代码。

而相比纯代码而言,低代码极有可能成为更好的下一代生产力工具:

减少不必要的工作量

可视化拖拽与参数配置的极简开发模式,结合模型驱动的代码自动生成机制,可以消灭绝大部分繁琐和重复的boilerplate代码;一站式的部署和运维管理平台,无需自己搭建CI/CD流水线、申请环境资源、配置监控报警;一次搭建同时生成、构建和发布多端应用,免去人工同步维护多个功能重复的端应用;开箱即用的组件库、模板库、主题库、连接器等,让最大化软件复用成为可能。总而言之,低代码能够让专业开发者更专注于创新性、有价值、有区分度的工作,而不是把宝贵开发时间都耗费在上面那些不必要的非业务核心工作上。

强大的平台能力支撑

虽然上面列的技术支撑性工作并不直接产生业务价值,但却会直接影响业务的性能、成本、稳定性、安全性、可持续发展能力等。有远见的企业,绝不允许牺牲这些重要指标,来换取短暂的业务加速。低代码开发平台深知这一点,因此在简化和屏蔽底层技术细节的同时,也会尽可能把自己所cover的部分做到最好(至少能和纯代码开发方式一样好),包括但不限于:

  • 现代化的技术架构和实现:现代化的低代码开发平台,在支撑用户应用时所选择的技术架构与实现方案,也会是现代化且符合业界最佳实践的,例如,前端基于主流的HTML5/CSS3标准和React框架,后端基于成熟的Java语言、SpringBoot框架和MySQL数据库,部署环境基于云原生的Docker镜像、CI/CD流水线、K8s集群和Service Mesh技术(相关知识可参考《正确入门Service Mesh:起源、发展和现状》)。
  • 零成本的技术升级和维护:低代码的高维抽象开发方式,让应用的核心业务逻辑与底层技术细节彻底解耦。开发者在大部分情况下都不需要关心底层技术选型,同时也无需亲自跟进这些技术的版本升级与漏洞修复,免费享受与时俱进的技术红利和应用安全性提升。即便遇到某些底层技术或工具需要进行彻底更换(比如不再维护的开源项目),开发者也完全不必感知;技术迁移再费劲再难搞,平台自己努力就行,对开发者来说只要服务一直在线,岁月就依然静好;事后可能还会惊喜地发现,应用访问突然就变得更快了,仿佛冥冥中自有天助,感激上苍和低代码。

一体化生态能力复用

复用(Reuse)是提升软件开发效率和工程质量的最有效途径。传统的代码开发模式下,开发者可以通过提取公共类/函数、引用共享库、调用外部API服务、沉淀代码片段和模板等方式实现复用。在低代码的世界里,平台也可以提供对应的多层次多粒度复用手段,比如页面组件库、逻辑函数库、应用模板库等。

但更重要的是,低代码平台还可以充分发挥其一体化的生态优势,提供强大易用的可复用能力(资产)的发现、集成与共享体系:以页面组件为例,你可以直接用系统组件,也可以在平台自带的组件市场上搜索和引用更合适的组件,还可以自己用代码开发一个自定义组件并发布到市场中。平台的生态体系越大,积累的可复用能力就越多,应用的开发成本也会越低。

相比而言,虽然传统代码世界整体生态更庞大和深厚,但由于各类技术不互通、缺乏统一平台与市场、代码集成成本高等原因,一直以来都没有形成有类似规模潜力的生态能力复用体系,导致重复造轮子和低水平重复建设的现象司空见惯,还美名为“新基建”。

说到这里,另一批裹着冲锋衣头顶锃亮的同学也忍不住了:“万一低代码真的发展起来了,是不是就不需要那么多程序员了啊?上有老下有小的,同是码农身,相煎何太急!”。低代码虽然是一场应用开发生产力革命,但并不会革掉程序员的饭碗。它去掉的只是难懂的编程语法、繁琐的技术细节和一切可自动化的重复性工作,并没有也无法去掉应用开发最核心的东西:严谨的业务逻辑、巧妙的算法设计、良好的工程风格等。对于真正的程序员,即使剥去他一层又一层的编程语言和工具熟练度技能外壳,最终剩下的仍然是一个有价值的硬核开发者。

当然,如果你坚持要用纯粹的写代码方式来改变世界,也不至于失业。要么,你可以选择那些低代码暂时不太适用的领域,比如底层系统驱动、3D游戏引擎、火箭发射程序;或者,你也可以选择去写低代码中那一部分不可或缺的自定义代码扩展,为平民开发者提供高质量的积木。最后,你也完全可以选择为低代码平台本身的底层代码添砖加瓦,比如加入阿里云云原生应用研发平台EMAS团队 (〃'▽'〃) ,与作者一起共建下一代云原生低代码开发平台“Mobi”,内推直达邮箱:pengqun.pq@alibaba-inc.com。

为什么「我不」需要低代码

即使所有人都认同上述“为什么要用低代码”的理由,但仍不时会有试水者跳出来,给大家细数“为什么我不需要低代码”。实践出真知没错,而且大部分质疑背后也都有一定道理;但在我看来,更多的可能是主观或无意识的偏见。这里我列了一些对低代码的常见质疑和我个人的看法,期望能帮助大家看到一个更全面和客观的低代码。

质疑1:低代码平台不好使

“试用过一些所谓的低代码开发平台,要么能力很弱,要么体验太差,只能开发点玩具应用。”

作为调研过国内外多款低代码产品的深度体验用户,我的观点是:不能以偏概全。低代码市场在国内正处于爆发初期,所以许多与低代码只沾一点边的产品也都在蹭热点;但它们并不能代表低代码目前的业界水平和发展方向。市面上真正成熟的企业级低代码开发平台,完全有能力以高效的开发方式满足大部分复杂场景的功能需求,以及企业级应用所需要的安全、性能、可伸缩等非功能需求,这一点在国外市场已得到充分验证(不然也不会这么被寄予厚望)。

当然,国内市场尚处于鱼龙混杂的混战阶段,遇到真龙的概率很低,但碰上金鱼鲤鱼甚至木头假鱼都在所难免。相信随着时间推移,真正有实力和口碑的产品都能脱颖而出,为大家展现低代码该有的样子。

质疑2:低代低开发不可控

“平台上的各种可视化组件、逻辑动作和部署环境都是黑盒,如果内部出问题无法排查和解决。”

作为同样不搞清楚底层原理不舒服斯基的程序员,我更愿意相信:问题只是暂时的。虽然这确实是目前使用低代码平台时绕不开的一个痛点,但并不属于低代码技术本身的固有缺陷。计算机领域有一句至理名言:任何问题都可以通过增加一个间接的中间层来解决。低代码的思路亦是如此:与当年的操作系统和现在的云平台一样,都是想通过建立一个黑盒化的中间层抽象来降低开发者的工作量与心智负担。

当然,所有额外增加的中间层都不是完全免费的,低代码也不例外。作为一个尚未成熟稳定的新的中间层,低代码必然会出现各种让使用者束手无措的问题,就跟当年的操作系统内核bug、如今的云主机I/O hang一样。但历史规律也告诉我们,所有伟大的技术最终都会走向成熟;只要低代码领域一直健康发展,问题总会越来越少,最终降到一个绝大部分人感知不到的范围内。过去萦绕在Windows用户心中挥之不去的“蓝屏”问题,对如今的新用户来说早已不知为何物;今天低代码开发者所遇到的种种“蓝瘦”问题,未来也终将成为被遗忘的历史(谁还没段黑历史呢)。

质疑3:低代码应用难维护

“应用一旦复杂起来,各种复杂逻辑流穿插着自定义代码,看不懂也改不动,还不如全用代码呢。”

作为对软件可维护性深有感触的无脑级布道者(见《救火必备!问题排查与系统优化手册》),我不得不说:用低代码开发,也要讲基本法。一般来说,无论是使用低代码开发还是纯代码开发,造成应用可维护性低的根本原因往往不在于开发工具,而是开发者自身没有去遵循一些软件开发的普适原则,比如工程规范性、命名可读性、DRY/KISS/SOLID原则等。

好的低代码平台绝不会阻碍开发者去改善应用的可维护性;恰恰相反,还会尽可能提供引导和帮助。以Mendix为例,除了支持基本的模型分析与重构(e.g. 无用模型、对象重命名、子逻辑流提取)以外,甚至还提供了基于ISO/IEC 25010标准的应用质量监控(AQM)能力。另一方面,让应用变得难以维护的一个客观原因也是应用本身过于复杂,而低代码作为高度抽象和自动化的开发模式,在降低应用复杂度方面是专业的。

综合来看,低代码虽然不是能解决一切问题的银弹,但更不是会带来更多问题的炸弹:在提高应用可维护性方面的上限,一定比传统开发模式更高;但决定应用可维护性下限的,依然还是开发者自己。

五、低代码行业发展

回应质疑的最好方式,就是做好你自己,用实际的表现说话。对于一个行业而言,判断它当前的表现是否够好,或者未来是否有潜力做到更好,可以从以下这三个方面进行衡量:市场规模(蛋糕够不够大)、适用场景(是否可落地)、竞品状况(有没有被验证过)。

市场规模

"Talk is cheap,show me the code money."

—— Linus Starcraft

文章可以忽悠,但市场不会说谎:

  • Forrester在2015年曾预测过,低代码的市场将从2015年的17亿美元增长至2020年的150亿美元。
  • Marketsandmarkets在今年四月份的分析报告中预测,低代码的市场将从2020年的130亿美元(估算值,可以看出来与Forrester当年的预测是接近的)增长到2025年的450亿美元(年复合增长率:28.1%)。
  • PS Inteligence在2018年的分析报告中预测,全球的低代码开发平台市场中,亚太地区将在今后五年(2019-2024年)中保持最高的增长速度。
    17.png

总结一下就是两点:

  • 低代码的市场规模足够大,且一直都在高速增长。
  • 作为亚太地区的经济大国与IT强国,中国的低代码市场将会引来一个爆发期,未来几年内的增速都会超过全球平均水平。

适用场景

理论上来说,低代码是完全对标传统纯代码的通用开发模式,应该有能力支撑所有可能的业务场景。但理论也只是理论,低代码一统江湖的梦想尚未照进现实,也不可能完全取代现实。前文中提到过,低代码与纯代码方式是互补关系,未来也将长期共存,各自在其所适合的业务场景中发光发热。同时还需要指出的是,当前阶段的低代码技术、产品和市场都尚未完全成熟,因此部分本来可能很适合用低代码来开发的场景,目前也只能先用纯代码来替代。

Gartner在2019年的低代码调研报告中,曾经绘制过一张用来阐述低代码适用场景的“应用金字塔”:

18.png

  • 应用级别划分:从下往上,分别为工作组级(Workgroup Class)、部门级(Departmental Class)、企业级(Enterprise Class)、可扩展需求极强的企业级(Extreme-Scale Enterprise Class)。容易看出来,它主要的划分维度就是应用所面向的用户基数(基数越大,可扩展需求也越高)。
  • 任务关键性:从下往上,各级别应用的任务关键性(Mission Criticality)逐级递增。例如一个只在工作组内使用的后台管理应用,一般都不会涉及到影响整个企业的关键任务。脱离企业这个视角来看,整个软件产业中也有很多通用的任务关键型应用,比如:实时操作系统、航空调度系统、银行对账系统。
  • 实现复杂度:从下往上,各级别应用的复杂度(Complexity)也逐级递增。例如最上层的企业级应用,除了功能覆盖面大导致业务复杂以外,往往还需要满足更多苛刻的非功能需求,包括但不限于:用户体验、性能、可靠性、安全性、可伸缩性、可维护性、兼容性。其他一些复杂软件的案例包括:3D游戏界面(交互复杂)极其底层的游戏引擎(逻辑复杂)、超大型CRM系统(一方面是实现很复杂,另一方面,这种成熟软件的标准化程度较高,大部分情况下可以直接用现成的SaaS软件)。
  • 应用需求量:从上往下,各级别应用的需求体量(Volume)逐级递增,呈现一个金字塔形状。这个特征可以用万能的2/8原则来理解:20%的“全民”应用,由于需求的通用性和普适性,可以覆盖至少80%的用户群体(例如企业大部分人都要用的考勤系统);而剩下那80%的“小众”应用,由于需求的定制化和特殊性(例如蚂蚁的期权系统...),就只能覆盖各自小圈子里那20%的用户了。
  • 与低代码的契合关系:从上往下,各级别应用与低代码越来越契合(Relevant)。也就是说:越简单的应用,越契合低代码;越不太关键的任务,也越契合低代码。同时,由于契合低代码的应用更偏金字塔底层,而这些应用的需求量都更大,所以可以得出如下判断:低代码能够适用于大部分业务场景(而且这个比例会一直上升,逐步往金字塔的更上层应用逼近),例如:B2E类应用(表单、审批流、ERP系统)、B2B类应用(企业商城、工业控制台)、B2C类应用(企业展示、营销页、店铺装修)。

竞品概况

低代码虽然是一个新兴概念,但这个行业本身并不算很新(前文也有提到),这些年以来早就积累了不少资深的荣耀王者。同时,低代码作为一个朝阳产业和资本热点,近几年也不断有更多的新玩家在加入这个刺激战场。

19.png

上图分别是Gartner给出的低代码平台魔力象限和Forrester给出的低代码平台技术波谱。从图中可以看到:

  • OutSystems和Mendix一马当先,是公认的低代码领域头牌。这两家都是很纯粹的通用低代码开发平台,且都经过了长时间的发展和积累:OutSystems成立于2001年,员工人数1000+,年营收超过1亿美元;2018年6月获得了KKR和高盛的3.6亿美元融资,目前估值超过10亿美元;Mendix成立于2005年,员工人数500+,年营收超过2300万美元(18年数据),2018年8月被西门子以7.3亿美元收购。
  • Salesforce和Microsoft紧随其后,都处于行业领先者地位。但这两家的公司性质和发展路径都很不一样:Salesforce是以SaaS起家,公司规模就不用多说了,反正就是SaaS届的巨无霸。这类SaaS厂商做低代码的动力,是为了解决客户对成品SaaS软件的定制诉求。M$更不用多介绍,只说下他们做低代码的天然优势:一方面,作为办公软件航空母舰,低代码可以帮助他们的客户实现从Excel表单到定制App的能力与体验升级;另一方面,作为云计算三巨头之一,低代码可以帮助他们连接内部的云计算生态体系,为开发者提供一个统一和易用的上云界面。
  • 国外市场已经得到充分验证,但国内市场还刚刚兴起,还没有一家能够赢得上述调研机构的芳心,挤进上面这两张方图。国内目前的一些竞品和融资情况包括:2018年5月,搭搭云完成A轮的千万级融资;2018年9月,宜创科技得到清源创投的战略融资;2018年12月,轻流完成千万级Pre-A融资;2019年8月,数式科技得到盈动资本的数千万人民币天使轮融资;2019年8月,ClickPaas获得晨兴资本数百万美元的A轮融资;2019年,奥哲分别获得阿里5千万的A+轮融和高榕资本上亿元的B轮融资。(注:竞品数据来源于我们组PD的辛勤整理;为此我决定这篇文章剩下内容再也不黑PD了;下篇再说。)

六、结语

本文总结了低代码领域的基本概念、核心价值与行业现状。虽然这些内容都比较基础和偏理论,但我始终认为,深刻理解一个系统的前提,正是这些务虚的东西 —— 技术架构只会告诉你这个系统是怎么实现的(How),无法准确表述它到底能用来做什么(What),以及为什么要做这样一个东西(Why);而后面这两个问题的答案,才是后续系统所有设计与演进的根因和驱动力。

虽然程序员真的不喜欢重复自己,但冗余也是一种必要的容错手段,好东西真的不容错过:欢迎各位技术同路人加入阿里云云原生应用研发平台EMAS团队,,我们专注于广泛的云原生技术(Backend as a Service、Serverless、DevOps、低代码平台等),致力于为企业、开发者提供一站式的应用研发管理服务,内推直达邮箱:pengqun.pq@alibaba-inc.com。

查看原文

赞 0 收藏 0 评论 0

应用研发平台EMAS 发布了文章 · 2020-11-11

HTTPDNS开源 Android SDK,赋能更多开发者参与共建

为赋能更多开发者参与共建,阿里云HTTPDNS开源 Android SDK,iOS SDK也在做开源准备,不久也将开放给开发者。HTTPDNS是阿里云移动研发平台面向多端应用(移动端APP,PC客户端应用)提供的域名解析服务,具有域名防劫持、精准调度、实时解析生效的特性。

开源介绍

HTTPDNS Android SDK 在原有的HTTP接口基础上,围绕易用性、可靠性、成本等方面为客户端应用提供了以下功能封装和扩展:

  1. 定期更新服务IP,随着应用环境的变化和服务器的更新,定期更新服务IP,可以保障HTTPDNS功能的可用性,避免因为一些网络攻击,导致用户的业务损失。
  2. IP优选,在解析IP之后,通过Socket连接测量服务连接速度,优先使用最快的IP,提供给用户。
  3. IP解析策略优化,通过解析结果的本地存储,提供预解析和IP过期、网络变化时重新解析选项,减少用户获取不到解析结果的概率,提高IP的准确性。
  4. HTTPDNS开源 Android SDK,赋能更多开发者参与共建

=================================降级自检功能,在一些网络极端情况,HTTPDNS服务不可用时,降级为嗅探模式,降低用户请求频次,减少网络请求消耗,在网络变好之后,自动恢复。在服务不可用的情况下,使用初始IP,更新服务IP,及时切换到可用的服务IP。

阿里云移动研发平台团队推出的HTTPDNS在解决了传统域名劫持一级调度精准性的问题的同时,也提供了开发者更灵活的DNS管理方式。通过在客户端合理地应用HTTPDNS管理策略,我们甚至能够做到DNS解析0延迟,大幅提升弱网环境下的网络通讯效率。对于使用HTTPDNS API接口的开发者,您可以在客户端自己定制更高效,并且符合您需求的HTTPDNS管理逻辑。

参与共建

现在移动研发平台团队开源了HTTPDNS Android SDK,使开发人员可以看到它的实现方式,并合理使用该SDK开发运行在本地或其他云上的服务。未来,随着HTTPDNS版本更新,还会陆续开源更多内容,赋能更多开发者参与共建。

目前代码已经在GitHub上正式开放:
GitHub地址:https://github.com/aliyun/alibabacloud-httpdns-android-sdk

查看原文

赞 1 收藏 0 评论 0

应用研发平台EMAS 发布了文章 · 2020-11-10

Android网络性能监控方案

背景

移动互联网时代,移动端极大部分业务都需要通过App和Server之间的数据交互来实现,所以大部分App提供的业务功能都需要使用网络请求。如果因为网络请求慢或者请求失败,导致用户无法顺畅的使用业务功能,会对用户体验造成极大影响。

此外,EMAS对外提供的APM之前并不包括网络监控功能,而网络性能监控作为移动端性能监控的重要组成部分,我们急需补全这部分能力来完善APM的产品功能,进一步满足客户的需求。

“阿里巴巴应用研发平台 EMAS 是国内领先的云原生应用研发平台(移动App、H5应用、小程序、Web应用等),基于广泛的云原生技术(Backend as a Service、Serverless、DevOps、低代码等),致力于为企业、开发者提供一站式的应用研发管理服务,涵盖开发、测试、运维、运营等应用全生命周期。”

问题与挑战

网络性能监控在端上主要包括数据采集和数据上报。我们希望能尽可能采集有用的信息来帮助客户发现、定位和解决网络性能问题。我们面临如下问题和挑战:

  • 首先要解决的是网络请求过程中,哪些阶段会影响请求性能,如果发现网络性能有问题,需要采集哪些数据来帮助用户去定位和解决问题。
  • android上主流的网络框架有okhttp2、okhttp3、okhttp4、volley、retrofit、httpclient和系统提供的httpurlconnection等,在我们不确定客户使用哪个网络库的哪个版本的情况下,如何尽量采集有用的信息。
  • 网络请求各个阶段的数据采集都是离散的,如何保证单个请求各个离散的监控数据能够串联起来,不和其他请求的监控数据混在一起。
  • 由于弱网环境下的网络请求日志往往更有价值,需要尽可能将异常的网络请求日志数据上报到服务端。
  • 并发网络请求时,需要确保在日志上传时尽量不影响客户正常业务。

实现方案

网络性能监控在端上的具体实现主要包含两大模块:

  • 数据采集
  • 数据上报

其中数据采集是整个SDK框架的核心。

整体架构概览:

接入层:

网络监控属于高可用产品的一部分,采用高可用统一接入的方式接入。

插件层:

高可用目前框架是通过插件式的方式集成各个业务,实现networkmonitor plugin集成到APM中,补充APM中网络监控部分。

逻辑层:

主要负责采集控制、数据管理、缓存管理和数据上报。

拦截器层:

整个网络监控的核心。为了采集更多的信息,我们选择使用字节码注入技术来实现网络请求监控功能。对OkHttp、HttpClient和HttpUrlConnection,分别实现Interceptor去采集不同网络库中网络请求各个阶段的数据,并在请求结束时完成采集进行上报。此外,通过自定义gradle plugin的方式,为各个网络库实现Injector和开关,控制在应用构建阶段将Interceptor中各个采集的方法注入到对应网络库字节码的埋点位置,从而实现在运行时网络请求各个阶段采集需要的数据。

数据采集

采集哪些数据

首先需要确定采集的数据范围来帮助我们及时发现网络请求的性能和异常等情况,另一方面也需要有额外的数据来辅助排查问题。所以我们采集的数据主要包括四个部分:

  • 基础数据。
  • 性能数据。
  • 异常信息。
  • 事件序列数据。
基础数据

  • 请求url:对请求做聚合运算。
  • 目标IP地址:对于多出口IP的客户,支持IP地址维度的数据分析。
  • dns解析结果:请求url的域名解析ip列表,用于分析是否存在域名劫持的问题。
  • http code:根据http code确定请求状态。
  • 上行流量:包括整个请求上行header和body的总的流量,包含重试和重定向的上行流量。用于监控上行流量开销。
  • 下行流量:包括整个请求下行header和body的总的流量,包含重试和重定向的下行流量。用于监控下行流量开销。
  • 网络库类型及版本:对于客户更换网络库或者升级网络库版本的情况,可以提供前后的网络数据的差异。
性能数据

性能数据主要是采集整个网络请求中各个阶段的耗时情况来定位慢请求发生的阶段。下图列举了http请求可能出现的各个阶段。

所以性能数据部分需要采集下述各个阶段的耗时数据:

•整个网络请求耗时
• •dns耗时
• •建连耗时
• • •TLS建连耗时
• •数据上行耗时
• • •header上行耗时
• • •body上行耗时
• •数据下行耗时
• • •header下行耗时
• • •body下行耗时

异常信息

异常信息主要是收集网络请求各阶段出现异常时的异常栈的信息。比如常见的java.net.UnknownHostException、java.net.SocketTimeoutException等。

事件序列数据

事件序列数据主要是收集网络请求各阶段的监控事件的信息,另外对于特定网络库的一些特殊的事件的监控,比如okhttp的连接复用、自动重定向和失败重试等对网络耗时有影响的机制。最后将这些事件按时间顺序排列。

比如在okhttp上dns被劫持的场景,我们通过基础数据中的目标IP地址去判断dns劫持情况,这个目标IP地址是在建立连接的时候去采集的。如果第一个请求发生了dns劫持的情况,那这个请求我们能正常识别的dns劫持已经发生。如果后续的网络请求复用了这个连接,因为不会再去建立连接,所以基础数据中没有目标IP地址,这时候就需要使用事件序列数据中的连接复用事件中的连接的url和目标IP地址来判断是不是被劫持的请求。

如何采集数据

字节码插桩原理

字节码插桩涉及到Android的打包构建流程。首先我们看下Android应用程序的打包流程,如下图:

从上图可知,我们只需要在 javac 之后 dex 之前遍历所有的字节码文件,并按照一定的规则过滤修改就可以实现字节码的插桩。

从Android Gradle 1.5.0 开始,Google官方提供了Transform API。通过Transform API,允许第三方以插件的形式,在Android应用程序打包成dex文件之前的编译过程中操作.class文件。

Android编译器中的TaskManager将每个Transform串起来,第一个Transform接收来自javac编译的结果,以及已经拉取到本地的第三方sdk(jar、aar),还有resource资源。这些编译的中间产物,在Transform组成的链条上流动,每个Transform节点可以对class进行处理再传递给下一个Transform。常见的混淆、Desugar等的实现就是封装在一个个Transform中。而自定义的Tranform会插入到这个Transform链条的最前面,所以开启混淆的情况下通过自定义Transform对字节码进行修改也是先修改字节码再混淆。

网络库调研

除了系统自带的网络库HttpUrlConnection,在android平台还有很多优秀的第三方网络库,大部分App开发会使用第三方的网络库来发起网络请求。

从上表中主流网络库的底层实现来看,我们只要支持OkHttp、HttpUrlConnection和HttpClinet的数据采集就能满足主流网络库的性能监控需求。

我们对应用市场上Top1000的App进行了分析,按集成数量排序依次是okhttp3&okhttp4、volley(HttpUrlConnection)、okhttp2和httpclient。其中okhttp网络库占比将近80%,所以我们优先实现了okhttp网络库的监控实现。

okhttp网络库的监控实现

okhttp网络库家族主要包括okhttp2、okhttp3和okhttp4。其中okhttp3版本分布众多,底层实现变化也最多,而okhttp2的底层实现和okhttp3的早期版本相近,okhttp4是okhttp3的kotlin版本的实现。所以我们主要介绍下okhttp3上的监控实现。

上图是okhttp3.12.0版本的实现框架,我们在网络库的具体逻辑里注入代码来采集需要的数据。

okhttp3版本众多,从3.0.0-3.14.9已经有超过40个版本,对于每一个代码注入的位置都需要确保再各个版本上能正常工作。所以实现okhttp3的无痕埋点,版本适配需要耗费大量的工作。

数据上报

数据上报,除了需要考虑加密、鉴权、压缩等方面,还需要能确保尽可能少的丢失日志,同时还需要控制资源的占用来降低对上层业务的影响。具体实现主要包括两方面:

  • 缓存:支持内存缓存和磁盘缓存两级缓存。需要实现业务隔离,多个业务使用缓存功能时可以做到互不影响。
  • 上报:由于APM产生的日志较多,为了控制并发数和内存,我们使用了一个业务共享的线程池和调度队列。调度队列最多缓存10条批量日志,如果超出10条会立即将日志放入磁盘缓存。另外在上报前提供了日志预处理的开放接口方便业务层对日志做处理,比如抽样、聚合等功能。

后续计划

EMAS网络性能监控已经对外开放,产品详情:https://www.aliyun.com/product/emascrash/apm,后续我们会根据客户实际需求去逐步完善功能。下一步计划实现的需求包括:

  • 支持HttpUrlConnection、HttpClient等网络库。
  • 支持body数据的采集上报,让客户可以感知、定位和解决在网络连通性正常,但服务端下发异常数据导致端上业务出现异常的问题。
  • 支持日志数据端上预聚合,降低服务端存储压力。
  • 支持socket请求的监控。

欢迎大家积极留言,提出你们的宝贵意见和建议,非常感谢!钉钉搜索35248489,加入阿里云云原生应用研发平台EMAS技术交流群,探讨最新最热门的应用研发技术和实践。

查看原文

赞 1 收藏 0 评论 0

应用研发平台EMAS 发布了文章 · 2020-11-04

移动端堆栈关键行定位的新思路

阿里云 云原生应用研发平台EMAS 张月(此间)

简介: 崩溃堆栈是我们日常应用问题排查中的重要辅助手段,在移动开发上也不例外,为了支持用户在堆栈上的快速定位,我们面临一个看似比较简单问题:高亮崩溃中的关键行, 辅助用户快速定位问题。

一、前言

崩溃堆栈是我们日常应用问题排查中的重要辅助手段,在移动开发上也不例外,为了支持用户在堆栈上的快速定位,我们面临一个看似比较简单问题:高亮崩溃中的关键行, 辅助用户快速定位问题。

崩溃堆栈关键行: 堆栈中是属于用户开发代码中那行直接引起崩溃的代码。

举个例子:

image

二、 业界方案

业界的竞品基本上是通过 Package Name判断的,在没有 Package Name 的情况下,有的竞品会定位到第一行,有的则会定位到非系统库的第一行。

例如: 友商这种情况下就将关键行挂在了第一行 fastjson 的位置。

image这里容易出现两个问题:

  • Package Name 大多数时候和真正的崩溃包名关系不大。
  • App 组件化,包名不能覆盖一方库,二方库。

为了更好的解决这个问题,我们提出了下面用词频比/词频分的方式来解决问题的新方案。

三、新方案

所以在 Package Name 的基础上,我们还需要一个辅助手段,让我们能够识别这两种情况,从而在关键行定位更精准。

这里我们想到的一个做法就是利用全量的 Crash 崩溃堆栈,计算词频比和相应的词频分,通过概率去优化我们的关键行判断。

实现上分为两个平台。

对于 iOS

主包判断

这个问题,对于 iOS,其实不用考虑用户填写的 Bundle ID, 因为 IOS Crash 天然就自带 Binary Images,我们将用户主包信息预存下来,用于后续判断就行了。

Binary Images

image

直接定位:

image.png

对于组件化的包,我们可以通过 Binary Images 里面的信息统计一下每个包名出现的频率,具体的频率分布统计大致如下图所示,纵坐标代表包名出现的次数:

注:横坐标为包名(这里放不下),纵坐标为包名出现次数

image

出现的频率越低,那么我们越认为他是一方库或者二方库。

对于 Android

对于 Android,情况稍微复杂一点,首先 Android 的 Crash 中其实是不能明确标识包名的,而且 Android 的 Package Name 并不是一个词,而是一长串的以点分隔的包名, 例如

"com.aliyun.emasha.cache"。

如果单纯的还以包名的词频比来做匹配的话,那么就会出现下面的问题

  • 历史数据 只出现 com.aliyun.emasha.cache 的包名, 下次出现个 com.aliyun.emasha.login 的就匹配不上了。
  • 同样是 com.aliyun.emasha 的前缀,匹配到了 com.aliyun.emasha 和匹配到了 com.aliyun.emasha.cache 包名的词频相差很大,不符合常理。

所以还要解决这两个问题

  • 能够尽可能的覆盖未出现的崩溃情况。
  • 随着匹配的前缀越长,需要考虑前面的包名匹配带来的影响。

所以这里要引入包名分级和词频分的概念

  • 包名分级:将包名 split(".") 得到数组,从前往后为 1级,2级,3级这样的分级。
  • 包名词频分:根据包的词频比多级累加算出来的一个评价包名是否是三方库的分数,分数越高,是三方库的几率越大。

但这还不够,如果我们的词频比只是单纯的累加,那么 com 开头的的包名,词频分一定会很高,大于所有的 org 开头的包名,但根据我们的经验,其实不是这样的,我们认为不同级别的匹配,权重应该是不一样的,所以我就拍脑袋想了个权重。

0 5 2 1 1 1

这里举个例子

com.alibaba.aliyun.emas.ha.tlog 这个包名

com 1

com.alibaba 0.3

com.alibaba.aliyun 0.1

com.alibaba.aliyun.emas 0.05

com.alibaba.aliyun.emas.ha 0.02

com.alibaba.aliyun.emas.ha.tlog 0.01

如果匹配到 com 那么词频分为 1 * 0

如果匹配到 com.alibaba 那么词频分为 1 0 + 0.3 5  = 1.5

如果匹配到 com.alibaba.aliyun  那么词频分为 1 0 + 0.3 5 + 0.1 * 2 = 1.7

以此类推

但是在我们的经验中匹配到了 com.alibaba  和匹配到了 com.alibaba.aliyun,后者更有可能是关键行,所以它的词频分按理来说也就更低。所以我们这里做一个符合常理的修正,对于位数过短的匹配,需要后几位的权重做补齐。

最终结果如下

如果匹配到 com 那么词频分为 1 0 + 1 5 + 1 2 + 1 1 + 1 1  + 1 1 = 10

如果匹配到 com.alibaba 那么词频分为 1 0 + 0.3 5 + 0.3 2 + 0.3 1 + 0.3 1 + 0.3 1  = 3

如果匹配到 com.alibaba.aliyun  那么词频分为 1 0 + 0.3 5 + 0.1 2 + 0.1 1 + 0.1 1 + 0.1 1 = 2

看上去是比较符合我们的经验的。

所以这里词频分的最终定义:根据包的词频多级累加算出来的一个评价包名是否是三方库的分数,分数越高,是三方库的几率越大。如果一个包名分级过短,需要把缺失的后面分级的也算上累加,用于增大短包名的词频分。

我们对所有的包做一个词频分统计,可以得到如下分布图

注:横坐标为包名(这里放不下),纵坐标为包名的词频分

image

根据观察和测试,这里把阈值定在 0.2 左右比较能区分用户的包名和三方、系统库。

整体架构

在工程实现上我们也做了一些优化

  • 以前业务数据是存储在 OSS 中的,但是 EMR-OSS 目前文件处理较慢,这里换成了更适合并行处理的 HBase。
  • 只计算增量 Crash 日志, 对于存量的数据,以 HyperLogLog 的形式存储,增量计算后与存量做 Merge。

image.png

四、效果评估

常规的利用 Package Name 做判定: F1 Score

image

使用词频分思路的:F1 Score

image

五、真实效果评估

上面的效果评估只考虑到了每一个包名的情况,在生产因素下,考虑到崩溃行出现的位置,包名出现的频率,以及没关键行的情况,准确率可能会有所不同,所以我们在真实环境做了高亮测试,测试方式为:对线上50个 App,每个 App 取前3条崩溃来做统计,总的准确率如下,可以说是比较高的。

安卓准确率:(33_3-9)/(33_3)*100%=90.91%

iOS准确率:(17_3-0)/(17_3)*100%=100%

总体准确率:(50_3-9)/(50_3)*100%=94%

六、思考

小需求可以做出大深度, 后续我们可以考虑更多跨用户数据的脱敏拉通,理解数据,为客户带来更多的数据价值。

七、接下来的方向

  • 组内算法的朋友说可以通过打标 + CNN 的方式来做深度学习下的三方包名判断, 这个后续可以试一试。
  • 对于凭经验拍脑袋相出来的参数和方程(词频分计算),其实都可以通过打标训练的方式做参数和方程的固定,这也是一个优化方向。

八、写在最后

移动研发平台 EMAS

阿里巴巴应用研发平台 EMAS 是国内领先的云原生应用研发平台(移动App、H5应用、小程序、Web应用等),基于广泛的云原生技术(Backend as a Service、Serverless、DevOps、低代码等),致力于为企业、开发者提供一站式的应用研发管理服务,涵盖开发、测试、运维、运营等应用全生命周期。

欢迎大家移步使用:https://cn.aliyun.com/product/emas

查看原文

赞 0 收藏 0 评论 0

应用研发平台EMAS 发布了文章 · 2020-10-28

端应用研发进入云原生时代

导读:随着技术的发展和各种用户端场景的涌现,业务前台形式变得更加多样,“面向多样化的端场景提供无缝的、一致的数字用户旅程”已经成为了新时代企业应用架构的关键目标,同时它也是当下大前端技术发展背后的核心业务牵引。基于阿里云在过去几年服务海量用户的经验沉淀,本文总结了新的基于云原生技术的端应用研发范式,期望为广大开发者、企业提供云计算时代面向企业业务前台的应用研发方法论。

多样化用户体验( Multiexperience )与大前端

随着云计算、移动化、IoT、AI等技术概念地落地和持续发展,社会的数字化进程在不断加速。Gartner近期发布了新的企业应用架构方法论MASA(Mesh Application and Service Architechture,网格应用和服务架构)[1],融合近5年流行的技术趋势,为广大企业信息化的供应商、开发者和企业用户定义了更广泛的企业数字化应用架构模型。

image.png

与阿里所定义的中台不同,MASA将企业应用拆解为上中下三层,在传统的后端业务能力基础之上,将企业前台,以及用于前后台链接的API网关层也涵盖了进来,通过网格化的架构实现企业的业务流程、员工、服务、内容、设备间的动态连接,以构建匹配现有技术形态和未来技术趋势的更敏捷、灵活、可扩展的应用架构。

伴随MASA,面向企业前台的Multiexperience( 多样化用户体验 )被Gartner明确提出并定义为2020年的十大技术趋势[2]。Multiexperience期望利用多元化的前台技术(移动应用、Web、小程序、可穿戴设备等)全面升级企业面向终端客户的数字化触点,以终端客户为中心构建多元(体验多元化)而一体(架构一体化)的用户界面。Multiexperience与国内所流行的大前端概念不同,但他们背后恰恰有着相通的故事主线。

大前端在国内还没有一个统一的定义,它更偏向一个相对纯粹的技术概念,意指面向客户侧的端技术集合,它的出现始于客户端Native与Web两大技术栈的不断融合,背后核心是跨平台技术在移动、PC、小程序、Web等场景下地不断发展和成熟。

大前端技术栈在Multiexperience这样的业务需求背景下不断磨砺,同时又反向支撑业务不断扩展其面向终端客户的数字化触点的场景和范围。技术拓展商业边界,商业驱动技术变革。面向全端场景,提供无缝的、一致的数字用户旅程是Multiexperience和大前端一脉相通的用户理念。

如今,面向全新的业务架构范式,如何加速新时代下多元化的端应用研发,为业务提供更敏捷而高效地交付呢?云原生技术是最佳选项。

一云多端,云原生技术如何驱动端应用研发

很多人有疑惑,云原生与端测的研发有什么关系,云原生不是一个后端技术域的概念么?其实不然。云原生代表了一种应用构建的方法论:如何最大程度地利用云计算服务模型的优势低成本、敏捷地构建和管理一款弹性的应用。它的关键理念包括:

  • 所有的运行环境透明化,弹性伸缩;
  • 所有的研发流程流水化,高效交付;
  • 所有的基础设施服务化,按量付费;

云原生的研发模型旨在降低业务的技术风险,让开发者可以更单纯地专注于自己的业务。面向端应用场景,云原生技术理念同样适用。

Gartner在2019年定义了一条全新的技术赛道:Multiexperience Development Platform(MXDP)[3],用以描述那些通过敏捷、现代化的技术能力帮助企业高效地实现Multiexperience的研发平台,其能力矩阵示意如下图:

image.png

从MXDP的关键元素构成我们可以看到,除了传统的研发工具类组件外,云原生技术成为了MXDP最核心的技术元素,其中的典型技术包括:

DevOps,驱动端应用的高速迭代

端应用对比传统后端有着典型的差异,以移动App为例,应用本身构建在异构的机型、OS平台之上,运行环境约束较多,依赖大量的后端服务支撑,应用本身的持续集成和交付过程也包含了许多移动场景特有的元素,比如编译环境、兼容测试、内测分发、渠道打包、灰度发布等,这些关键差异决定了端应用必须构建自己特有的DevOps体系。

image.png

研发域:面向端应用的DevOps平台需要解决应用持续集成过程的组织协同和自动化。针对端应用的研发期,成熟的DevOps平台需具备:

  • 面向多端的编译构建环境并实现自动化的软件更新;
  • 可靠,弹性伸缩的构建服务集群;
  • 代码与证书托管;
  • 静态代码扫描;
  • 软件定义的工作流;

测试域:端应用的测试较传统后端应用复杂度大幅提升,除了基础的功能、性能测试外,还需要有面向异构机型、终端、操作系统的兼容性测试,成熟的端应用测试平台应具备:

  • 兼容性测试服务,覆盖主流的机型、设备、操作系统;
  • 性能测试服务,支持各类应用崩溃、ANR、卡顿、IO、CPU、内存等关键性能指标监测和评估;
  • 自动化测试引擎,支持测试用例编写、回放和管理;
  • 远程真机能力,支持设备的云端访问;
  • 智能Monkey与AITest等智能化技术驱动的测试能力;

发布域:端应用的目标发布对象是海量的终端设备,生产发布受应用市场审核限制,因此,可靠、精准、定向的应用分发能力是应用生产分发的关键技术要求,包括:

  • 企业内分发能力;
  • 支持软件定义的灰度能力,支持面向不同的地域、网络、机型、渠道及其他自定义标签进行灰度分发;
  • 面向不同渠道的生产发布能力;
  • 版本管理与归档;

运维域:面向端应用的运维体系应始终围绕问题的感知,问题的定位,问题的修复展开,在传统的Metrics,Tracing,Logging基础之上,我们特别强调面向端的Hotfix的能力,这是区别于后端应用形态的特殊之处。成熟的端运维体系应包含:

  • 面向端应用的APM能力,支持包括启动速度、页面加载、崩溃、网络性能、API性能等在内的监控报警体系,并能与后端APM联动进行基于事务的访问追踪;
  • 面向端应用的远程日志能力,支持实时的终端日志记录和管理,加速问题的远程诊断;
  • 面向端应用的热修复能力,支持针对不同设备平台的代码、资源热更新;

运营域:端应用作为企业业务入口,是企业面向终端用户的关键界面,必须时刻洞察用户的行为、倾听用户的声音,驱动业务的敏捷迭代。面向App的数据分析以及舆情反馈能力是DevOps的关键闭环之一。

数据分析应具备:

  • 面向全端的用户行为数据采集能力,包括小程序,APP,H5,PC,WEB,IoT等;
  • 易用的终端埋点工具:支持代码埋点,自动埋点,可视化埋点等;
  • 开放的数据能力:支持以API方式同步数据,支持与云厂商的计算平台无缝对接;

舆情反馈应具备:

  • 面向全端的用户反馈通道能力;
  • 智能化的应答机器人;
  • 舆情数据搜集和分析;

DevOps为Multiexperience的生产实践带来的关键价值包括:

  • 更短的业务迭代周期

覆盖端应用全生命周期的工作流与自动化能力将带来应用持续交付能力以及跨团队协同效率地大幅提升,进而缩短业务的交付周期。作为企业面向终端用户的入口,更短的业务迭代周期意味着面向市场更快速的反应,这是数字时代商业成功的基石。

  • 更合理的人力资源分配

云原生的工具链与自动化流水线将帮助企业避免耗费大量工程技术人员来维护本地化的工具和系统,同时大幅削减应用持续交付过程的人工环节。企业能够将宝贵的人力资源专注在自己核心业务的生产和研发上。

  • 更稳固的应用交付质量

自动化的终端测试体系以及全方位的监控诊断体系将为端应用提供完整而充分的质量保障,这些云原生服务将为企业节省大量细分领域的专业人员投入,并通过专业且持续的工程技术演进以及智能技术的引进不断优化应用质量保障体系。

  • 更优异的即时用户体验

围绕端应用全方位的行为数据埋点和分析将帮助企业更好地把握产品功能与市场的匹配度,而即时的舆情反馈能力则帮助企业更好地进行用户管理和关系维护。所有这些直接和间接来自客户的声音将直接驱动业务的快速迭代,通过云原生DevOps实现敏捷开发的生产实践。

Serverless & Backend as a Service(BaaS),端应用的运行引擎

Serverless是当下开发者社区最火爆的话题之一,其核心理念即去服务器化:把底层云计算的基础能力进行高维抽象,以API/SDK的方式开放后端能力的访问和获取,无需开发人员配置和部署服务器资源即可获得弹性伸缩、按量付费的后端服务支持。Serverless的技术理念其实在数年前就已出现:后端即服务(Backend as a Service,BaaS)[4]是典型的遵循Serverless设计理念的服务形态,早在2012年BaaS便在开发者社区中传播并因其便捷的使用模型而深受开发者喜爱。比较典型的BaaS服务包括消息推送、用户认证、云存储、云数据库等。

image.png

由于BaaS服务大幅削减了企业在后端研发力量上的开销,其在端应用场景得到了大范围地应用。但BaaS核心解决的主要是垂直场景化的后端能力抽象,并没法支撑业务本身的后端逻辑部分。Function as a Service(Faas)[5]的出现弥补了这一空缺,并使得Serverless的架构范式能够面向端应用场景提供更加完整的闭环。

FaaS是一种软件构建和部署的新方式,基于事件驱动模型,以函数粒度为开发者提供业务代码的托管环境。这种架构模型在数据处理、Backend for Frontend、移动应用、IoT应用和Web应用等场景有较常见的应用空间。

综上我们可以看到,面向应用的Serverless架构包含了BaaS和FaaS两种服务形态,为了完整地支撑端应用的场景需求,成熟的Serverless引擎应包括

  • 消息推送

支持在服务器与客户端间建立可靠、省电的长连接,面向Android、iOS、Web、IoT等端应用提供下行消息推送能力。

  • 登录认证

为开发者提供多维度的安全可靠的端到端身份验证能力,从而降低开发者在登录和账号体系上的开发成本和业务风险。身份验证模式包括邮箱认证、短信认证、号码认证以及主流互联网平台(淘宝、支付宝、QQ、微信、Google等)提供的登录认证能力。

  • 数据同步

提供一个稳定可靠、加密安全的数据同步系统,支持数据在客户端的离线使用以及在线同步更新,以提供业务在移动应用、Web应用以及PC应用间的一致化用户体验。

  • 远程配置

远程配置是面向端应用的持久配置管理服务,通过云端管理配置内容,并实时推送更新到客户端,灵活控制应用的功能、配置及UI实现。

  • 云存储

提供基于API/SDK的便捷的云端存储能力,支持包括文本、图片、视频以及其他由用户生成的内容。

  • 云数据库

基于云端的NoSQL数据库,提供面向各种前端的便捷访问接口,支持实时的数据操作、跨端数据同步和弹性伸缩。

  • 云函数

允许开发者直接将程序托管到云函数平台上,以函数作为最小单元完成事件驱动的业务逻辑开发,通过API方式进行远程访问和调用。

  • AI能力

应用智能化是端应用的关键技术趋势,基础AI能力将成为端应用Serverless架构的基础组成,包括但不限于OCR、人脸识别、语音识别等。

Serverless架构及服务带来的核心价值体现在三个方面:

  • 资源成本
    传统的应用架构模型需要预先购置一批服务器设备,并按照使用周期内的预估业务峰值来进行财务预算,不确定性因素较多,服务器资源的空置也会带来非常巨大的成本浪费。而Serverless的架构模型则实现了按需扩展、按量付费的弹性模型,让企业成本更可控。
  • 运维成本
    开发者不必再关心底层计算资源的容量与日常运维问题,所有基础设施维护将会由Serverless服务商负责解决并对开发者透明。削减的运维成本,弹性的资源使用和可扩展·能力都将帮助开发者更好地专注于业务本身的增长。
  • 研发效率
    完整的Serverless引擎提供了面向端应用的绝大部分场景能力的支撑,使得应用的研发非常便捷并易于维护。而在传统的研发模型下,代码开发、环境搭建、容量压测、集群扩容、应用部署等环节都会带来巨大的时间成本。

低代码,应用研发形态的新变革

云原生技术的出现使得传统业务架构大规模地向云架构转型,软件开发效率在这个阶段也得到了明显地提升。然而数字化时代,各种应用场景地涌现,业务对IT面向市场的响应即时性也提出了更高的要求。在跨时代的技术演进浪潮中,Low-code Development Platform(低代码平台)[6]快速浮出水面,并伴随多样化的端应用场景开始加速普及。低代码技术为软件研发效率带来的不仅仅是提升,更是变革。image.png

对比传统的基于手工编码方式构建应用的模型,低代码平台提供给开发者基于GUI的软件编辑环境,并结合云原生基础设施帮助开发者快速完成应用的搭建。同时,这样的研发模型使得软件研发对软件开发者的技能要求门槛大幅降低,更多的具备一定IT基础概念的人群可以参与到软件开发中,而云原生架构则天然地帮助开发者解决了软件本身的部署、运维等工作。

成熟的低代码平台将广泛应用于企业的生产、营销、BPM、工具应用等场景,其核心能力主要由两部分组成:

  • 可视化应用编排引擎
  • 支持包括Web、移动App、小程序在内的多端应用场景;
  • 支持包括UI可视化编排、业务流编排、逻辑编排、数据编排等能力;
  • 支持组件、模块、模板等模型,有开放化的物料系统和组件市场;
  • 模型驱动,搭配元数据解析引擎(包括多端转译引擎/渲染引擎等);
  • 云原生应用平台
  • 行业化领域模型与元数据管理
  • 代码生成引擎
  • 云原生应用托管
  • CI/CD
  • 丰富的集成与扩展能力

我们可以从施耐德电气与顶级低代码平台公司Outsystems的合作中看到低代码带来的价值:施耐德电气在应用低代码平台后,在短短20个月的时间内快速上线了60款App,其中绝大多数App在10周内完成开发和上线,第一年节省的人工成本达到650人天。低代码技术大幅缩短了传统企业数字化转型的路径。

至2024年,Gartner预计所有应用程序开发活动当中的65%将通过低代码的方式完成,似乎比想象的更快一些,但它确实在持续地发生。在全球市场,我们能够看到OutSystems、Mendix、PowerApps、App Maker快速的成长脚步,未来结合AI与机器学习,我们可以预见真正的“App工厂”的诞生。

求变应变,永不止步成就技术革新

作为国内移动互联网、云计算领域的行业巨擘,阿里巴巴在大前端、云原生领域有着丰富的实战经验。我们从2016年开始逐步将集团内部成熟的应用中间件云化输出,并在2018年推出了移动研发平台EMAS( https://cn.aliyun.com/product/emas ),如今,EMAS已经逐渐成长为横跨多端(移动App、H5应用、小程序、Web应用等)场景的云原生应用研发平台,基于广泛的云原生技术(Backend as a Service、Serverless、DevOps、低代码等),为企业、开发者提供一站式的应用研发管理服务,涵盖开发、测试、运维、运营等应用全生命周期。

image.png

截止到今天,伴随云计算的迅速普及和发展,我们已服务了15万以上的企业与开发者。

在海量的生产实践中,我们也看到了云原生技术在端应用场景下所面临的的关键挑战:

  • 研发心智的改变

对于所有开发团队而言,前后端团队的定义根深蒂固,协同界面已成自然。然而随着Serverless等云原生技术地广泛应用,在越来越多的端应用场景中,开发团队仅需前端开发人员即可以闭环完成应用的研发和上线工作;在应用架构维度,Serverless FaaS带来的是基于事件驱动,无状态,函数式逻辑片段的全新范式,与传统的应用模型有着较大的区别。改变即成本,更关键的是改变背后不是纯粹的技术,还有组织的变革,生产关系的变革。

  • 技术成熟度

无论是Serverless FaaS还是低代码开发,都属于商业导入期的技术,产品化完善度还有欠缺,所能覆盖的场景也有一定的局限性,对于主流的复杂应用场景,Serverless FaaS还需结合传统微服务等架构形成混合式的Serverless应用。在系统可观测性,研发调试便捷性,函数启动性能,函数执行时长等技术关键控制点上依然有较长的路要走。

  • 架构灵活度

云原生能力代表了对云基础设施的高维封装和抽象,抽象即意味着管控粒度变粗,系统的灵活性与定制扩展能力会天然地受到一定的削弱;

虽然挑战巨大,但趋势已现。EMAS BaaS已经成为国内大量移动App的必备基础设施,全球范围内覆盖超过20亿的活跃设备终端,每天的API调用量超过百亿规模;基于EMAS Serverless( https://www.aliyun.com/product/miniappdev ),疫情期间我们看到大量开发者快速地实现了防疫抗疫工具应用的开发,从诞生想法到产品上线历时仅需一周;在企业内部,越来越多的办公应用和表单应用基于低代码平台快速构建,企业生产力得到了大幅提升。参照Hype Cycle[7]的模型,云原生的多项新兴技术已经涌现大量生产实践项目,技术成熟度已然进入了稳步爬坡期。

毫无疑问我们站在了又一个技术纪元的前夜,云端一体,一云多端正在成为前台应用研发的事实标准,拥抱云原生将成为开发者享受云计算红利的最短路径。我们欢迎更多的有识之士加入我们( lingming.yb@alibaba-inc.com ),变革生产力,改变世界。

REFERENCES

[1] Use MASA to Deliver an Agile Multiexperience Enterprise Application Architecture, Gartner, 2019

[2] Top 10 Strategic Technology Trends for 2020: Multiexperience, Gartner, 2020

[3] Technology Insight for Multiexperience Development Platforms, Gartner, 2020

[4] https://en.wikipedia.org/wiki/Mobile_backend_as_a_service, WIKIPEDIA

[5] https://en.wikipedia.org/wiki/Function_as_a_service, WIKIPEDIA

[6] https://en.wikipedia.org/wiki/Low-code_development_platform, WIKIPEDIA

[7] https://en.wikipedia.org/wiki/Hype_cycle,WIKIPEDIA

阿里云 云原生应用研发平台EMAS 杨镔(泠茗)
查看原文

赞 0 收藏 0 评论 0

认证与成就

  • 获得 4 次点赞
  • 获得 1 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 1 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2020-07-13
个人主页被 774 人浏览