阿里巴巴淘系技术

阿里巴巴淘系技术 查看完整档案

杭州编辑  |  填写毕业院校淘宝  |  技术专家 编辑 tech.taobao.org 编辑
编辑

阿里巴巴集团淘系技术部官方账号。淘系技术旗下包含淘宝技术、天猫技术、闲鱼技术、躺平等团队和业务。我们服务9亿用户,赋能各行业1000万商家,并成功主导了11次阿里巴巴经济体双十一技术大考,打造了全球领先的线上新零售技术平台。
我们的愿景是致力于成为全球最懂商业的技术创新团队,让科技引领面向未来的商业创新和进步。
公众号关注:淘系技术

个人动态

阿里巴巴淘系技术 发布了文章 · 今天 17:53

淘宝直播再升级!淘系自研GRTN 新一代多媒体传输网络

相信大家对网络直播已经不再陌生了。

2016年被称为直播元年,基础技术逐渐成熟,引出千播大战。在红海下,纯粹的直播逐渐失去竞争力,不少企业开始走内容垂直化,跟秀场、游戏、电商、广电等内容特点深度结合。其中内容垂直化最为成功的,莫过于电商直播。据一些行业调查报告,2020年中国电商直播市场规模接近万亿元,年增长超过100%,增长势头强劲。2020年S1疫情爆发,电商为病毒隔离贡献巨大,同时疫情也为电商直播购物按下了加速键。

电商体系中,多媒体传输网络处于关键位置,承载着内容中台的基座。

image.png

电商内容体系架构图

电商体系中,内容中台为主要增长引擎。2020年淘宝双十一GMV达到4982亿,淘宝直播带宽峰值超过7T,比去年增长超过1倍。直播玩法、用户体验、系统稳定性都比去年大幅提升,GRTN(Global Realtime Transport Network)新一代多媒体传输网络为双十一的增长保驾护航,整个双十一期间,系统如丝般顺滑。

(淘宝直播专题内容正在更新,欢迎关注【淘系技术】公众号)

GRTN新一代多媒体传输网络架构

多媒体传输网络,是不是就是CDN?答案当然是否定的,CDN只是传输网络的一部分。多媒体传输网络包括内容生产、编解码、内容分发、观看体验、宏观控制。GRTN是一套从生产到消费,从功能到管控的完整的系统。

image.png

GRTN新一代多媒体传输网络架构

内容生产:让直播更好玩

淘宝直播走到现在已经5个年头,主播的能力有了很大提高,我们的权益互动也做了很多创新,今年我们更注重直播的内容,我们希望主播在直播卖货的同时,也能产生很多很有趣的内容,让大家买买买的同时,保持好心情。所以我们重点做了直播游戏互动玩法,使得直播在卖货的同时也能更加有趣好玩。

4444.gif666.gif777.gif

内容生产流内互动的系统主要分为3个部分:功能强大的素材玩法编辑器、灵活通用的脚本编辑器、跨平台渲染计算引擎。编辑器是内容生产的用户界面,提供各种素材、玩法的编辑能力。然而,有时简单的素材和玩法不能满足需求,需要用一套脚本来控制素材和玩法的运行,为了降低脚本开发难度,脚本必须灵活通用。最后所有的素材、玩法要在流里面展现出来,必须依靠渲染计算引擎。

编解码:成本更低,体验更好

S265是直播成本极佳的编解码方案

带宽是直播运营中最大的成本,根据前瞻网估算算全行业2020年的CDN费用支出将超过300亿元,在2025年接近1000亿规模(https://bg.qianzhan.com/trends/detail/506/200715-ec767b9b.html),在保证视频质量的前提下降低带宽是成本控制中至关重要的一环。

相机采集到的视频数字信号通常是yuv格式,每个像素点需要1.5个Byte来表示,以720p 25fps为例,带宽有263.67Mbps,直播1小时总流量有124.4GB,如有100万人观看这场直播,CDN费用高达1.58亿。好在视频图像内部帧与帧之间存在非常高的相关性,采用视频压缩技术去除相关性后,可以将带宽降低到原来的100-400倍;

视频压缩标准主要有ISO(国际标准组织)制定的MPEG系列和ITU(国际电信联盟)主导的H.26X系列,2003年两大组织组成联合专家组(JVT),共同制定了AVC(H.264)编码标准,2013年JVT发布了HEVC(H.265)标准,HEVC 作为比AVC更新一代的视频压缩标准,相同画质下可以节省一半码率.

S265是基于H.265标准实现的软编码器,具有高压缩、高效率、适应场景广三大特点,对比业界开源的X265可节约20%以上的码率且编码速度提升100%-600%;目前已在淘宝直播、优酷视频、阿里云MTS、VMate、钉钉会议等业务中上线使用;

S265的优化思路包含两个方面,一方面从码率控制、编码工具两个方向优化编码质量,另一方面从快速算法及工程优化两方面优化编码速度,下表可以看到,S265相比X265和X264都有更高的码率优势或速度优势;

image

下面是一个demo视频,左边是S265的压缩结果,右边是X265的压缩结果。可以看到,同等码率下S265的地面瓷砖的纹理及水纹更清晰(语雀有二次压缩,原片更明显)

output.mp4

左边S265,右边X265

从另一个角度看,相同质量下,S265的码率可以大幅节省,从而降低带宽成本。下图左侧是X264的压缩2400kbps,右侧是S265 1200kbps的结果,码率相差一倍,S265的质量还更好。

45_x264_ali265.mp4

过去一年,淘宝直播的在线规模增加超过一倍,而CDN的带宽成本几乎未增加,这还是在FY20相比FY19已经降低一倍的前提下发生,S265起到了至关重要的作用。

S265降低成本前提下不降体验

虽然S265大幅降低了直播成本,但体验并未降低。

在清晰度方面,淘宝直播S265 在720p分辨率下的平均推流码率在 800kbs以下,但大盘监控的平均psnr大于42db。在今年双十一还上线了1080p高清直播,满足用户极致高清的需求。

在流量控制方面,S265支持秒级码率调控,可以让GRTN流量调度在1秒内完成对大盘流量的控制,实现CDN流量的全面掌控;

在编码延时方面,S265实现了低延时压缩模式,相比X265 Medium模式降低了70%的编码延,且编码质量几乎不损失。

最后,伴随着码率降低,网络传输的压力也相应下降,用户体验的卡顿率和秒开指标都有显著提升,过去一年淘宝直播的卡顿vv下降了25%,秒开率绝对值提升了1%,跟码率下降有直接的关系。

内容分发:二网合一的传输系统

在流媒体领域,提到直播技术,往往会想到RTMP、HTTP-FLV、QUIC-FLV、SRT,只有提到连麦、通话、视频会议,才会想到RTC(webrtc)。如今淘宝直播架构整体升级,一改往日印象,将直播全链路跑在了RTC之上,实现了直播网和通信网的融合,完成了二网合一。

统一架构后,实时音视频通话和直播两大业务,使用统一套代码,一套运维体系,减少维护成本。同时,淘宝直播针对业务特点,对融合网络架构进行了深度定制,自研了适合直播业务的拥塞控制算法和网络传输策略。针对 WebRTC 中网络传输的核心,淘宝直播对拥塞控制算法的探索层层深入。从基于特定网络场景的深度定制优化,到系统性的参数探测优化,再到基于神经网络的拥塞控制算法相关的前沿探索,深度定制的优化落地,使得推流端卡顿总体下降 40% ,延迟也下降了 12%,主播推流更加平滑稳定;前沿探索的学术结果,也已经两次由网络方向国际顶级会议 MobiCom 接收和发表。

低延迟传输是一个综合性问题,对于直播来说要兼顾成本,体验,延迟,需要客户端,服务器配合,基于线上数据不断迭代。相关控制算法从webrtc完整模块化剥离和重构,性能是webrtc原来实现的2倍以上,针对直播大的I帧场景深度定制优化,同时兼顾秒开和延迟,追求最大吞吐率。在网络小范围抖动情况下不受影响,最大支持20%丢包和500ms内的抖动。相对于去年同期指标,卡顿率降低79%,卡顿VV降低44%,秒开率提升32%,延迟和首帧到达时间降低100多ms。

image.png

淘宝直播与其他直播应用对比

通过用秒表内容推流,拍摄推流和播放内容的方式,测得端到端延时,手淘基本在2秒以下,而行业内大部分直播软件还是FLV技术,延时通常在5秒以上。通过严格的AB测试证明,端到端延时降低,对促进GMV有正面效果。网络好时,对比卡顿没有意义,大家卡顿率都为0,因此通过网损仪增加30%丢包、100ms延时测试,卡顿情况就不一样了,由于RTC有拥塞控制、网络抗丢包策略,30%丢包完全无卡顿,而FLV直播则有较高的卡顿率。

后续会继续在统一的直播通信网上优化,不断提高淘宝直播的用户体验,敬请期待。

观看体验:真实还原现场

阿里集团CTO程立分享了他购买古琴的经历,买古琴不能通过常规的图文描述来分辨古琴的好坏,卖家将程立引导到直播间,通过主播讲解,在直播间听声音来分辨古琴好坏。买到琴后发现琴的声音跟直播间里听到的完全一样,CTO对淘宝乐器直播间的音质大加赞赏,这种所见即所得的感觉是直播最大的优势。

“让画面更清晰,让声音更真实”,是淘宝直播的极致追求。淘宝直播通过自研3A、智能降噪、高音质模式、窄带高清等技术,克服生产设备、观看设备及网络条件多样性适配困难,为主播提供低成本直播方案,为观众打造高清音视频体验。

音乐直播间高保真体验:

音乐直播间.mp3

电商直播中,讲解声音的清晰度直接影响沟通效率,因此要尽量屏蔽干扰声音,降噪能力至关重要,淘宝直播团队在智能降噪上深入研究,在技术上创新,比传统技术降噪能力更强,降噪后声音可懂度更高。

降噪前原始语音:

原始语音.mp3

通过AliDenoise智能降噪后的语音:

AliDenoise语音.mp3

在画质上,淘宝直播团队通过去抖、降噪、超分等技术,实现画质增强。并且借助S265编码器高压缩率的优势,我们以业界720p的码率实现了1080P分辨率的高清直播。

720p_1080p.mp4

左边720P,右边1080P

宏观控制:大象也能跳舞

无论怎么设计,系统的复杂度都会逐渐增加,变成一头臃肿的大象。一般的系统,牵一发而动全身,平时已不敢随意变动,更何况大促等关键时刻。然而淘宝直播今年打造了宏观控制系统,让这头大象灵活起来,数据系统如同大象的眼镜、智能策略系统如同大象的大脑、任务执行系统如同大象的四肢,而业务策略配置系统如同驯兽师手里的指挥棍。

宏观控制系统将复杂系统闭环,使得整个系统能观能控,增强了系统的鲁棒性。宏观控制系统的输入是当前主播的编码码率和直播效果等;基于blink搭建的多数据源自纠错的实时数据平台作为检测环节将当前的在线主播数、在线观众数、CDN带宽、以及预测的接下来一段时间内的各个数据清洗统计后输入至决策系统;决策系统融合了限峰策略、时间策略和大主播策略等多种策略,结合数据平台的反馈数据作出最优决策后通知执行模块进行调控;基于集团多维消息群发中间件MASS与长连通道ACCS实现的执行模块会实时调控主播的编码码率、观众观看的清晰度等,实现提高带宽利用率、提高用户体验、降低成本、确保稳定的目的;客户端编码器支持实时动态调整编码码率和智能码控档位,支持帧级实时调控,码率调控秒级生效。宏观控制系统让资源管控更加弹性,在我们无法准确预见未来时,申请资源以及准备资源是一个大难题,有了宏观控制系统情况后,不用为资源预估不准而犯愁,宏观控制系统可以根据实时数据进行预测并且弹性地调整人均消耗的资源。

image.png

宏观控制对带宽调整的效果

在今年双十一期间,宏观控制系统通过上下调整码率等策略,实现了人均消耗带宽在平时的0.5倍~1.5倍之间浮动。再也不用因为在线人数偏低而浪费带宽,也不用因为在线人数偏高而导致部分用户被限流,值班同学可以安心地边吃零食边看直播了。

内容生产通过AI等技术,产生更有趣的直播内容,然后通过高效率的S265压缩算法编码,得到较低的音视频码率,在然后通过去中心化的RTC网络分发到各个观众,最后通过高质量的观看体验,真实还原现场,整个系统需要宏观控制带宽、质量,需要有一个系统从大局控制。

今年淘宝直播全方位升级换代,整个系统内容比较多,接下来将会对这一些列技术展开描述,敬请关注后续的子主题。

(淘宝直播专题内容正在更新,欢迎关注【淘系技术】公众号)
查看原文

赞 0 收藏 0 评论 0

阿里巴巴淘系技术 发布了文章 · 11月25日

阿里亿级长连网关的云原生演进之路(2020最新沉淀)

导读

AServer接入网关承载整个阿里集团的入口流量,负责亿级用户的长链保活,支持上万路由策略转发,是连接上亿用户与后端几十万服务节点的桥梁,在今年双十一需要支撑亿级在线用户、千万级QPS、生效上万条API管控策略,做到了安全可靠的转发路由,并保障了用户体验如丝般顺滑。

在大规模业务流量与管控支撑的背后,需要对系统每一个细节的精确把控,消除每一个潜在的风险点。

借助云原生架构可以极大地简化运维操作,降低了潜在的风险,今年双十一阿里AServer接入网关上千台规模的Pod平稳扛过峰值。本文主要介绍阿里AServer接入网关如何从上一代架构拥抱变化,全面云原生的演进之路。

(更多干货请关注【淘系技术】公众号)

一、架构演进背景

每年双十一大促都是对阿里所有服务最严峻的考验,尤其对AServer接入网关来说,作为阿里集团第一道门户,需要抵御大促峰值带来的流量洪峰,清洗攻击流量,所需集群规模巨大。

巨大集群规模,以及对机器性能极致要求,导致了运维上的复杂性;随着接入业务的增多,所支持的业务场景扩宽,业务对路由策略的灵活性、生效的实时性要求变高,对路由策略的动态编排能力有着强烈诉求;由于业务的多样性,业务线不同封网节奏,以及故障隔离性,衍生出对流量隔离的稳定性诉求。

运维的复杂性、动态编排的诉求、流量隔离以及对性能的极致要求,推动着AServer接入网关不断演变和成长,紧跟业务的发展步伐的同时,逐步降低运维成本的,增强系统稳定性,能够一次又一次经受住双十一的考验。

1.业务背景

作为阿里集团AServer接入网关,承载整个阿里集团入口流量,最开始支持域名转发策略的tengine网关,根据域名 转发到后端不同服务,业务形态相对简洁。

来到All in无线时代,为优化手机端侧的用户体验,同时降级服务端人员的开发成本,集团自研了MTOP(Mobile Taobao Open Platform)API网关,为客户端和服务端提供了一致的API平台,相同的域名,仅通过URI携带的API信息转发到对应业务,接入网关需要支持按照API(通过URI区分)的路由转发能力,几年时间迅速增加到数万规则。

随着业务发展越来越精细化,期望对同一API下的不同业务场景进行细分,如针对双十一大促会场的来源,手淘、支付宝、其他外投页面等场景进行更精细化控制,为适应业务发展,网关需要支持精细化的管控能力,根据业务请求参数、请求头进行管控和分流。每一个请求都要从上万灵活的配置规则中匹配出唯一的路径,同时又要保持极高的性能,是一件极具挑战性的事情。

image.png

(业务模型图)

2.运维体系背景

最开始基础配套的基础设施并不完善,网关层基于tengine搭建,最简单快速的方案便是使用物理机,部署进程和配置即可完成服务搭建。随着业务增长,配置管理就成为瓶颈,网关层需要一个强有力的配置管理平台,通过标准化的方式生成业务配置,配套自研的配置管理平台把配置划分为应用配置、公共配置管理、证书配置三部分。

  • 公共配置:通过Git版本管理方式生成tengine运行的基本配置,如启用模块配置,tengine运行逻辑配置
  • 应用配置:通过标准的模板生成业务所需的tengine配置
  • 证书配置:由于证书存在有效期,为了防止过期时忘记更新,还承担了证书自动更新任务

最初的系统部署架构:

image.png

该方案可以实现业务自助接入,通过配置管理平台的模板生成 tengine 配置,再由定时推送到网关机器并进行进程的reload,生效配置。

通过这种运维方式,不依赖基础设施,可以快速演进,但随着业务增长以及集群规模的上涨,物理机的运维方式弊端逐步显现,野蛮生长的时代过去,作为阿里服务入口,稳定性成为了重中之重,物理机的二进制发布依赖人工部署,需批量执行命令安装rpm包,并且分批restart进程,这一切都是黑屏操作完成。

此种运维方式显然无法满足现在的稳定性需求,通过手工发布,极易出现误操作导致系统性故障。另外物理机运维很难进行一致性保障,包括二进制的一致性,机器本身环境的一致性检查(如内核参数等),过去的手工运维方式显然已经跟不上时代的步伐。

解决发布和环境一致性问题的最优方案便是容器化技术,随着集团基础设施的完善,接入网关容器化改造扫除了障碍,把不变量(系统配置、二进制)打包成一体进行发布,把变量(应用配置、公共配置、证书)继续沿用配置管理平台进行管理,配合容器化技术进行调整。

容器化改造后的发布和配置变更流程:

image.png

容器化架构,简化了建站、扩缩容操作,发布效率有了极大的提升,增加审批流程,系统化卡点,避免了人为操作可能导致故障,发布流程还可对接监控系统,自动告警并暂停发布。

3.核心问题

随着电商业务发展越来越快,规模化达到瓶颈以后,业务就会有更多的横向扩展,精细化程度越来越高,迭代速度也随之变高,网关层适应业务的变化的成本也来越高,由此带来的核心问题:

  • 运维操作复杂性:由于对性能的极致要求,网关集群对机器有着特殊的要求;由于网关配置管理的特殊性,导致了运维操作的复杂性;特殊性的存在无法很好对接集团现有运维体系,需要进行运维体系的升级;
  • 动态编排能力不足:随着接入业务的增多,所支持的业务场景扩宽,业务对路由策略的灵活性、实时性要求越来越高,静态配置不论生效的实时性还是策略灵活性都难以满足业务发展需求,需要支持路由策略的动态编排能力;
  • 流量隔离成本较高:缺乏轻量级业务范围隔离能力,通过新建集群实现的成本过高,为支持业务线不同封网节奏,以及支持故障隔离性,需要轻量级的多集群流量隔离方案。

云原生近年来的飞速发展,也为网关层提供了更好的架构选择。

二、云原生架构

为解决接入网关现存问题,结合集团业务场景以及云原生的开源体系,开启了AServer接入网关的云原生演进之路,为了分步验证,分解三个阶段逐步实现:运维体系升级,服务治理&网关Mesh化,南北向架构拆分。接下来对每一个步骤进行详细的演进说明。

1. 运维体系升级


1.1 待解决问题

通过容器化升级部署,极大的简化了部署运维方式,能够解决当时最突出的问题,但仅仅改造部署方式还远远不够:

  • 由于接入网关有着特殊性(如需要对接配置管理平台,有着大量的VIP需求),无法直接对接集团的基础设施,开发了独立的定制化化的运维工具,扩缩容流程需要多个基础组件通过非标接口配合进行,极大的影响了运维产品的迭代效率
  • 故障机置换机器等操作,依赖外部系统轮询检测,并且集团基础设置系统跟定制运维平台对接才能处理,有较大时延
  • 运维操作脱离集团运维体系

1.2 演进思路

随着集团内针对云原生应用设计的统一基础设施ASI(Alibaba Serverless infrastructure)的逐步完善,提供了基于原生K8S API的完整云原生技术栈支持。

云原生方案可编排能力很强,通过自定义实现k8s扩展,非常容易抹平网关层的特殊性,ASI 原有的自动化运维手段,可直接应用于网关层。

网关层对机型的特殊性,可以通过节点池划分来实现,网关机器节点池可自定义机型以及内核参数,消除网关运维上的特殊性,统一管理运维。

1.3 演进方案

通过 k8s 自身的 Controller 扩展能力,自定义容器编排,在扩缩容时可以监听Pod变更事件对配置管理平台进行机器增删操作,同时也可以挂载/卸载VIP,抹平运维上的特殊性,并且所有资源都通过声明式API定义,方便运维。

对于网关运维,还需要保留一个非常简单的运维平台,仅做建站之用,对比普通应用,网关建站需要在对应区域创建VIP,进行域名绑定等操作,轻量且易维护:

image.png

通过进行ASI化改造,使得接入网关的运维融入集团ASI云原生体系(提升交付效率,去除特殊化运维),通用能力下沉至ASI和基础系统,同时具备了风险隔离、自恢复、弹性能力

  • 风险隔离:使用Sidecar能力隔离安全和工程能力,避免二者的互相干扰,安全能力出现异常,只影响流量清洗,降级安全能力后,不至于服务整体不可用;
  • 自恢复:对于容器自愈能力,原有容器化方式依赖外部应用的轮询检测,不论是准确性和实时性达都有所欠缺,升级ASI后,通过容器自身的检测,可在3-5分钟内识别并置换故障容器;
  • 弹性能力:自动弹性能力,通过ASI的改造,各系统的对接方式可以使用标准的声明式API,整合集团内各组件,极大的简化了扩缩容操作,为自动弹性提供了支持;
  • 屏蔽机型差异:通过节点池划分,针对网关应用可使用特殊的机型,底层配置屏蔽差异,无需特殊操作。

2.服务治理&网关Mesh化

2.1 待解决问题

随着网关层接入的业务类型增多,需要支持上万条API路由规则,而且路由策略也越来越精细化,使用tengine原生能力无法满足业务需求。通过定制开发tengine模块,非标的定义方式,过去几年中可以很好适应业务的发展,但随着业务诉求愈发精细化,定制开发tengine模块的成本也逐步变大

image.png

原有架构

  • 路由配置通过模块配置+原生配置组合而成,多个模块配置共同决定路由策略,分散的配置无法对一个请求完整的路由路径的识别;
  • 通过功能模块划分,想要按照业务粒度的进行增量更新较难实现;
  • 基于tengine架构,动态变更能力不足,域名变更每日定时推送配置并生效,无法满足业务快速迭代需求;
  • 非标准协议直接跟不同管控平台直接对接,对接成本较高,并且不容易收口管控;
  • 对于不同业务线(如淘系、优酷),要做到资源隔离,由于多数模块配置使用静态的公共配置,建站成本较高。

2.2 演进思路

如何动态编排、精细化的控制路由策略,是在云原生体系下首要考虑的问题。参考对比业界网关层做法,如Kong,Ambassador等,主流网关数据面实现都是基于nginx或者envoy,不同产品的扩展性、动态编排能力、成熟度的对比情况:

image

从动态性、标准性、性能方面综合考虑,使用envoy作为数据面更适合云原生演进方向:

  • 动态性和灵活性
  • envoy实现的标准xDS协议足够灵活,并且可全部动态配置和变更
  • envoy扩展性足够好,可通过实现filter扩展实现集团内特有的路由逻辑
  • 标准性
  • istio标准组件,社区支持力度大,发展迅速
  • 阿里集团mesh化使用istio技术方案,使用envoy作为数据面选项能够跟集团业务管控的统一化
  • 性能
  • C++实现,性能足够好,而开发效率比tengine高

而envoy不足之处在于作为istio标准组件,东西向路由能力较强,作为南北向需要进行一定性能和稳定性优化,但长远来看,动态性和标准性更为重要。

2.3 演进方案

复用集团Pilot作为统一的控制面组件,实现网关自身的Mesh化:

image.png

控制面为提供各透出的业务产品写入,需提供一层管控逻辑进行权限的收口,各产品通过k8s声明式api写入路由策略,再由Pilot控制面转换为xDS数据面协议,实时同步给数据面Envoy,南向路由网关的实现架构:

image.png

由于集团的配置规模较大,数十万的路由规则和数千应用,几十万业务节点,开源体系鲜有如此规模。Pilot + Envoy方案应用于南北向网关后,需要对原生组件做一定的优化和定制,以解决规模化引起的性能和稳定性问题:

  • Pilot支持SRDS协议:解决大规模API配置导致的线性匹配性能问题
  • 增量配置更新:实现并完善控制面增量更新能力,避免全量更新导致变更半径扩大风险
  • 节点变更优化:解决几十万业务节点的状态变更对控制面和数据面性能影响
  • 扩展定制:针对集团特有的路由规则,定制filter实现

通过对开源体系进行定制和优化,可以很好的对接集团内的需求,通过灵活的配置组合,通过快速迭代控制面透传的能力,实现集团内不同业务的特殊需求。

3.南北向拆分

3.1 待解决问题

网关作为用户跟业务的桥梁,对用户端保活长链,协议优化,让用户尽可能快速稳定的连到集团;对业务支持灵活的路由和熔断限流策略,负载均衡。虽然连接保活跟路由转发作为网关的整体能力透出,但二者的迭代效率的诉求,以及业务特点都有较大差异。

在一些大促活动场景,即使有预期外的流量洪峰,网关层作为保护业务服务的屏障,仍然可以做到稳如磐石,依赖于高性能和水位的预留。考虑到保活长链,协议优化有这较长的迭代周期,性能极高;路由转发和流量清洗由于策略灵活复杂,资源消耗自然相对较高,如把二者进行架构拆分,可以极大的提升整体资源的使用率。

3.2 演进思路和方案

把协议卸载、长链保活等跟客户端交互,并且能够保有极高性能的模块,单独拆分为北向集群,由于性能很好,只需要少量的机器,便可筑高坝挡洪流;对于跟业务路由策略相关,以及安全清洗能力,消耗性能较多,拆分到南向集群,通过北向的高坝保护南向集群不会过载,南向集群可减少预留水位,进而提升整体的资源利用率,如此可做到即能够提升资源利用率,又可进行灵活配置适应业务快速发展的需求。

image.png

4.整体架构

通过三个阶段演进,终局架构图如下:

image.png

AServer接入网关云原生架构

  • 统一控制面:通过集团统一控制面进行服务接入、服务发现、熔断限流控制,起到变更收口统一处理的作用;
  • 北向连接层:基于tengine承载亿级在线用户和流量洪峰,起到高水坝作用,提升南向路由层资源利用率;
  • 南向路由层:基于Envoy通过Pilot转换xDS协议动态下发路由策略,实现动态编排路由、轻量级流量隔离方案;
  • 云原生基座:运维操作建立在集团统一基础设施ASI,屏蔽网关差异性,降低运维复杂性。

三、未来

阿里AServer接入网关一步步向云原生演进,每次演进都是基于长久以来困扰我们的问题,但又不仅仅止步于解决问题,同时基于当前时代的解决方案,云原生架构改造也远不是终点,云原生的优势也尚未完全发挥。技术的升级最终是为产品服务,云原生升级之后,让我们有了一个强有力的引擎,接下来需要做的就是利用这个引擎改造产品形态,让基于网关之上的开发者最终受益。

1.产品整合

什么样的状态才是一个网关产品最好的状态呢?开发者每天都在使用,但又无需关心网关的存在,这样存在感最低的状态或许就是最优的状态。当前接入网关从产品形态上暴露了一些实现细节,一个入口应用上线需要通过若干不同系统交互才能完成接入,在云原生改造完成后,可以更好的实现All in One,产品上做到一体化和闭环。

2.快速弹性

虽完成ASI Pod升级改造,可自动化执行故障机置换,机器迁移等操作,降低了运维成本,但上云最重要的一项能力就是快速弹性,如可以在双十一峰值大促前快速扩容,大促过后快速缩容,可极大减少为准备大促所保有的机器资源,从而节省巨量的成本。当然其中要解决的问题也很多,如安全性可靠性,弹性的实时性,这都需要配合云的基础设施共同建设,真正发挥云上的优势。

加入我们

淘系架构与基础服务团队

致力于为淘系和阿里提供基础核心能力、产品与解决方案:

  • 下一代网络协议QUIC的实现与落地 - XQUIC
  • 自适应高可用解决方案与核心能力 - Noah
  • 新一代业务研发模式平台 - Gaia
  • 支撑整个阿里的移动中间件体系(千万级QPS接入网关、API网关、推送/消息、移动配置中心等)

团队大牛云集~~ 想要加入我们,请邮件简历至:miaoji.lym@alibaba-inc.com

(更多干货请关注【淘系技术】公众号,每日更新阿里工程师技术干货)
查看原文

赞 1 收藏 0 评论 0

阿里巴巴淘系技术 发布了文章 · 11月24日

在千亿的成交额背后,前端工程师是如何做“资损防控”的?

前言

资损 —— 顾名思义就是平台发生了与用户或客户心理预期不符、直接或间接产生经济损失的场景。

一直以来,资损问题就在我们的生产环境中不断发生,而且随着业务的规模和疆土不断扩大,经济损失的规模也在不断扩大,这直接对平台、客户和用户都产生了非常不良的影响。尤其在某一时间段连续发生高资损风险问题,恶劣程度上升到集团,对平台的生产和运营产生很高的负面影响,所以大家高度重视资损风险的防控。

本文希望通过我们的思考以及淘系双 11 的实践为大家提供一些资损防控的经验参考,也欢迎大家提出宝贵的意见。

(更多干货内容请关注【淘系技术】公众号,每日更新阿里工程师技术干货)

探索之路

在资损防控方面,服务端比前端起步要早,而且做得也非常专业,比如各种离线或实时的容灾幂等检查、链路对账告警、关键配置巡检、关键标巡检等等。

然而对于前端而言,阿里淘系技术部是从 2019 年双 11 前夕开始才开始重视起前端资损防护问题,所以一年前并没有沉淀什么产品化方案,当时能采取的手段就是对案例的总结、对问题的定义、对程度的定级、对红线的定论,通过一些规章制度、学习考试的手段来强化资损防控的文化意识,通过一些人肉盘点、case by case 的人工预演方式来规避资损风险保障业务的稳定。比如下文,就是人工预演这个很直接的土办法的介绍。

人工预演

由于缺少产品化手段,去年的双 11 、双 12 等大促,前端采用的都是人肉盘点、人工预演的土办法来做保障。我们分析了前端所有可能出现的资损风险点,并制定了一套前端的专属资防规章制度和风险编码表,并围绕这些资损风险点,盘点所有参与双11的业务前端代码,对资损问题的识别、预防、止血和恢复过程进行详细的人工预演。

印象中 2019 年双 11,前端 C 端资损防控,总共进行 6 天,每天 2 场(下午与晚上),每场平均 3.5 小时,大概 4 位评委,共进行 73 例预演,每例预演大概 15 分钟且至少 2 位预演者参与,耗费人力总成本均值在 200 小时(折算 25 人日),这个数字相比双 11 整体的人力投入水平来说,也是非常恐怖的。

通过上述方式,过程中我们属实提前发现了一些资损风险问题,虽然最后每场大促线上都没有出现资损问题,但这个土办法在过程中人力和时间消耗还是非常恐怖的,而且防控效果如何完全依赖当时现场的评委 review 的效果好坏。由此可见,人工预演这种方式不仅时间和人力成本过高,而且防护效果有限,并不适合作为长期的防控手段。所以,我们向前探索准备通过一些产品化的手段来解决防控效果和成本问题,就有了如下的一些尝试。

前后端对账

如上文所提,受人工预演方式的成本、防控效果限制,我们去年双 12 之后开始尝试资损防控的产品化方案设计。根据以往权益营销活动出现过的资损案例来看,当消费者看到的权益信息与实际到账的权益信息不一致时,容易引起大面积客户投诉。譬如:

  • 某短视频业务在权益发放时,在消费者领取成功单品优惠券时错误地表达成了红包;
  • 某红包发放业务错误地使用红包列表接口作为中奖结果表达,发现时长长达10.5小时

对于上述这类权益信息前台展示和后端发放不一致的问题,及时的监控报警对于止血、控制资损规模至关重要。为此,我们针对类似问题为业务产品的生产阶段设计了一套前后端对账的产品化方案。

前后端对账的整体思路如下:

image.png

对账方案整体涉及采集层统一接入、数据实时处理对账以及报警订阅,具体如下:

  • 接入层:前端封装统一的 SDK ,覆盖 web、weex 和 miniapp,在页面端采集权益的关键信息;
  • 数据层:基于 Blink 进行数据实时处理,存储到 SLS 日志以及 METAQ 消息,并通过后端平台订阅日志消息进行实时对账;
  • 应用层:订阅权益的对账消息并打通实时报警流程,以及通过 SLS 日志,查看权益的实时大盘以及模块治理。

然而,项目上线一段时间后,我们发现效果并不如预期:

  • 一方面,由于前端 SDK 对业务代码是有一定侵入性的,所以各方业务在接入前后端对账时,或多或少还是存在一定的成本。尤其是对一些稳定的线上老业务,反而容易在改造时引入新的问题;
  • 另一方面,前端 SDK 采集的权益信息无法直接从 UI 展现层识别(金额可能被截断),从报警情况来看,发现的问题均是各方的业务开发同学上报错权益字段而非真的前后端权益不一致导致的误报。

从实际表现来看,我们原本期望用前后端对账的方式能够及时发现业务产品在生产阶段中权益信息在前端表达和服务下发不一致的情况,然而这套方案由于前端拿不到 UI 的利益点字段、问题发现率很低且存在一定接入成本等原因,并不能满足我们的需求,我们只能继续探索其他的资损防控手段。所以我们把目光聚焦到业务产品的研发阶段,看看能否从产品的研发阶段中探索出一些资损预防的产品化手段出来,所以就有了以下的尝试。

静态代码扫描

在尝试前后端对账方案不足预期后,我们开始重新思考:人工预演的方式可以帮我们发现潜在的资损风险问题,但其主要问题在于需要投入大量人力和时间成本,那么为什么不想办法降低这个成本呢?

为此,我们从代码的 CcdeReview 过程中摸索出了一种 基于 AST(Abstract Syntax Tree,抽象语法树)的前端代码静态扫描方案,可以在一定程度上规避金额计算、数字造假、数字歧义、文案过期等问题。这种机器替代人为 CodeReview 的方式,不仅省去了人力成本,而且还为 CR 的质量提供了一道基准保障。

静态代码扫描的整体方案思路如下:

代码扫描.png

其背后具体的原理介绍如下。

AST

在计算机科学中,抽象语法树(Abstract Syntax Tree,AST)或简称语法树(Syntax tree),是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。

这是摘自百科上对 AST 的一段解释,我们再来看一个 code ⇌ AST 相互转换的简单示例:

image

如上所示,代码片段 var str = "hello world" 被拆解成了多个部分,最终以一棵树的形式表示出来(如果想查看更多源代码对应的 AST,可以使用神器 astexplorer 在线尝试)。

代码扫描的基础正是建立在仓库代码的 AST 解析和遍历之上的,为此,我们需要借助 Babel 来完成这部分工作

Babel

Babel 其实是一个 JavaScript 编译器,主要用于在旧的浏览器或环境中将 ECMAScript 2015+ 代码转换为向后兼容版本的 JavaScript 代码。

简单来说,为了将 ES2015+ 代码转换成向后兼容版本代码(比如 ES5),Babel 每次都需要先将源代码解析成 AST,然后修改 AST 使其符合 ES5 语法,最后再重新生成代码。总结一下就是 3 个阶段:

parse -> transform -> generate。

由上可以看到 Babel 不但完成了 AST 的解析工作,而且由于其编译 js 代码的使命,它还提供了一套完善的 visitor 插件机制用于扩展。有关 『如何自定义 Babel 插件』,可以查看这份 Babel 插件手册。根据手册,我们就可以使用以下代码添加自定义规则来完成代码扫描任务:

image

自定义规则

介绍完 AST 和 Babel 后,我们再回到资损防控问题上来。根据以往的经验来看,前端容易造成资损/舆情的代码往往有:

  • 金额赋默认值
  • 金额计算
  • 数字造假、固定金额/积分
  • 过期时效文案
    ...

因此,我们就可以根据上述这些 case 自定义规则来编写 Babel 插件。就拿 『金额赋默认值』 为例,我们可以列举日常代码中的一些 bad cases,然后使用 astexplorer 分析其 AST,最后再针对性地编写匹配规则即可。

image

case 1: 直接赋默认值

image

根据上面的 code vs AST 关系图可以看到,我们只要找到 VariableDeclarator 节点,且同时满足 id 是金额变量,init 是大于 0 的数值节点这两个条件即可。代码如下:

image

case 2: ES6解构语法赋默认值

image

观察上面的关系图,我们可以得出结论:找到 AssignmentPattern 节点,且同时满足 left 是金额变量,right 是大于 0 的数值节点这两个条件。代码如下:

image

case 3: "||"运算符赋默认值

image

上图的规则同样也不复杂,但需要注意一点:实际代码中,= 右侧的赋值表达式可能会复杂的多,甚至包含了一些逻辑运算。因此,我们需要改变策略:遍历右侧的赋值表达式中是否包含 "|| 正数" 的模式。代码如下:

image

通过上述的3个例子,我们就已经能把绝大部分 『金额赋默认值』 的代码给扫描出来。其他的一些场景也是如此,只要根据代码生成的 AST 找到规律,然后编写对应的 Babel 插件即可。

小结

然而,静态代码扫描工具虽然能够帮助我们从代码层面上发现一些共性问题,但面对不同的业务逻辑仍然是没有感知的,以至于不容易挖掘出代码中深层次的问题。因此,在面对 UI、多态、复杂交互逻辑等场景时,纯靠静态代码扫描不足以完全解决问题。所以在第一道防护工序之后,我们又设计了第二道防护工序,具体介绍如下。

UI 测试扫描

根据以往发生的资损故障来看,问题往往多发生在代码变更时,开发同学的新改动影响到了业务的原有功能,而测试同学又恰好没有回归到这点。对测试同学而言,业务每次的全量回归工作量是巨大且重复的。就拿领取红包的例子来说,不同的账号(人群)、领取成功、网络超时、重复领取、没有资格、服务故障等等都是资损通常需要考虑在内的测试用例。此时,如果能有一个 UI 自动化回归测试工具,既能为业务提供一个保障,又能解放测试同学。然而,传统的 UI 自动化测试需要开发同学编写对应的自动化测试代码,不但有上手成本,而且还造成了额外的工作负担。

为此,我们又提出一种 基于录制/回放的 UI 测试扫描方案:开发/测试同学只需提供一个可正常访问的页面地址,正常的功能测试录成测试用例,在项目发布的时候就会进行一次页面回放,最后再通过 UI 测试用例快照比对的方式判定本次功能回归是否通过。

UI 测试扫描的整体思路如下:

image

其背后的原理介绍如下。

页面代理

代理页面本质是一个 web 服务,它通过 url 参数方式接收原始页面链接和注入脚本地址,由服务器请求原始页面返回对应的 html 文档,并且在返回文档头部注入接口拦截脚本、调试工具脚本以及url参数中取得的自定义注入脚本。代理页面拥有和原始页一样的 html ,同时也会添加上原始页的 query 参数,直接访问代理页除了 js 的 location 变量,其他环境和原页面相差无几。至于 location 变量,试了很多方案,发现都改写不了,一重写页面就跳转,多次尝试无果后我们发现可以换个思路解这个问题,既然重写不了我们就替换掉它,我们将页面所有的 script 脚本包了一层 with,如下图所示,我们将页面内所有的js脚本的上下文改写,使之读取的 location 是被我们重写的,从而达到代理页的渲染运行结果和原始页一致的效果。

image

录制脚本

通过上述的页面代理,我们就可以在访问原页面的时候注入我们的录制脚本。为了能够支持页面的回放,录制的时候就要提供两份数据:

  • 录制期间产生的所有网络访问数据
  • 用户操作数据(包括点击、滚动等)

要想记录网络访问的数据并不难,此处不展开多述,可以借用 AOP 的思想,在网络请求的回调中增加一个 interceptor ,同时保存下本次请求的 url,param,response,以便回放的时候匹配使用。

再来看下又该如何劫持用户的操作数据,其实在 h5 页面中,用户的任何触摸操作都会依次触发 onTouchStart、onTouchMove、onTouchEnd 事件,所以我们只需拦截这三个事件对应的 targetEvent 参数即可。就拿拦截 onTouchStart 为例:

image

如上可以看到,我们记录下了触发事件的事件类型、节点选择器、时间戳、页面距离顶部高度以及坐标位置等信息,这些都是回放时必不可少的数据。

再来看页面的滚动拦截,只要劫持 onScroll 事件即可。不过这里需要注意一点,页面滚动分两种:手指接触屏幕时的拖动,手指离开屏幕后的惯性滚动。前者会同时触发 onTouchMove 和 onScroll,而后者只会触发 onScroll。

image

回放脚本

回放脚本同样依赖代理页面的注入能力,但做的事刚好和录制脚本相反:

  • 拦截请求,使用录制时记录的网络数据 mock
  • 按照时序依次派发 touchEvent 事件

类似地,拦截请求和录制时的原理大体一致,只需根据本次请求的请求参数从录制时拦截的数据中找到对应的匹配即可。

再来看下如何根据时序派发 touchEvent 事件来模拟回放,核心代码如下:

image

派发事件是基于 dom 的 dispatchEvent 方法,可以参考 MDN 文档,代码如下:

image

快照对比

难点分析

根据前文的介绍,我们已经可以分别拿到录制和回放的最后一帧快照,所以接下来我们就希望设计出一套算法对这两个快照做内容一致性的自动化判断。从不同的输入案例来看,我们主要面临以下的几个难点:

  • 相同文字在不同型号的手机上会有不同的字体字号显示,像素级比对会将相同文字误判为不一致。
  • 对于红包等弹层图片,只需关注红包弹层信息是否一致,无关的背景会导致模型误判。
  • 由于回放/录制在时间戳上无法保证严格一致性,两张快照往往存在位置上的位移偏差。

算法设计

整体的算法流程如下图所示,下面我们分步骤阐述算法思路。

image.png

  1. 首先对两张快照计算 SIFT 相似度进行初筛。匹配的核心问题是将同一目标在不同时间、不同分辨率、不同光照、不同方向的情况下所成的像对应起来。图像的局部特征,对旋转、尺度缩放、亮度变化保持不变,对视角变化、仿射变换、噪声也保持一定程度的稳定性。相似度低于阈值的两张快照判为不通过,通过快照会做进一步精细比对。
  2. 针对弹层图片,需要预先对背景等无关信息做去除,仅保留弹层信息。这边先将图片从 RGB 空间转换成 LUV 空间。L 分量会保留图片的亮度信息,便于根据亮度值二值化图片,去除无效背景,效果如下。

img2.jpg       tmp_img0.jpg

  1. 将预处理好的干净图片送到 OCR(光学字符识别) 模型,提取出文字内容及相对应的坐标信息。针对像素过小的文字信息进行删除,往往是噪声产生的错误信息。
  2. 按照返回的坐标信息进行文字的位置还原,方便下一步做内容比对。
  3. 由上一步产出的结果进行内容比对,在图上标注出两张快照不一致的地方作为输出,算法结束。

效果演示

不通过:

25.jpg&27 (2).jpg.jpg")

通过:

1111.jpg&2222 (2).jpg.jpg")

img2.jpg&img3 (8).jpg.jpg")

小结

诚然,我们通过 UI 扫描工具改变了传统编写 UI 测试代码的方式,测试同学只需在功能测试的时候顺便录制一份测试用例即可,这不但降低了测试同学的自动化的学习成本和回归的时间成本,而且还为每次业务的发布提供了一道自动化回归保障。不过,在本次双 11 前端资防工作实际落地中,我们仍然遇到了一些问题:

  1. UI 测试扫描目前暂时只支持 h5,还不兼容淘系内的其他一些前端技术栈(比如 weex、直播、小程序等),导致这些业务仍然只能通过人工 review 的方式保障;
  2. 我们虽然对快照对比的算法进行了优化,但在实际应用中仍遇到一些由于算法判断不准导致误判的情况。因此,我们还将继续优化快照对比算法,进一步提升判断的准确度。
  3. 目前的快照对比只校验了录制和回放的最后一帧(即最终状态),大量的中间状态信息没有被利用起来,从而丢失了过程的校验。因此,后续我们将考虑引入视频的对比算法,达到真正的录制/回放全对比。
  4. 基于目前的页面代理机制,录制功能只支持当前页的操作录制,对于页面跳转类的测试用例还无法覆盖。因此,我们接下来也将继续升级页面代理和录制/回放脚本,支持链路层面的测试用例覆盖。

以上遇到的这些问题均是我们接下来继续重点突破的挑战。

总结与展望

如前文所述,淘系的前端资防工作一年内悄然变化着,从最初的人工预演到目前的三道递进式的产品化防控手段:

  • 【已产品化】针对可以在代码级别静态扫描分析出来的资损风险问题,做了第一道产品化防控手段——资损/舆情风险代码扫描工具;
  • 【已产品化】针对 UI、多态、复杂交互逻辑等不能从代码级别分析出来的资损风险问题,与测试团队合作做了第二道产品化防控手段——资损/舆情风险 UI 测试扫描,通过 UI 测试用例快照比对预防资损风险;
  • 【兜底方案】针对上述产品化手段不能覆盖的特殊场景,暂时先依赖人工预演作为兜底防护方案。

相比于去年的双 11 资防工作,今年我们依靠上述方案甚至取消了人工预演的环节。预演者也从去年需要准备相关文档(如止血方案、预案等)变成今年录制 UI 测试用例,其中需要准备的时间成本几乎打平,但大大节省了预演的参会时间;除此之外,预防效果也因其范围更聚焦、防护组合更全面,要比去年效果更佳。当然了,目前的这些方案都还只是预防手段,无法百分之百保障线上不会发生资损故障,每个人对于资防的态度仍不能掉以轻心。

在接下来的工作中,考虑到目前的资防方案仅能做代码缺陷方面的预防,产品设计、运营配置等方向还没有实质性的防控方法,所以后续我们将在构思链路级别的、生产环境以及运营环境上的防控手段,建设一些告警和自动止血机制为平台保驾护航。

(更多干货内容请关注【淘系技术】公众号,每日更新阿里工程师技术干货)
查看原文

赞 3 收藏 1 评论 0

阿里巴巴淘系技术 发布了文章 · 11月23日

人机协同时代,AI助力90.4%双11前端模块自动生成

背景介绍

2017 年,一篇论文 pix2code: Generating Code from a Graphical User Interface Screenshot 引起业界关注,论文讲述了使用深度学习技术实现从一张 UI 截图识别生成 UI 结构描述,然后将 UI 结构描述转成 HTML 代码。有人认为这种从 UI 截图直接生成代码的意义不大,AI 和 Sketch 软件本来就是用数据结构保存设计文件的结构描述,不需要通过机器学习来获取,而且生成的代码不确定性很大。也有一部分人对这个思路给予肯定,提出让深度学习模型学习 UI 界面特征,还可以做 UI 智能设计。

随后基于 pix2code 开发的 Screenshot2Code 项目进入 Github 排行榜第一名,该工具能够自动将 UI 截图转成 HTML 代码,该项目作者号称 3 年后人工智能会彻底改变前端开发,对此也有不少用户表示质疑,认为前端技术复杂框架各异,仅 HTML 代码无法满足需求。

2018 年,微软 AI Lab 开源了草图转代码工具 Sketch2Code一些人认为生成代码效果不理想不适用于生产环境,但也有人认为代码自动生成还处于初级阶段,未来发展值得想象。

2019 年,阿里巴巴对外开放智能生成代码平台 imgcook,可以通过识别设计稿(Sketch/PSD/图片)智能生成 React、Vue、Flutter、小程序等不同种类的代码,并在同年双 11 大促中自动生成了 79.34% 的前端代码,智能生成代码不再只是一个线下实验产品,而是真正产生了价值。

每当这些新的自动生成代码产品发布,网络上总会出现“人工智能会不会取代前端”“一大批前端程序员要失业了”这些讨论。

那人工智能到底会不会取代前端?人工智能在未来很长的一段时间内不会取代前端,但是会改变前端。一是会改变在前端智能化方向的前端领域探索者,他们除了可以成为 Nodejs 服务端工程师,还可以成为机器学习工程师,为前端智能化领域创造更多的价值和成果;二是会改变享受前端智能化成果的前端开发者,改变他们的研发方式,例如代码智能生成、代码智能推荐、代码智能纠错、UI 自动化测试等可以帮助他们完成大量简单重复的工作,可以把更多的时间放在更有价值的事情上。

本篇文章将给大家分享作为前端智能化领域的探索者,我们是如何看待人工智能在前端领域的未来发展方向,如何推进智能化能力在智能生成代码平台 imgcook 上的应用落地和迭代升级助力今年双 11 会场 90.4% 新模块的代码智能生成,编码效率提升 68% 的。

(更多干货内容请关注【淘系技术】公众号)

阶段性成果

======

imgcook(https://www.imgcook.com)官网首页平均每月 PV 6519, 平均每月 UV 3059。相比于 2019 年, 2020 年月平均 PV 和 UV 均是 2019 年的 2.5 倍。

imgcook 用户共有 18305 个,其中社区用户占比 77%,阿里集团内用户占比 23%。imgcook 模块共有 56406 个,其中外部模块占比 68%,内部模块占比 32%。相比 2019 年之前总量,2020 年用户增长 2.7 倍,模块增长 2.1 倍。

社区覆盖公司至少 150 家,集团内部覆盖 BU 10 个以上,双 11 会场新增模块覆盖度 90.4%,无人工辅助情况下智能生成的代码被保留发布上线的占比 79.26%,编码效率(模块复杂度和研发耗时比值)提升 68%。

与 2019 年相比,用户感官提效提升 14%;和完全不使用 D2C 相比,固定人力单位时间模块需求吞吐量提升约 1.5 倍。与传统研发模式相比,使用 imgcook 研发链路编码效率可提升约 68%。

更多详细数据请看 2020 年 imgcook 研发效能报告

image.png

(Imgcook 研发效能数据概览)

技术产品体系升级

技术原理简介

我们先来了解下 imgcook 智能生成代码的原理, imgcook 能够自动生成代码主要是做了两件事:  从视觉稿中识别信息,然后将这些信息表达成代码。

本质是通过设计工具插件从设计稿中提取 JSON 描述信息,通过规则系统、计算机视觉和机器学习等智能还原技术对 JSON 进行处理和转换,最终得到一个符合代码结构和代码语义的 JSON,再用一个 DSL 转换器,转换为前端代码。DSL 转换器就是一个 JS 函数,输入是一个JSON,输出就是我们需要的代码。例如 React DSL 的输出就是符合 React 开发规范的 React 代码。

image.png

(D2C 智能生成代码使用动线)

其中核心部分在于 JSON to JSON 这部分。设计稿中只有图像、文本这些元信息,位置信息是绝对坐标,并且设计稿中的样式与 Web 页面中的样式表现存在差异,例如 sketch 中透明度 opacity 属性不会影响子节点,但在网页中 opacity 会影响子节点,而人工编写的代码具有各种布局类型、DOM 结构需要合理可维护、代码需要语义化、组件化、循环等信息。

如何能智能生成像人工编写这样的代码,这是智能还原这部分要解决的事情。我们把 D2C 智能还原部分做了能力分层,每一层的输入和输出都是 JSON,智能还原部分的本质是一层一层的做 JSON 转换,这就是整个智能还原的流程。如果需要对生成的 JSON 做修改,可以通过 imgcook 编辑器可视化干预,最终通过 DSL 开放层将得到的符合代码结构和语义的 JSON 转换为代码。

image.png

(D2C 智能还原技术分层)

智能还原的核心链路构成了 D2C 的核心技术体系,并通过度量体系来衡量核心还原能力和研发提效效果。下层依托算法工程体系提供核心技术体系中智能化能力的底层服务,包括样本制造、算法工程服务、前端算法工程框架,上层通过 D2C 研发体系承接智能还原的后置链路,通过提供可视化干预能力满足用户二次迭代的需求,并通过将工程链路内置到 imgcook 平台实现一站式开发、调试、预览和发布来提升整体的工程效率。再加上支持自定义 DSL、自定义开发物料等扩展性很强的自定义能力形成的开放体系一起构成了整个 D2C 架构,服务于阿里内部 C 端、小程序、中后台等以及外部社区各种不同的业务场景。

image.png

(D2C 技术架构图)

今年在前端智能化大背景下,对 D2C 技术体系全链路进行了智能化能力升级,并为前端同学带来了让前端工程师能成为机器学习工程师的前端算法工程框架 Pipcook 和解决样本收集问题的样本制造机 Samplecook。同时带来了营销模块研发链路产品化升级,助力全链路研发提效。

智能化能力升级

智能化能力分层定义

《汽车驾驶自动化分级标准》基于驾驶自动化系统能够执行动态驾驶任务的程度,根据在执行动态驾驶任务中的角色分配以及有无设计运行条件限制,将驾驶自动化分成 0 至 5 级。在高级别的自动驾驶中,驾驶员的角色向乘客转变。这种明确的标准有助于各类企业更有针对性展开研发和技术部署的工作。

image.png

(自动驾驶分级标准)

参考自动驾驶分级标准,基于 D2C 系统能够自动生成代码的程度,根据编码的角色以及是否需要再人工干预和验证,我们定义了一个 D2C 系统交付的分级标准,用来帮助我们认识 D2C 系统当前所处的级别以及下一阶段的发展方向。

image.png

(D2C 系统交付分级参考标准)

目前 imgcook 的能力处于 D2C 的 L3 级别,智能生成的代码还需要可视化干预或人工兜底开发后验证上线。未来期望达到 L4 级别,我们需要对 UI 信息架构进行拆解,对从 UI 信息自动生成代码的智能化能力进行细分。

image.png

(UI 信息架构拆解)

一个应用由多个页面组成,每个页面中按 UI 颗粒度划分可以分为模块/区块、原子模块/区块、组件(业务组件、基础组件)、元件。每一个颗粒度的 UI 我们都需要识别到它的布局结构和语义,才能生成像人工编写一样模块化、组件化、语义化的可维护性较高的代码。

根据对 UI 信息架构的拆解,我们结合 imgcook 生成代码的技术体系从不同颗粒度对智能化能力进行分级 I0-I5(I 是 Intelligent 的首字母)。

image.png

(D2C 智能化能力分级)

其中涂色部分是目前已具备的能力,从这个维度来看 imgcook 的智能化能力目前处在 I3 和 I4 级别,并与 I2 级别的能力协同运作于生产环境。 I3 级别的智能化能力需要不断优化和迭代模型,当线上真实场景准确率达到 75% 以上或模型具备自我迭代能力则进入 I4 级别。如果达到了 I5 级别的智能化能力,根据 D2C 系统交付分级参考标准,D2C 系统交付分级可以从 L3 进入 L4, 生成的代码将不需要人工干预和验证即可直接上线。

当然我们可能会长期处于 L4 级别这个人机协同编程的阶段,这种分级的定义是为了促进智能化落地的进程,可以指导 我们提升 D2C 智能化能力,对 D2C 智能化有个更清晰的认识。

我们以生成代码的可用度作为总体技术指标,并根据代码生成链路的技术分层给出各阶段的技术指标以及对代码可用率影响的权重,其中生成代码的理论准确度 = (各个环节准确度 * 权重)之和,而真实的代码可用率 = imgcook 生成的代码在最终上线的代码中留存的占比。

image.png

(各分层技术指标与权重定义)

D2C 的智能化能力分布在还原链路的各个阶段,我们以提升代码可用率为目标,对全链路进行智能化能力升级,将技术方案细化到如何让各阶段模型识别准确率提升以及如何能将识别结果最终应用到智能还原链路生成代码,如何做到从样本收集、模型训练、模型部署到模型应用到工程链路整个流程能够自动化、自我迭代优化,不断优化和迭代模型能力。

智能化能力的应用还需要工程链路的支撑,例如模型识别结果的应用、线上用户行为召回、前端开发组件对 UI 组件识别结果的承接等,整体的 D2C 技术体系也需要同步升级。

image.png

(D2C 技术体系升级大图)

各阶段智能化能力升级

图层解析阶段

imgcook 通过解析设计稿图层信息,并通过规则系统、智能化技术等识别和生成代码,但由于设计域与研发域的表达方式、结构和规范等差异,设计稿的图层结构对生成代码的合理性影响较大,一些设计不规范的设计稿需要用 imgcook 的“成组”和“图片合并”协议对设计稿进行调整。

开发同学在开发代码时也经常会有写多余的 console.log、没有注释、变量重复声明等代码不规范的问题,为了解决这些问题,提供了 ESLint、JSLint 等工具来保障代码规范的统一。

在设计域,我们也同样可以开发一套设计稿规范智能检查工具来保障设计规范,智能审查设计稿的规范性,提示错误并辅助调整。我们把这套工具称为 Design Lint(DLint),具体的实现方案可以查看 设计稿生成代码 Imgcook 3.0 系列-设计稿规范智能检查篇

image.png

(设计规范检查)

物料识别阶段

UI 物料可以分为模块/区块、组件和元件,从 Sketch/PSD 中直接提取的信息只有文本、图片和位置信息,直接生成的代码都是由 div、img、span 组成,实际开发中组件化、代码语义化必不可少,如何从设计稿中提取组件和语义信息,这是 NLP、深度学习等智能化技术非常适合解决的问题。

去年我们在组件识别、图片识别、文本识别这几个方向都有探索和实践,识别的结果最终用于语义化和字段绑定,但使用的技术方案对识别的效果限制较大,今年我们做了如下改进:

组件识别

原本使用目标检测的方案来识别 UI 组件,但这种方案既需要识别出正确的组件类别还需要识别出正确的位置,以整个视觉图片作为输入,复杂的图片背景很容易被误识别,并且由于识别出的位置偏差导致很难挂载到正确的节点上,模型识别结果在线上的应用准确率较低。

基于这些原因,以及 imgcook 能够从视觉稿中获取每个图层位置信息的优势,我们将方案转换成了图片分类,并能将识别结果真正的应用到线上,这其中依托一套组件可配置、可识别、可渲染、可干预、可出码的智能物料体系。具体实现方案可以查看 设计稿生成代码 Imgcook 3.0 系列-组件识别篇

image.png

(组件识别应用全链路)

以下是组件识别应用到线上的演示,识别视觉稿中的视频信息,并用 rax-video 前端组件承接生成组件粒度的代码,需要配置自定义的组件(组件库设置)、组件识别模型服务(模型服务设置)、支持渲染 video 组件的画布资源(编辑器配置-画布资源)以及应用组件识别结果的业务逻辑点(业务逻辑库配置)。

组件识别全链路.gif

(组件识别全链路演示)

Icon 识别

Icon 识别其实是一个图片分类的问题,依然沿用图片分类的方案,但为了能够让模型的泛化能力能自我增强,我们设计了一个 Icon 自动收集、处理数据、自动训练模型、自动发布模型的模型闭环链路,让模型能够自我迭代优化。

image.png

(Icon 识别模型闭环链路)

自上线以来,新增训练集总数达到了 2729 个,平均每月回捞有效数据 909 个, 模型经过几次自我迭代测试集的准确度从 80% 提升到了 83%。具体实现方案可以查看 设计稿生成代码 Imgcook 3.0 系列-Icon识别篇

图片/文本语义识别

在 imgcook 智能化系统中有一个很关键的部分,就是如何对 UI 界面内的元素绑定语义化信息,之前解决方法是基于图片和文本分类模型识别,该方法有很大的局限性:仅对文本进行分类,没有考虑与整个 UI 界面内的上下文语义,导致模型效果不好。

举个例子:$200,这个字段文本分类是没办法对其进行语义识别的,因为它放到不同的场景中有着不同的意思,如:活动价、原价、优惠劵...,正确的做法是考虑该字段与在 UI 界面的联系(即独特的样式)来对它进行语义分析。

因此,我们引入了一种能结合 UI 中上下文语义的方案来进行语义识别,采用图片元素决策+文本分类两步走的方案解决界面元素语义化问题,具体流程是:先基于强化学习对界面元素按样式“过滤”一遍,识别出有样式的非纯文本字段,再对纯文本的字段进行文本分类。具体框架如下。

image.png

(强化学习 + 文本分类)

以下是模型算法训练结果。

语义分析结果演示.gif

(基于上下文的语义分析)

布局还原阶段

布局即是代码中每个节点与节点之间的关系,是父子关系还是兄弟关系。从颗粒度大小上划分,可以分为页面间模块/区块之前的关系、模块/区块内原子模块/区块之间的关系以及原子模块/区块内组件、元件之间的关系。

目前 imgcook 已具备了循环识别与多态识别的能力,识别设计稿中的循环体生成循环代码,识别同一个节点有多种 UI 状态时生成多状态的 UI 代码,并定义了布局可维护度衡量方式来衡量还原阶段的准确度。

image.png

(布局还原阶段识别能力升级)

逻辑生成阶段

在业务逻辑生成阶段优化原有的配置链路,将业务逻辑库与算法工程链路解耦,并承接所有识别结果的应用和表达。物料识别阶段只关心 UI 中有什么物料,不关心识别的结果如何用于生成代码,布局还原阶段的循环识别和多态识别同理。这样做的好处是我们可以自定义识别结果的表达,并且可以让用户感知智能识别的结果并选择是否使用。

除了从业务逻辑库生成逻辑代码也可以从需求稿生成部分逻辑,或者来源于代码片段推荐,或者来源于代码智能推荐( Code to Code,C2C)。

image.png

(通用业务逻辑库配置)

算法工程体系升级


样本制造机

算法工程服务提供了 UI 特征识别的模型训练产品,为所有想使用业务组件识别的小伙伴打造一个玩弄机器学习的链路。为了解决使用算法工程服务的关键痛点,所以有了新的衍生产品:样本制造机,为前端 UI 识别的模型提供样本制造捷径。

前端算法工程框架

有很多同学会觉得,让前端同学用机器学习技术去解决前端领域的问题,会不会难度很大。为了降低前端工程师使用机器学习的门槛,我们开发了前端算法工程框架 Pipcook。前端工程师可以用熟悉的 JavaScript 来完成机器学习任务。

Pipcook 通过提供通用的模型能力,比如图片分类、目标检测、文本分类等,减少了在 imgcook 中从开发到上线这些模型的门槛,使得如此多的底层识别能力也具备快速迭代的可能性。imgcook 全链路的识别能力,如组件识别、Icon 识别、字段语义识别等都是基于 Pipcook 训练。

image.png

(前端算法工程框架 Pipcook)

我们可以这样理解 Pipcook, Node.js 的出现可以让前端工程师成为一位服务端工程师,做服务端同学能做的事情, Pipcook 的出现可以让前端工程师成为一位机器学习工程师,可以做机器学习工程师做的事情。

image.png

(前端与机器学习)

研发链路升级

天马模块研发链路

淘系营销以模块开发为主,模块开发的完整链路是从模块管理平台创建模块 ⇥ 进入 imgcook 平台智能生成代码&可视化研发 ⇥ 开发完成后进入 IDE 调试预览 ⇥ 测试完成后进入工程平台发布。整个研发流程需要切换多个平台,开发链路体验和工程效率都有待提升。

创建模块后进入 imgcook 平台智能生成代码&可视化研发,如果能够直接在 imgcook 平台开发、调试、预览和发布,一站式的 D2C 研发模式是提升整体研发效率和研发体验的一个不错的选择。

所以我们自定义了具有可视化模式和源码模式的营销版本 imgcook 可视化编辑器,在可视化模式智能生成代码和可视化研发,并将生成的代码一键同步到源码模式的 WebIDE,在 WebIDE 中支持界面化的调试、预览、发布。

image.png

(天马模块 imgcook 可视化研发动线)

我们通过计算使用传统研发模式开发的模块与使用 imgcook 可视化研发模式开发的模块的效率值(复杂度与研发耗时比值)看到,使用 imgcook 可视化研发链路开发的模块编码效率提升 68%。

Imgcook 可视化研发链路1.gif

(天马模块 imgcook 可视化研发全链路演示)

智能 UI 研发链路

智能 UI 是一种通过分析用户特征为用户提供个性化 UI 的方案,因此需要开发大量的 UI 界面,在淘系智能 UI 平台鲸幂中开发智能 UI 的原始链路是在上传视觉稿解析物料之后会批量创建 imgcook 模块,但每种物料都需要进入对应的 imgcook 可视化界面单独开发、创建仓库、单独发布,并且看不到智能 UI 整体的视觉效果。这样导致智能 UI 所需要的大量物料的开发成本很大,业务接入智能 UI 的成本比较大。

image.png

(智能 UI imgcook 可视化研发动线)

这次升级了智能 UI 的研发链路, D2C 可视化研发链路承接了智能 UI 的批量化生产。在上传设计稿解析出 UI 物料之后,创建 imgcook 模块,批量生成物料 UI 代码,同时创建代码仓库与 imgcook 模块关联,并支持将已创建的物料批量导入 imgcook,批量生成 UI 方案(不同类型的 UI),在生成的 UI 方案中集中式对物料进行开发,最后还将支持物料的批量发布,整个链路集中高效了很多。

落地结果

今年前端智能化助力前端研发模式升级,数个 BU 共建前端设计稿识别算法模型和数据集,并于双 11 会场大规模应用落地。

设计稿生成代码技术体系全面升级(如对 UI 多态、直播视频组件、循环的智能识别增强等)带来了营销模块研发链路产品化升级:双十一会场有 90.4% (高于去年)新模块的代码智能生成。升级设计稿智能检查能力,在可统计范围内,无人工辅助的情况下智能生成的代码被保留发布上线的占比 79.26%。

相比传统模块开发模式,使用设计稿生成代码技术后编码效率(模块复杂度和研发耗时比值)提升68%,固定人力单位时间模块需求吞吐量增加约 1.5 倍。

目前还需要人工改动代码的主要原因有:循环未被识别、条件展示逻辑代码未自动生成、字段绑定猜测错误(字段标准化情况不佳)、业务特性必须的图片合并问题等,这些问题也都是接下来需要逐步完善的。

代码生成示例.gif

(D2C 代码生成用户更改情况)

同时,imgcook 支撑了天猫淘宝的主会场和行业会场智能 UI 的批量化生产,极大的提升了智能 UI 的生产效率。

智能UI批量化生产.gif

(智能 UI 批量化生产结果)

未来展望

智能化方式无论是使用计算机视觉还是深度学习技术,都会有准确率的问题,准确率低在线上环境可能无法被接受。需要建立一套与线上用户使用数据形成闭环的算法工程链路,实现样本自动化收集、算法工程链路的闭环才能让模型线上识别准确率不断提升。目前在 imgcook 的系统中,Icon 识别从样本收集到模型识别结果的最终应用已经形成了完整的链路闭环,开发同学不需要花太多精力用于模型的优化。对于其他的模型,后续也会用同样的思路让模型具有自我迭代的能力。

另一个 D2C 智能化的难点是模型识别的结果最终如何用于生成代码,例如组件识别模型能识别组件的类别,但最终生成代码使用哪个组件库的组件、如何识别 UI 中的组件属性值这些问题,imgcook 的平台能力与智能还原技术分层架构具备解决这些问题的能力,未来会有更多的智能化方案用于生产环境。

后续我们会继续根据对 imgcook 的 D2C 智能化能力拆解,探索更多智能化解决方案,优化现有模型能力,建立算法工程闭环机制实现每一个模型的自我迭代,不断提高模型的泛化能力和线上识别准确度,辅助生成可维护性更高语义更强的前端代码。

(更多干货内容请关注【淘系技术】公众号)
查看原文

赞 3 收藏 2 评论 0

阿里巴巴淘系技术 发布了文章 · 11月23日

手淘双11最新实践:PopLayer弹层领域业务研发模式升级

背景

近年来,各大APP内的弹层需求逐渐增多,以手机淘宝为例,日常的弹层上线频率为单端每月50次左右,而在大促期间可以达到240次以上。在手淘内,各类弹层业务都会通过PopLayer中间件的能力进行管理。但业务往往会遇到开发弹层难、慢、稳定性差的种种困难。对比于往年业务研发成本较高的现状,PopLayer在今年提出了【低研发搭建模式】来解决这类问题,形成一套快速搭建+可视化+多端多场景通用的解决方案,在日常与大促期间得到了广泛应用:

  • 研发效率升级:弹层业务的上线成本从3天+,降低到2小时左右
  • 业务覆盖率高:双11大促期间的业务覆盖率达到75%
  • 稳定性极佳:大促期间线上0故障

在各类APP都逐渐走向存量时代,精细化流量运营的今天,弹层作为一个可以随时随地产生内容并带来高流量的强运营手段,已经从低频需求,变成了面向各类人群触达的高频需求。作为业务支撑方向的中间件,如何为业务提效,将业务的关注重点从开发转向内容运营,助力其完成触达矩阵,成为了一件非常值得探索的事情。

(更多干货内容请搜索关注【淘系技术】公众号)

PopLayer

弹层,是一种强触达用户的交互形态。PopLayer的定义,则是一个可以在任何APP页面上,在指定时间内,对页面无侵入地弹出任何内容的弹层中间件。其业务定位,则为触达各领域用户的重要流量场。

为了便于理解,下面以手淘首页近期Pop为例,将手淘内的Pop业务分类举例介绍(本文中Pop即指弹层):

  1. 大促氛围打造

image.png

开售倒计时提醒

  1. 增强用户体验

死亡恢复.jpg

死亡恢复浏览飘条

  1. 红包发放&提醒

互动权益.PNG

星秀猫开奖

催用倒计时.png

红包催用提醒飘条

  1. 用户指引

可以看到,弹层业务的交互形态是灵活多变的,业务目标诉求也各有不同。其背后有着各自业务层面的复杂诉求和增长目标。PopLayer为此提供了一套端侧弹层管理SDK+任务管理系统的整体解决方案。

image.png

PopLayer常规任务管理流程

注:PopLayer是以端侧中间件为核心进行建设的,其中每个环节都有比较复杂的链路可以展开,本文不展开讨论端侧细节,主要讨论研发效率方面。

在这套流程中,对业务方负担最重的,也是研发耗时最重的,便是前端页面的研发以及服务端接口的研发。且各个业务的曝光预判接口不断累积,也带来了非常大的资源浪费与QPS压力。随着弹层业务逐年增多,这套模式的弊端越来越凸显:

  • 研发效率低下以日常期间观察,研发一个图文类型弹层,至少需要一个前端人员投入三天以上时间+一个后端人员投入三天以上时间+测试人员投入一天以上。
  • 运营效率低下。运营策略往往受限于研发成本、资源调控、以及上线时间等等问题,而无法灵活展开与快速迭代。尤其在大促期间,很多快速决策的运营玩法无法及时且稳定地落地,丧失了关键时刻获取流量的机会。
  • 研发质量难以保证。不同于整页研发,弹层存在一些特殊需要注意的问题。而研发人员接入PopLayer的流程熟悉程度往往有限,很容易因缺乏经验而产生线上异常,比如只有背景黑色遮罩弹出而内容加载失败(可以想一想会是什么状况)
  • 业务数据指标没有统一标准,无法形成客观统一的业务指标,无法通过数据快速定位问题,无法形成有效的数据沉淀与对比。
  • 整体方案难以沉淀复用。

这样的研发成本,对于Pop这类往往需要快速响应的业务需求,是远远不能满足的。尤其在大促期间,对时效性要求很高,一个Pop从决策到上线,可能仅仅只有1-2个小时的响应时间,一旦错过时机对业务的流量损失是巨大的。

经过建设搭建模式,这套陈旧野生的研发流程终于得到了改变。如今,通过新模式,一个常规的单图Pop几分钟就可以完成搭建。业务方可以彻底解放双手,集中精力在更加优质的内容编排与制作上。

模板全域触达技术模型111.png

PopLayer搭建模式对研发流程的影响

-

PopLayer搭建模式

Pop业务背景分析

经过长期与业务深入合作,我们发现弹层的需求往往有一定的规律可循。PopLayer领域下的业务特征大体如下:

  • UI结构轻量:主要为底图+内部图文混合的UI结构,视觉复杂度有限
  • 点击交互可枚举:跳转页面、关闭Pop、发送后端接口、切换内部子页面等
  • 组件复用性低、整体复用性高:每个Pop内部可复用的组件几乎不存在,更应该以一个完整的Pop作为一个模板进行维护和复用
  • Pop特有逻辑较多,比如疲劳度规则、各类数据来源变量解析等

那么实现一套统一标准的搭建方案,从前后端等各个方面逐个击破,来承载业务的大部分高频需求,支持其快速、低研发迭代上线,便成了解决这类问题的首选方案。

得益于这套标准化的前端协议规则,我们可以将PopLayer的触发范围,从APP站内触达,向其他流量场横向扩展,比如Android桌面、H5环境等,这部分后文将会展开讨论。

搭建模式架构

模板全域触达技术模型.png

搭建模式方案框架图

我们通过锁定 低研发搭建+多端多领域统一触达 的解决方案,支持运营与业务快速完成各类弹层小时级上线。其链路主要包括如下几个部分:

  • 搭建
  • 设计一套Pop业务域内的统一业务描述DSL,来描述Pop的全部UI架构、数据提取规则、交互逻辑等等内容。以其为核心,完成搭建与各端各领域的解耦
  • 搭建IDE,提供友好的编辑界面、实时动态预览、真机预览等业务服务,最终产生标准DSL内容
  • 解析
  • 探索除APP站内之外的更多触达领域,包括Android桌面环境、H5环境
  • 研发DSL运行时解析引擎,并完成统一体验的Pop渲染及交互
  • 任务管理服务
  • 提供一体化人群曝光预判
  • 提供权益、AB与模板搭建的打包配置能力,无需业务方自建实验、自研权益对接
  • 将单场景多Pop情况下的预判QPS压力,降低为单场景组合预判模式,有效降低服务端压力

搭建

搭建与DSL

DSL,即领域特定描述语言,是为了解决特定领域问题而形成的编程语言或规范语言。在Pop业务域下,我们无需形成编程语言,甚至追求尽可能低研发,所以这里的DSL即为一种Pop业务域范围内的规范描述语言。

Pop的DSL格式为常用的JSON格式。其整体结构为pages-UI动线、props-变量解析、requests-请求接口、env-环境全局配置。

image.png

下面我们从交互动线结构、变量解析、事件结构、疲劳度几个方面分别介绍DSL描述的主要内容。

  1. 交互动线与UI结构

交互动线

对应到DSL,我们提供了多子页面+多版本的描述方案,即通过创建多个子页面+每个子页面的多个版本来完成动线素材,并通过设置事件动作,完成动线串联。对应到DSL的结构,即通过pages+vers以树形结构分别描述各个子页面版本。其整体示例如下:

模板全域触达技术模型.png

布局版型

Pop的布局版型是多种多样的,但基本可归类为如下几种:居中、四角挂角、四边贴边。DSL设计中,每一个子页面都可以单独设置其布局版型。不同的版型,会以不同的布局逻辑计算其大小位置。

模板全域触达技术模型1231.png

UI组件

Pop形态下的UI组件,基于围绕着如下几个类型展开:图片、文本、视频、容器、倒计时、点击热区等。即通过提供大图或视频为背景,并通过容器+内部组件形成内部复杂的界面布局。我们针对各个组件提供了统一的布局配置+各自不同的素材配置。以一个倒计时组件为例:

2231313.png

  1. 变量数据提取与绑定

变量数据提取

Pop的内容与服务端数据做绑定时,需要提供一套提取数据的描述方案。而数据来源因Pop的整体链路设计,存在多个可能来源。我们通过 指定数据来源+提供插入式Mtop接口配置+接口数据提取Function 完成数据提取的设置,形成一个变量。仍以上述Demo为例,其中红包金额的变量为服务端Mtop接口返回数据。其提取流程示例:

模板全域触达技术模型11111.png

即通过预判MTOP接口数据源,通过JSONPath,并指定其数据位置完成提取。在某些较为复杂的情况下,有时数据来源需要多层解析(JSONPath+URLDecode+URLParse),那么也支持其设置串行多层解析。

变量绑定

解析结束的变量,即视为一种全局资源,其可以绑定到各种内容与其他数据上,哪里需要哪里搬。比如图片地址、文本内容、toast内容、跳转地址、MTOP请求参数等等。其实现方案为常用的字符串模板表达式${prop_name},进行运行时替换。

  1. 事件结构

大多情况下,Pop内的事件,即为用户点击事件,但随着业务复杂度的提升,例如视频播放结束、视频加载失败、倒计时结束等时机也需要响应事件,我们便提供了统一的事件描述,方便挂载到各个组件事件配置上。而事件的类型。即为跳转场景、切换子页面、发送MTOP接口、关闭Pop等,我们分别对这些事件提供了对应的封装描述。此处细节较多暂不展开。

  1. 疲劳度

疲劳度是Pop的重要组成部分之一。疲劳度的设计分为疲劳度规则+疲劳度消耗规则。例如Pop需要用户每天曝光不设限,但点击后当天不再弹出。那么其疲劳度规则为一天一次,而消耗规则即为点击时消耗。通过这样的实现方式,则可以非常灵活的实现各类疲劳度需求,做到想怎么弹就怎么弹。

在DSL的曝光、关闭、以及每个事件结构中,均有疲劳度消耗规则,而疲劳度整体规则,则通过不同的疲劳度表达式完成配置。

搭建IDE

IDE的核心功能,即为业务用户提供一个实时可视化、随时可真机预览的一站式搭建编辑器。其产出,则是产生一份描述业务完整需求的DSL内容。目前已为业务提供包括页面搭建、数据管理、曝光判定、疲劳度规则、降级策略、埋点配置等方面的搭建功能。

20201113135045.jpg

搭建IDE

解析

如方案框架图所示,搭建模式的目标不仅仅是在APP站内完成Pop触达,还需要在Android桌面、站外H5这样的环境里完成一站式多端触达。我们可以把目前涉及的几个流量域,称为触达领域。

APP站内的触发流程,即PopLayer端侧中间件,功能上有非常丰富的积累,可支撑几乎所有Pop业务的各方面诉求,此处不进行展开,本文将从弹出Pop后的解析引擎、Android桌面的触达领域支持方面进行介绍。

运行时解析引擎

针对不同的触达环境,需要形成各自的运行时解析引擎,目前我们完成了APP站内引擎:负责站内+Android桌面的解析渲染,以及H5站外引擎:负责H5环境下的解析渲染。这里我们主要针对站内引擎进行介绍。

PreDisplay + Running

解析引擎的主体工作流程,分为PreDisplay阶段:获取DSL、获取各环境数据、解析变量、完成UI渲染并曝光,以及Running阶段:在曝光后的事件交互处理。

模板全域触达技术模型121231312.png

解析引擎工作流

在执行display之前,Pop为隐形状态,用户无感知。经过如上图的DSL解析、同步各类环境数据、变量解析、曝光判定、素材加载等流程后,通过display接口,完成最终曝光。

为了达到双端统一的渲染效果、高适配性、以及高性能渲染的要求,站内引擎的底层载体目前为Rax方案。基于Rax完善的工程化支持,我们得以完成一系列上层方案,无需过度关注动态性、适配性等问题。

Android桌面弹层

对于手淘这样日活流量足够大的APP,其Android桌面的触达流量价值同样是巨大的。相比APP站内的Pop触达,其更加拥有包括加强唤端、二方流量交换这样的独特价值。在有规则规范的前提下,我们可以通过端侧中间件建设,把Pop搭建的能力无差别的输出到桌面环境,使其成为Pop触达生态的一环。其具体的触达形态,则可以是顶部消息、挂角提醒等。其底层实现方案为Android悬浮窗。

桌面Pop的效果Demo如下:

20201115180521.jpg

模板全域触达技术模型111.png

桌面Pop方案框架

首先,我们将桌面与站内进行了搭建能力对齐,使一个搭建产生的页面,即可以在手淘里弹出,也可以在桌面上弹出。为此我们抹平了底层方案不同带来的差异,包括:

  • 搭建模式与站内一致,同样采用标准DSL+解析引擎完成渲染
  • 通过控制Window添加次序来对齐层级管理
  • 通过控制视窗大小位置,控制其可绘图区域;通过搭建输出可视区域位移量,对视窗内容进行位移还原窗口内容

另外,我们提供了桌面环境的特殊处理:

  • 增加了切换桌面触发时机(计划触发,适合计划常驻),并打通了ACCS消息触发时机(即时触发,适合消息类型)
  • 增加了自由拖拽、边侧自动吸附功能

由于桌面环境的特殊性,应避免对用户形成严重的干扰。那么桌面触达的规则管理则十分重要。目前我们设计了如下避免过度干扰的规则:

  • 桌面环境的Pop必须有明确明显的关闭按钮
  • 切换其他APP时,需要将Pop内容进行隐藏,对于Android高版本则进行倒计时后自动关闭设置
  • 桌面的弹出管理底层与站内一致,采用分层分优先级管理,并对一次桌面切换的曝光次数进行上限设置

任务管理服务

从上述任务管理流程图可以看到,业务对于曝光预判、业务数据方面都是需要服务端的人力投入的。即除前端的研发成本问题,服务端同样面临类似的问题。我们梳理业务目前痛点如下:

  • 人力消耗大,大促时效性差
  • 机器资源消耗大
  • 全量配置下发+全量接口预判的模式,导致单活动机器资源消耗大
  • 单场景(比如手淘首页)下的Pop往往存在多个,活动之间筛选独立进行,导致机器消耗总量增长快(QPS总量随活动数线性增加且无上限)
  • 稳定性风险高
  • 临时开发的模式,加上人员开发质量层次不齐,稳定性很难保障。
  • 业务需要自己投入精力维护稳定性,特别是每次大促的时候应对突发流量

为此我们实现了对业务进行一站式托管。核心目标为:

  • 实现权益、导流这两个业务领域的低研发极速上线
  • 降低机器资源消耗,在线活动数量不再受机器资源限制
  • 托管业务全年0故障

通过拆解上文的任务管理流程图,可以看到服务端的工作主要包括曝光预判接口,以及页面内的业务数据接口。我们针对两部分分别进行部分托管建设,架构图设计如下:

1587024041829-d573d633-5736-4b3b-9939-8b2285049b82.png

任务管理服务架构

  • 针对曝光预判接口,我们提供了单场景多活动的人群预判复用能力,即将人群圈选的预判模式统一集中管理,底层与奥格人群平台二方包打通,上层单场景仅透出一个整合接口。从过去每次切换页面触发N次预判接口,变为仅触发一次。业务也无需自研人群接口,仅需把人群包ID进行配置即可。
  • 针对内容数据接口,我们仍在建设中。计划通过底层打通了拉菲权益平台二方包,将权益类型(红包、优惠券等)直接整合进搭建体系中,业务无需进行复杂的权益能力对接,仅需提供权益ID配置即可。

整体效果

除文章开头提到双十一期间的业务覆盖率已经达到75%之外,得益于搭建模式对研发效率的提升,今年双十一期间,手淘内Pop的业务量和整体流量也有了大幅度飞跃:

image.png

除此之外,今年我们快速稳定地响应了大促期间的全部紧急需求,避免出现过去几年因封网、研发效率等问题带来的无法上线Pop的情况。

写在最后

PopLayer目前除手淘外,已经服务了集团众多APP,包括天猫、淘宝特价版、闲鱼、淘宝直播、饿了么、Lazada、零售通、AE等等。后续也将继续以手淘为核心,服务更多的集团业务。

通过双十一大促期间以及日常的业务覆盖率,我们印证了搭建模式对业务的价值。站在业务的角度思考,Pop这类“既轻量又复杂”的业务域,经过一番深挖的底层支持,可以大幅度破除业务的桎梏,让其解放双手,去快速通过“提出idea-搭建-AB-看数据-再次迭代”的模式得到最佳的业务结果。这套业务研发模式的优化,从思考如何研发变为如何尽可能封装研发,对于相对轻量级的业务域来说也是有输出价值的。

后续,我们一方面将会继续完善相关建设,将AB、标签+推荐系统、引擎加载页面性能优化等等进行深度挖掘,从研发效率提升,升级到业务价值提升;另一方面也会将Pop的建设经验沉淀成流量域方法论的一部分,输出到其他流量域中,为业务探索与构建更有价值的流量增长矩阵。

手淘平台技术

我们背靠淘系基础架构和厂商,既有立足5G适配、网络加速、图片体验、网关调用、大内容上传下载等核心技术支撑业务体验升级和改造,

又为用户增长提供消息推送、浮层搭建、厂商触达、外链拉端等流量端能力,并沉淀一系列如最小核、全链路数据等架构能力,为手淘及产品升级提供平台支撑,并成为集团移动端基础设施。

职位:Android研发工程师、iOS研发工程师

感兴趣的同学可将简历发送到:yangqing.yq@alibaba-inc.com,获取优先内推资格!

查看原文

赞 2 收藏 1 评论 0

阿里巴巴淘系技术 发布了文章 · 11月20日

史上最快破5亿用户的互动 - 2020双11养猫技术大揭秘

前言

在电商领域,互动是一个重要的用户增长方案,在提升用户黏性、活跃以及拉新上都发挥着重要的作用。今年双11,淘系互动团队推出了“超级星秀猫”,我们不盖楼、不开车,全民参与养猫出道,3只风格各异的萌猫咪一经问世,瞬间俘获了无数消费者的心。通过 EVA 互动体系一整套解决方案,大幅提升研发效率,支撑全民养猫猫在手淘、猫客、支付宝等多个 APP 互通。借助客户端能力及 EVA 互动体系将性能与内存良好控制,让多数用户体验高清稳定的互动,实现 0 故障及秒开,同时星秀猫参与人数再创新高。这篇文章将主要从页面渲染基建、EVA 研发体系和全局稳定性方案 3 个方面,来具体阐述淘系互动前端团队是如何做到双11互动又快又好又稳的。

image.png

(更多干货请关注【淘系技术】公众号)

页面渲染基建

不知道大家有没有发现,今年的双11养猫互动(以下简称双11互动)页面打开特别快,具体可看下面与去年双11互动主页在 iPhone 11 PRO 机器手机淘宝上的主页加载对比视频。不仅如此,还有个明显的变化是以往互动页面的标配--进度条没有了。

image.png

见多识广的你也许会问,是不是今年双11互动使用了 Native 版本?是不是今年双11互动使用了缓存方案?是不是今年双11互动也使用了预渲染技术?然而,答案是,都没有,今年双11互动与历年狂欢城一样,仍然是 web 页面,且资源全部走 CDN 无额外缓存。

那么,我们是如何做到如此顺滑的加载体验呢?这就要从 Solution 说起。

Solution 是天马搭建体系的概念,主要解决的问题是将模块+数据组合成页面,简单理解就是负责页面渲染 Layout

自去年618起,淘系互动团队全部业务都开始迁移到天马搭建体系,Solution 也使用了官方推荐的通用 Solution。但是,通用 Solution 由于其通用性,冗杂了淘宝/天猫 60% 以上业务逻辑(粗略估计),体积大的同时易受其他业务影响导致稳定性风险高;而互动由于其业务特殊性,很多优化甚至稳定性保障方案的实现也需要在 Solution 层面进行定制。基于此,淘系互动团队定制了自己的页面渲染方案,即互动专用 Solution,这也是今年双11互动之所以那么快的核心原因。

得益于天马团队提供的新版 Solution 解决方案,既提供了标准化端渲染机制,又提供了基于插件进行业务定制的能力,还提供了产品化平台。互动专用 Solution 是在上述解决方案的基础上扩展实现,主要做了以下事情:

  • 精简基础依赖/逻辑,去除非必要依赖及非必要逻辑
  • 根据互动场景定制模块加载顺序,提供分批加载能力(当前主要是首屏/非首屏)
  • 提供数据处理能力,通过去除渲染无关字段实现数据自动瘦身
  • 内置基于客户端评分的稳定性保障方案,保障互动页面稳定性,详见下面稳定性方案章节
  • 增加资源及模块加载监控,保障稳定性
  • 集成互动通用能力,包括规范化 CSS/通用的渲染干预能力/常用的移动端调试方案/页面上下线能力等

image.png

EVA 研发体系

今年双11互动,非常多的用户反馈猫猫们太好看了、太萌了、特别可爱,很多人都纷纷来咨询小编是如何开发出来的。

image.png

接下来将重点阐述双11星秀喵加工厂--EVA 研发体系,TA 是淘系互动团队提供的从素材上传到端上渲染的互动研发的一整套解决方案,以引擎、框架、工具、平台为支点,致力于为广大前端带来简单舒适的互动研发体验。

EVA 研发体系,提供互动研发一条龙服务,我们是认真的

EVA Store:素材上传服务

大家看到的星秀喵,并不是3D模型,而是如假包换的2D骨骼动画。它使用 Spine 制作,通过网格自由变形和蒙皮技术在视觉上呈现“3D轴”的偏转,应用此类技术的动画软件还有大名鼎鼎的 Live2D。在 Spine 强大动画创作的支持下,双11的星秀喵才有了“3D化”的动画化表现力。一个标准的Spine动画文件包含一张雪碧图、一份骨骼数据以及一份动画数据,那么,我们应该如何上传到 CDN 呢?

EVA 为了解决互动业务中常见且频繁的动画和模型素材,提供了一站式的素材上传服务 EVA Store,包括帧动画、雪碧图、DragonBones、Spine、音频等,这些互动素材的协议标准是由阿里巴巴经济体互动小组统一制定。

image.png

EVA JS:2D 互动引擎

互动引擎是互动研发的基础,一款好的互动引擎能大大降低研发成本,EVA JS 应运而生。EVAJS 是一款轻量级,用于开发互动游戏的前端框架。EVA JS 支持插件体系,所有的互动游戏能力都是由插件提供的。EVA JS 一方面能够让前端互动游戏开发更加专业,另外一方面帮助前端开发者无需深度学习互动游戏技术即可开发互动游戏。TA 的整体设计是以游戏行业最佳实践的 ECS 设计模式为基础,拆分核心功能和组件能力,按需使用。

image.png

EVA JS 引擎

值得一提的是,EVA JS 还提供了无障碍化的支持。以往,游戏区实现无障碍需要手动在图层上添加辅助 DOM 来指定无障碍内容。今年双11,EVA JS 研制了 Canvas 上的无障碍技术,能够在手机淘宝/支付宝客户端上自动识别无障碍对象上的交互事件,降低研发成本的同时,让广大有障碍人士也能全方位体验到撸猫的乐趣,真正做到了互动无障碍体验。

640.gif

双11养猫无障碍体验

EVA JS 计划在2021年6月份前完成开源,了解更多,可参考 淘系前端互动引擎EVAJS架构与生态实现

Rax EVA:Rax 解决方案

素材和引擎都准备好后,就可以上手开始写代码了。市面上大多数的游戏引擎无法和 JSX、Hooks 结合在一起,这样,开发者就需要学习“两套框架”,再加上游戏引擎的学习成本也不低,整体上增加了开发门槛。为解决门槛高、上手难的问题,淘系互动前端团队设计了一套用于开发互动的 Rax 解决方案--Rax EVA,TA 是一个能够在Rax技术体系下,利用 EVA JS 的游戏研发能力,开发动画、游戏类场景的框架。它可以让开发同学用熟悉的 JSX 和 Hooks 语法编写动画、游戏场景的代码。

例如,我们把上一章节上传好的 Spine 动画显示出来(此处为示意版伪代码)

image

另外,对于前端来说,DOM 和 CSS 有天然的排版能力,这也是它们的优势。而游戏引擎是通过图形引擎渲染的,并不具备 CSS 那样高级的排版能力。于是在整个游戏互动的项目里,即存在 Canvas 又存在 DOM+CSS,也就是所谓的混合开发。Rax EVA 也为这类混合开发提供了方便快捷的方式,在 EVA 组件内,使用background / hud 这两个原生标签划分了游戏区域Z轴方向的三层布局,在这两个标签内以及 EVA 组件外,任何DOM 标签或其他熟悉的 JSX 都可以照常使用。

image.png

互动项目分层最佳实践

EVA Ware:弹窗规模化生产

除了基础的游戏研发外,EVA 研发体系还提供了一系列的低代码工具或服务,其中表现尤为突出的就是在今年 618 互动中就表现优异的弹窗规模化生成方案(以下称 Super Modal)。

互动研发最大的工作量之一就是弹窗的开发,相比今年 618,今年双11互动弹窗数量更甚。得益于 Super Modal 在弹窗研发上的抽象,所有的弹窗样式都是在平台上简易拖拽复制生成,通过 DSL+Runtime 提供端上稳定的渲染服务。弹窗的样式、文案可以作为页面配置项快速修改,前端在开发弹窗功能时,不用过多关注弹窗的样式问题,专注于弹窗的显示、关闭逻辑即可。除此之外, Super Modal 还在今年 618 功能的基础上,增加了相对定位布局、自定义组件、弹窗队列管理器插件等功能,并提供了简单的项目管理能力,进一步降低了弹窗开发的成本。

image.png

Super Modal 核心理念

了解更多,可参考 2020年618淘系技术分享-互动生产力进化之路

全局稳定性方案

细心的同学会发现,今年双11互动主页动效特别多,除了开场视频外,养猫和比拼的主界面上每个区域都在各种动。你一定在好奇,为什么你没有感觉到卡或者出现闪退的情况呢?这一切的背后,除了手机淘宝客户端架构组底层升级外,也有全局稳定性方案在护航。

互动场景中存在大量动效、视频,而过高的内存占用可能会引发客户端 crash 影响业务结果。一边是客户端需要更炫酷的玩法去支撑业务发展,一边是一些设备性能较差的用户反馈卡顿,如何让所有设备都能流畅的参与互动呢?比起不顾一切的上动效或是一刀切的砍玩法,显然存在一个更合理的选项--体验分级。淘宝技术质量团队提供了名为 Kite 的获取设备评分的统一降级 SDK,结合互动特性,如下图所示,我们将设备划分为 4 个等级,其中,容灾等级时页面将进入到一个异常兜底页面,用于应对一些低版本或者兼容性较差的机器场景。至此,我们完成了体验分级。

image.png

互动设备分级

接下来,就是针对不同设备等级的机型做不同降级方案,这也是互动的稳定性保驾护航重要的一环。基于客户端架构组提供的稳定性指标,我们需要整体考虑页面的内存、帧率、CPU 3 个指标,而动效、图片尺寸、游戏区画布尺寸、FPS 等配置则直接影响这 3 个指标的结果。然而,众所周知,在实际的开发过程中,对每张图片、每个动效做针对性的降级往往需要各种配置项,且人人参与,操作起来非常繁琐和耗时。因此,淘系互动前端团队在上面体验分级的基础上,通过 1 份静态全局降级规则 + 1 个运行时获取配置的稳定性保障 SDK,设计了一套完整的全局稳定性保障方案。

image.png

全局稳定性保障方案

正是这套稳定性方案,让双11互动在极大程度做到了高清互动、符合了架构组验收标准而且在线 22 天全程 0 故障。TA 让互动稳定性保障更加系统,也已经成为营销互动的标配。

总结展望

今年双11整体节奏从之前的“光棍节”到今年的“双节棍”,在这样变化的背景下,今年双11互动依然做到了参与人数再创新高。未来,我们希望完善 EVA 体系,通过不同的技术方案不断地优化我们的开发方式和生产关系,逐渐让更多的人来开发互动,实现“人人可开发,处处有互动”。

image.png

加入我们

淘系互动团队目前负责“芭芭农场”、“金币小镇”、“淘宝人生”等手淘内千万级的互动产品,重点打造双促、春节、市场PR等S/A级营销互动,同时为商家、达人、主播等沉淀和提供私域内的互动玩法。如果你对 工程/搭建/低代码研发方向 或者 WebGL/图形渲染/特效方向 等存在兴趣,欢迎微信联系/钉钉进群了解更多,完整 Job Model

image.png

查看原文

赞 6 收藏 2 评论 1

阿里巴巴淘系技术 发布了文章 · 11月19日

双十一SSR优化实践:秒开率提升新高度

前言

会场是每年双十一的主角之一,会场的用户体验自然也是每年最关注的点。在日趋复杂的业务需求下,如何保障我们的用户体验不劣化甚至能更优化是永恒的命题。

今年(2020)我们在不改变现有架构,不改变业务的前提下,在会场上使用了 SSR 技术,将秒开率提高到了新的高度(82.6%);也观察到在用户体验得到优化的同时,业务指标如 UV 点击率等也有小幅的增长(视不同业务场景有不同的提升,最大可达 5%),带来了不错的业务价值。

本文将从服务端、前端两个角度介绍我们在 SSR 上的方案与经验

  1. 前端在解决工程化、业务效果评估上的具体实践与方法论
  2. 服务端在解决前端模块代码于服务端执行、隔离和性能优化上的具体实践与方法论

(更多干货欢迎关注【淘系技术】公众号)

页面体验性能的核心指标

在正文开始前我们先介绍一下衡量的相关指标,从多年前雅虎 yslow 定义出了相对完整的体验性能评估指标,到后来的谷歌的 Lighthouse 等新工具的出现,体验性能的评估标准逐渐的统一且更加被大家认同。

会场的评估体系

基于 Web.Dev 以及其他的一些参考,我们定义了自己的简化评估体系

image.png

TTFB(Time to First Byte): 第一个字节的时间 - 从点击链接到收到第一个字节内容的时间

FP(First Paint): 第一次绘制 - 用户第一次看到任何像素内容的时间

FCP(First Contentful Paint): 第一次内容绘制 - 用户看到第一次有效内容的时间

FSP(First Screen Paint,首屏可视时间): 第一屏内容绘制 - 用户看到第一屏内容的时间

LCP(Largest Contentful Paint): 第一次最大内容绘制 - 用户看到最大内容的时间

TTI(Time To Interactive): 可交互时间 - 页面变为可交互的时间(比如可响应事件等)

大体上来说 FSP 约等于 FCP 或 LCP

会场的现状

我们的会场页面是使用基于低代码方案的页面搭建平台产出的,一个由搭建平台产出的会场页面简单而言由两部分组成:页面框架(layout)和楼层模块。

image.png

页面框架有一份单独的构建产物(即页面的 layout html 以及基础公共的 js、css 等 assets 资源)。每个楼层模块也有单独的一份构建产物(模块的 js、css 等 assets 资源,基础公共 js 的依赖版本信息等)。

页面框架的任务比较繁杂,负责页面的 layout、根据页面的搭投数据加载具体哪些楼层模块并组织分屏渲染模块。

会场原有的 CSR 渲染架构如下图,可以分成三部分:

  1. 客户端,包括手机淘宝等阿里系 App
  2. 文档服务,用于响应页面的主文档 HTML 清求
  3. 数据服务,用于响应页面的数据请求

image.png

原有的CSR渲染流程如下图

image.png

针对会场的性能,除了基础的大家都知道的前端优化手段之外,还结合客户端能力做过很多优化方案,比较具有代表性的有两个:

  1. 客户端主文档/Assets 缓存
在客户端内,我们利用了端侧提供的静态资源缓存能力,将 HTML 和基础公共的 JS 等资源,推送下发至用户侧客户端缓存。当客户端的 WebView 请求资源时,端侧可根据规则来匹配已下发的缓存包,在匹配成功后直接从本地缓存中读取对应的 HTML 和 JS 资源,而无需每次都请求网络、大大缩短了页面的初始化时间
  1. 数据预加载
从用户点击跳转链接到页面开始加载数据,中间还要经过客户端动画、WebView初始化、主文档 HTML 请求以及基础公共 js 的加载和执行这些过渡阶段,加起来有 几百ms 的时间被浪费掉。通过客户端提供的数据预加载能力,在用户点击后就可以立即由 native 开始页面的数据加载,等页面的基础公共 js 执行完需要使用页面数据时,直接调用 jsbridge 接口即可从 native 获取已经预先加载好的数据

在这些优化工作的基础上会场的体验性能已经可以达到不错的水准。

随着时间的推移,基于我们 CSR 渲染体系下的优化存在一些瓶颈:

  • 在线上复杂网络环境下(低网速、虚假的 WiFi)、Android 中低端机上的页面体验还是不尽人如意,特别是模块的加载和执行时间比较长,且这部分用户的占比有增长趋势
  • 作为拉新的一个重要手段,外部唤起淘宝或者天猫客户端因为需要时间来初始化一些功能组件,比如网络库等,页面的体验从体感上不能追平端内的会场
  • 会场是营销活动性质的业务,页面的复访率相对较低,且页面内容全面个性化。离线的 HTML 快照等用户侧缓存手段会因为缓存的数据过期导致出现重复渲染(打开更慢)、页面元素跳动(渲染闪烁、重排)等伤害体验的问题

还有没有优化手段呢?以一个 2020 年双十一会场页面,使用 PC 上的 Chrome DevTools 的 performance 离线分析结果为例,我们看一下重点的问题

image.png

可以看到页面从 FP 到 FCP 这段过渡的时间较长且只有背景色。FCP 到 LCP 这段时间处于等待图片加载的时间,优化空间较小,且难以衡量。

离线分析尚且如此,线上更有着复杂的网络环境/差异化的手机机型等,这样的“背景色”时间对用户的体验有很大的伤害,可能会让用户更加容易跳失。

我们的 CSR 渲染体系依赖前端+客户端的能力,从工作机制上已经很难再有比较大的提升。怎么才能让会场页面的体验更上一层楼呢,我们想到了服务端渲染(SSR), 针对 FP 到 FCP 这段时间进行攻坚优化

image.png

SSR 的线下测试结果,FP 到 FCP 从 825ms -> 408ms

SSR 要怎么做?

大的方向

SSR 本身意为服务端渲染,这个服务端可以在 任何地方 ,在 CDN 的边缘节点、在云上的中心机房或者就在你家的路由上。

实现一个 SSR 的 demo,熟悉的人应该都知道套路:

搞一个 Rax Server Renderer,传入一个 Rax Component,renderToString,完事了

业界也已经有很多实践的案例,但就像“把大象装进冰箱里”一样,看似简单的事情在双十一所要求的复杂场景稳定性下,需要有稳妥可实施的执行方案。

如何在现有的这套模块化、成熟的渲染架构之上使用SSR呢,一开始我们往常规的思路去想,直接在文档 HTML 响应中返回服务端渲染完成的 HTML,看下来存在几个问题:

  • 改造成本高,对现有的服务端架构改动比较大(CDN 缓存失效,文档服务的要求更高)
  • 无法复用现有的客户端性能优化能力,比如客户端主文档/Assets 缓存和数据预加载能力,会劣化完全可交互时间
  • CDN 缓存无法利用,TTFB 的时间增加,带来了新的 “完全白屏阶段”
  • SSR 服务不稳定因素较多,自动降级为CSR的方案复杂,无法保证 100% 能够降级
  • 主文档 HTML 的安全防护能力较弱,难以抵御黑产的恶意抓取

基于以上的问题,我们考虑是否还有其他的方案可以 低风险 、 低成本 地实现SSR呢?经过短暂且激烈的讨论,我们设计了「数据 SSR」架构方案,分享给大家。

数据 SSR 渲染架构如下,文档服务返回的内容保持静态化不变,数据服务新增调用一个独立的 SSR FaaS 函数,因为数据里有这张页面包含的模块列表和模块需要的数据,SSR FaaS 函数可以直接根据这些内容动态加载模块代码并渲染出 HTML。

image.png

这套方案在客户端内的场景下可以很好的将 前端 + 客户端 + 服务端三者的能力结合到一起。

有人可能会问,为什么这个方案会带来性能提升呢?不就是把浏览器的工作移到了服务端吗?我们举个例子(数据仅为定性分析,不代表真实值)。在正常 CSR 渲染流程下,每段消耗的时间如下,首屏可视时间总共耗时1500ms。

image.png

在SSR渲染流程下,在「调用加载基础js」之前的耗时都是一样的,由于下面两个原因,在服务端渲染的耗时会比客户端低几个数量级。

  • 服务端加载模块文件比在客户端快很多,而且服务端模块资源的缓存是公用的,只要有一次访问,后续所有用户的访问都使用这份缓存。
  • 服务端的机器性能比用户手机的性能高出几个数量级,所以在服务端渲染模块的耗时很小。根据线上实际耗时统计,服务端单纯渲染耗时平均 40ms 左右。

由于 HTML 被放到了数据响应中,gzip 后典型值增加 10KB 左右,相应的网络耗时会增加 30~100ms不等。最终 SSR 的渲染流程及耗时如下,可以看到 SSR 首屏的可视时间耗时为660ms,比CSR提升了800ms。

image.png

总而言之,「数据 SSR」的方案核心哲学是:将首屏内容的计算转移到算力更强的服务端

核心问题

大方向确定了,我们再来看看 SSR 应用到生产中还存在哪些核心问题

  1. 如何做到 CSR/SSR 的平滑切换
  2. 开发者如何开发出“能 SSR”的代码
  3. 开发者面向前端编写的代码在服务端运行的不可控风险
  4. 低代码搭建场景下,在服务端解决楼层模块代码加载的问题
  5. 服务端性能
  6. 怎么衡量优化的价值

别急,我们一个一个的来看解法

如何做到 CSR/SSR 的平滑切换?

在我们的页面渲染方案中,有两个分支:

  1. 页面未开启数据SSR,则与原有的 CSR 渲染流程一样,根据数据中的模块列表加载模块并渲染
  2. 页面开启了数据SSR并且返回的数据中有 SSR HTML,则使用 SSR 的 HTML 塞入到 root container 中,然后根据数据中的模块列表加载模块最终 hyrdate。

image.png

优点很明显

  • 风险低,能够无缝降级到CSR,只需要判断数据接口的响应中是否成功返回 HTML 即可。如果 SSR 失败或者超时(未返回 HTML),通过设置合理的服务端超时时间(例如 80ms),不会影响到用户的最终体验
  • 能够利用端上成熟的性能优化能力,比如客户端缓存能力,数据预加载能力。有客户端缓存能力,页面的白屏时间与原CSR一致;有了数据预加载能力,能够在页面加载之前就开始请求数据服务

在线上服务时,我们可以通过 HASH 分桶的方式对流量进行划分,将线上的流量缓慢的切换到 SSR 技术方案,既能保证稳定性,同时还可以方便的进行业务效果的进一步评估。

比较好的字符串转换为数字的 HASH 方法有 DJBHash,验证下来分桶效果较为稳定

开发者如何开发出“能 SSR”的代码?

很多做 SSR “demo”分享的往往会忽略一个重要点:开发者

在双十一的场景下,我们有百+的开发者,三百+的楼层模块,如何能推动这些存量代码升级,降低开发者的改造适配成本是我们的一个核心方向。

我们原有的楼层模块构建产物分为 PC/H5/Weex 三个,业界通用的是针对 SSR,单独构建一个 target 为 node 的构建产物。在实际 POC 验证过程中,我们发现其实绝大部分的模块并不需要改造就可以直接适配 SSR,而新增构建产物会牵扯到更多的开发者,于是想找寻别的解决方案。

复用现有 Web 构建产物的一个问题是,Webpack 4 默认会注入一些 Node 环境相关变量,会导致常用的组件库中的类似 const isNode = typeof process !== 'undefined' && process && process.env 的判断异常。不过还好这个是可以关闭的,开发环境下其他的类似 devServer 等的注入也是可以关闭的,这给了我们一点慰藉,最终复用了 Web 的构建产物。像更新的 Webpack 5 中把 target 的差异给弱化了,也可以更好的定制,让我们未来有了更好的社区化方向可以继续靠拢。

解决完构建产物的问题,在本地开发阶段,Rax 团队提供了 VSCode SSR 开发插件,集成了一些 best practice 以及 lint 规则,写代码的时候就可以发现 SSR 的相关问题,及时规避和修复。

image.png

同时我们模拟真实线上的环境,在本地提供了 Webpack 的 SSR 预览调试插件,直接 dev 就可以看到 SSR 的渲染结果。

针对开发者会在代码中直接访问 windowlocation 等变量的场景,我们一方面开发了统一的类库封装调用抹平差异,另一方面在服务端我们也模拟了部分常用的浏览器宿主变量,比如 windowlocationnavigatordocument  等等,再加上与 Web 共用构建产物,所以大部分模块无需改造即可在服务端执行。

接下来的模块发布阶段,我们在工程平台上增加了发布卡口,若在代码静态检查时发现了影响 SSR 的代码问题就阻止发布并提示修复。

image.png

由于实际的业务模块量较大,为了进一步缩小改造的范围,测试团队联合提供了模块的批量测试解决方案。具体的原理是构造一个待改造模块的 mock 页面,通过比较页面 SSR 渲染后的截图与 CSR 渲染后的截图是否一致,来检测SSR 的渲染结果是否符合预期

image.png

开发者面向前端编写的代码在服务端运行的不可控风险

尽管我们在开发阶段通过静态代码检查等方法极力规避问题,实际上仍然存在一些针刺痛着我们的心

  1. 开发者把全局变量当缓存用造成内存泄露
  2. 错误的条件结束语句导致死循环
  3. 未知情况页面上存在不支持 SSR 的模块

这些疑难点从 SSR 的机制上其实很难解决,需要有完善的自动降级方案避免对用户的体验造成影响。

在说更详细的方案前要先感谢我们自己,前端已经提前做到了 CSR/SSR 的平滑切换,让服务端能每天不活在恐惧里 = =

对于机制上的问题,可以引申阅读到之前分享过的 在 Node.js 中 ”相对可靠” 的高效执行可信三方的代码。我们这里主要聚焦在如何快速止血与恢复。

image.png

FaaS 给服务端降低了非常大的运维成本,“一个函数做一件事”的设计哲学也让 SSR 的不稳定性局限在了一块很小的部分,不给我们带来额外的运维负担。

低代码搭建场景下,在服务端解决楼层模块代码加载的问题

业界分享的一些 SSR 场景基本都是整页或者 SPA 类型的,即 SSR 所使用的 bundle 是将整页完整的代码构建后暴露出一个 Root Component,交由 Renderer 渲染的。而我们的低代码搭建场景,由于整个可选的模块池规模较大,页面的楼层模块是动态选择、排序和加载的。这在前端 CSR 情况下很方便,只要有个模块加载器就可以了,但是在服务端问题就比较复杂。

image.png

还好我们的模块规范遵守的是特殊的 CMD 规范,有显式的依赖关系声明,可以让我们在获取到页面的楼层组织信息之后一次性的把页面首屏的全部 Assets 依赖关系计算出来。

image

在服务端加载到代码后,我们就可以拼装出一个 Root Component 交给 Renderer 渲染了。

服务端性能

性能上主要是有几个方面的问题

  1. 机制问题
  2. 代码问题
机制问题

由于楼层模块很多,在实际执行的过程中发现存在一些机制上的性能问题

  1. 代码的 parse 时间较长且不稳定
  2. 流量较低情况下难以触发 JIT

优化方案的话比较 tricky

  1. 缓存 vm.Script  实例,避免重复 parse
  2. 期望一致性 HASH 或自动扩缩容(本次未实现)

巡检的时候还观测到存在小范围的 RT 抖动问题,分析后定位是同步的 renderToString 调用在微观上存在排队执行的问题

image.png

在这种情况下会造成部分渲染任务的 RT 为多个排队任务的渲染 RT 叠加,影响单个请求的 RT(但不影响吞吐量)。这种问题要求我们需要更精确的评估备容的资源。机制上有效的解法推测可以让 renderToString 以 fiber 的方式执行,缓解微观排队造成的不公平的问题。

代码问题

性能问题的分析当然免不了 CPU Profile,拿出最爱的 alinode 进行分析,很快的可以找到热点进行针对性优化。

image.png

上图中标蓝的方法为 CMD 加载器计算依赖的热点方法,对计算结果进行缓存后热点消除,整体性能提升了 80% 》.》

怎么衡量优化的价值

这么多的投入当然需要完善的评价体系来进行评价,我们从体验性能和业务收益两个分别评估。

体验性能

基于兼容性较好的 PerformanceTiming (将被 PerformanceNavigationTiming 替代),我们可以获取到前端范畴下的一些关键的时间

  • navigationStart
  • firstPaint

其中 navigationStart 将会作为我们的前端起点时间所使用。在前端之外,对用户的交互路径而言真正的起点是在客户端的点击跳转时间 jumpTime ,我们也联合客户端进行了全链路埋点,将客户端 native 的时间与前端的时间串联了起来,纳入到我们的评价体系中。

在最开始的核心指标中,我们看到有 FCP、TTI 这几个指标。目前的 Web 实现中,还未有兼容性较好的可以线上衡量的方案(线下可以使用 DevTools 或者 Lighthouse 等工具),因此我们通过其他的方式来做近似代替

image
线上取到的数据通过 tracker 的方式进行无采样上报,最终我们可以通过多个维度进行分析

  • 机型
  • 网络条件
  • 是否命中 SSR
  • 是否命中其他前端优化

主要的衡量指标有

  • 从用户点击到 FCP 的时间(FCP - jumpTime)
  • 从 NavigationStart 到 FCP 的时间(FCP - NavigationStart)
业务收益

这部分很忐忑,体验的优化是否会带来真金白银的收益呢?我们直接通过 AA 和 AB 实验进行业务数据的分析。

基于之前的切流分桶,我们可以通过类似 hash 值 % 10 的方式将流量分为 0~9 号十个桶,首先通过 AA 实验验证分桶是否均匀

image

统计指标举例

这一步是保证分桶的逻辑本身不会有数据的倾斜影响置信度。接下来我们再进行 AB 实验,逐步增加实验桶验证业务数据的变化。

最终的效果

搞了这么多,得看看产出了。在这次双十一会场中,我们切流了多个核心的页面,拿到的第一手数据分享给大家。

image

循环.gif

小米5 骁龙 820 处理器

可以看到,在 Android 碎片化的生态的下,带来的提升甚至超出了预期,这也给了我们未来更大的动力,将前端 + 客户端 + 服务端的能力更有效的结合到一起,带给用户更好的体验,给业务创造更大的价值。

未来的渲染架构还会更复杂吗?

为了更好的用户体验,当然会了!我们可以简单的看看短期和长期的一些事情

电商体验指标的统一定义

长期以来,业务在用户侧的实现有 Web、Native、Hybrid 混合开发等多种选择,每个体系都有着自己的封闭体验衡量标准,这就造成了一些“鸡同鸭讲”的问题。而 Web.dev 中所定义的 FCP、LCP 通用评价体系也并不适合电商场景,能展示出核心的商品/店铺其实对一张页面来说就完成了它的使命。

后续我们可以将体验指标评估标准对齐,将起点时间、绘制完成时间等在多个体系对齐概念与实现,达到互相之间可以横向比较良性竞争的状态。

工程上还有更多的事情要做...

在 Webpack 5 的 Release Note 中,我们可以看到 Webpack 正在弱化 target 的一些特殊处理,将 Web 描述为了 browserlike 的环境。同时还提供了自定义 browserlist 的能力,可以给予开发者更方便处理跨端的兼容性问题的能力。这一变化将推动我们更快的拥抱社区,获得更好的开发体验。

现有的 SSR 静态代码检查方案会有一些漏网之鱼,还有没有更完善的方案能从工程上前置解决代码风险(性能、安全)问题也是未来的一个方向。

ServiceWorker Cache 等离线缓存快照

复访率高,变化不太大的页面可以利用 ServiceWorker Cache 等方案,将之前的渲染结果缓存下来,命中缓存直接用,未命中缓存 SSR。降低服务端压力的同时可以让体验更好。

SSR 的性能优化与安全

现阶段的 Node.js 或者说 V8,对于动态加载代码的情况支持并没有特别的完善,缺失了安全相关的保护逻辑。并且从性能上来说,SSR 属于 CPU 密集型的 workload,纯异步的优势并不明显,也可能需要一些特殊的解决方案来配合。

外部投放场景的覆盖

「数据 SSR」的方案是端内的最佳方案,却是外投场景的最劣方案。外投场景下由于用户是在第三方 App 中打开页面,相应的缺失了客户端的定制化优化能力,SSR 调用会造成数据服务的 RT 增加,反而推后了 FCP。

这时候古老的 HTML 直出方案又可以再捞回来了。

image.png

核心在于

  1. 利用 CDN 的边缘计算能力,可以较好的做到“动静分离”以及容灾
  2. 使用中心化的 SSR 函数,可以将 SSR 的不稳定性与 CDN 的可靠性分离,保证近端链路的可靠,避免出现近端直接不可用导致的无法恢复

近端的流式方案经常被提及,但是在实际的使用中会遇到当流式输出遇到错误时,用户侧无法有效容灾的问题(HTML 损毁,无法补救)。通过“动静分离”可以将页面分为

image.png

仅将 Root Container 进行动态化,进而在享用流式输出带来的 TTFB 提前的好处的同时又能兼顾容灾 SSR 的不稳定。和业务团队更可以一起探讨下如何将页面更好的从业务上做到“动静分离”,而不是仅从技术的角度出发。

总结

渲染架构的不断改进实质上是我们在有限且变化的环境下(终端性能、复杂网络和多变业务)自发做的适应,也许有那么一天,环境不再是问题,性能优化的课题将会消失。我们项目组有时候还开玩笑,等明年手机叒换代了,5G 100% 普及了,是不是这些优化都可以下线了😝

但是!现在看理想还有点远,在 2020 的双十一会场我们走进了一个新的深水区,期待未来技术与业务结合能带给广大用户更棒的体验!

查看原文

赞 9 收藏 8 评论 1

阿里巴巴淘系技术 发布了文章 · 11月18日

淘宝直播“一猜到底”——移动端实时语音识别技术方案及应用

双11淘宝直播App·一猜到底

过去一年淘宝直播快速发展,截止2020年9月底,80个淘宝直播产业基地在全国落地开花,从农村走出10万农民主播,直播真正意义上成为帮助商家和消费者完成交易的利器,同时通过各种互动玩法让直播购物变得有趣好玩。在2020年双11开始阶段,淘宝直播App升级了18年直播答题「点题成金」的玩法,推出「一猜到底」新玩法。如果说传统的直播答题是「选择题」,一猜到底的玩法更像是几万人同时在线的「抢答题」,将答题方式从文字选择升级成语音抢答,给出猜中价格高低提示,让用户增加了更多的参与的乐趣。

为了实现比肩综艺现场的直播竞猜体验,我们一次压上了由达摩院语音实验室阿里云PAI团队、淘系技术直播App和端智能MNN团队组成的全明星阵容,通力协作之下,一举实现了工业界首个用于直播的移动端语音识别

(更多内容干货可关注【淘系技术】公众号)

业务流程和技术挑战

image.png

「一猜到底」整体玩法链路如上图所示,主播口播开始后,用户需要在人数和时间未满前,按住按钮,通过语音报出价格,系统通过本地语音识别能力进行识别和结果比对,提示用户所报价格“过高”还是“过低”,直到答对或者超时结束。在每一关有限的作答时间内,用户往往需要多次竞答,才能逼近商品的真实价格。于是,实时语音识别能不能准确且快速地识别用户的报价,直接决定了「一猜到底」的成败。

不同于一般的语音识别应用,一场顶流的淘宝直播,可以聚集百万乃至千万的用户围观。这么多用户同时进行语音识别,会出现非常多的请求,如果采用云端识别对服务压力和服务质量都有非常大的挑战。项目开始时实验了端侧和云侧识别的两种方案,发现云侧方案难以支撑这样的活动,最终选择了端侧方案,确定端侧识别方案之后,发现也不是康庄大道,主要存在以下技术难点:

  • 高精度高性能的本地语音识别

目前行业比较成熟的是服务端的语音识别方案,完全照搬服务端方案到移动端也不现实,需要创建一套适合移动端运行的语音识别方案。同时,直播场景下的语音答题噪声较大,对语音识别的准确度要求较高,语音识别速度也会对用户的答题速度造成巨大影响。

  • 语音模型和资源包体积过大

考虑到活动特性,端侧的语音识别引擎需要内置在包内,而且越小越好。经过客户端研发评估,如何做到15MB以内甚至更小的语音模型是关键,因此需要极致的模型压缩能力支持。

  • 端侧资源有限,性能压力大

直播场景本身就已经很占用资源,叠加直播场景下做语音识别,对语音识别过程中的CPU、内存占用,都有很大的要求,高性能的推理和优化成为模型落地的最大拦路虎。

移动端实时语音识别技术大揭秘

image.png

阿里达摩院语音实验室早在2015年就研发出了第一代移动端离线语音识别方案,近来结合PAI模型压缩、MNN高性能推理引擎,实现了移动端离线和流式端到端语音识别方案,满足语音指令、语音识别、实时翻译等场景需求。根据「一猜到底」项目需求,我们选取"基于SAN-M的离线端到端语音识别"方案,通过极致的模型压缩和性能优化,最终实现模型大小小于15MB、内存占用低于60MB、1s语料识别快于50ms的高性能方案。

基于SAN-M的离线端到端语音识别

目前,最具代表性的离线端到端语音识别模型LAS[1]和Transformer[2]都是基于Attention-Encoder-Decoder的。LAS采用基于BLSTM的Encoder和基于单向LSTM的Decoder;而Transformer则采用Multi-head Self-Attention模块组建Encoder网络,采用Masked Multi-head Self-Attention组建Decoder网络。

在公开评测任务集上,Transformer较LAS在性能上有优势,同时由于采用了Multi-head,训练并行化效率更高。我们分析了Self-Attention和DFSMN memory block[3,4]之间的关联性:Self-Attention可以理解为采用了context-dependent系数进行全局建模,而DFSMN的memory block则采用了context-independent系数进行局部建模。对于语音识别,局部声学建模和全局语义建模都非常重要,因此我们提出了如下图所示的SAN-M模型结构,高效地融合了Self-Attention和DFSMN memory block。

image.png

SAN-M模块如上左图所示,将Self-Attention和DFSMN memory block融合一个模块,有效的结合了Self-Attention的全局长时建模能力和memory block的局部长时建模能力。基于SAN-M模块构建了如上右图的Encoder-Decoder离线语音识别系统(SAN-M-E2E-ASR),并在开源的1000小时AISHELL-2中文识别任务中获得了当前该任务的最优性能(CER=5.61%);在工业量级的2万小时中文识别任务中,该系统也显著优于我们之前线上的CTC系统和标准Transformer系统。

针对本次识别场景,我们最终实现了不到40MB的端到端模型,而识别性能则可以媲美上一代整体超过100GB大小的云端DFSMN-CTC系统。我们在finetune数据上进行了不同维度的挑选和搭配,并做了不同策略的数据扩增来覆盖多样的识别情况。针对模型输出的token,也进行了一定压缩,并拉低了与本次任务无关的token概率来降低误识别率。在ITN模块,我们采用精小的FST(Finite State Transducer)来实现规则网络,用状态转移来实现文字到阿拉伯数字的转换,通过边上权重来控制其转换方向,并在简略读法、谐音、容错上也做了一系列路径优化。

基于PAI-MNN云端一体化模型压缩

虽然达摩院语音实验室通过定制化语音识别模型设计,将原有的170MB模型裁剪至不到40MB,但是考虑到移动端的资源情况,我们还需要通过PAI-MNN云端一体化模型压缩方案,进一步将模型基本无损地压缩到15MB以内。

image.png

从训练、模型压缩到优化部署的PAI-MNN云端一体方案

PAI混合精度量化流程

image.png

PAI混合精度量化流程

上图显示了PAI团队 (PAI: Platform of A. I. in Alibaba)研发的无数据标注干预的自动混合精度量化流程Label-free AMP Pipeline,AMP: Automatic Mixed Precision),包括量化误差预补偿、离线标定、量化噪声分析与混合精度决策四个阶段,主要创新点包括:

  • 支持端到端Transformer的离线后量化:
  • PAI团队的后量化方法,引入了循环张量探针,以支持端到端Transformer的离线后量化。
  • 相比于拆图量化、量化训练等,端到端后量化具备快捷、高效的优势;
  • 集成了丰富的后量化策略,为后量化的精度鲁棒性提供了坚实保证,基本策略包括:
  • KL算法的改进,能够有效减少输入/输出张量的量化噪声;
  • EasyQuant参考文献 [5])的使用,可进一步减少输入/输出张量的量化误差,尤其能改善INT7等更低精度量化的效果;
  • Bias Correction参考文献 [6])通过补偿网络权重的量化偏差(均值与方差的偏差),以减少权重量化噪声;同时对Bias Correction的适当改进,增强了对SAN-M ASR模型的补偿效果;
  • ADMM参考文献 [7])亦可优化权重量化参数,减少权重量化噪声;也适当改进了ADMM的使用,从而在交替方向迭代范围内,确保权重量化误差最小;
  • Weight Adjustment参考文献 [8])在Kernel weight按Per-tensor量化时,通过Per-channel形式的等价均衡变换,可以减少Weight量化误差。
  • 无Label干预的混合精度量化流程:
  • 该流程从模型输入到混合精度决策,无需数据标注(Label)的干预,简洁易用、快捷有效;
  • 量化误差按逐层统计,且能准确反映每个网络层的量化敏感度,为混合精度(INT8/FP32混合)决策提供了可靠基础;
  • 通过控制回退的网络层数,可选择出精度与模型容量折中最佳的帕累托最优解,完成多目标优化;
  • 生成的混合精度量化表,能够对接移动端推理框架MNN,以生成低延迟、高推理精度的运行时推理引擎;从而构成了完整的工具链路,即从混合精度量化、到移动端的推理部署;
  • AMP Pipeline不仅适用于移动端,也适用于CPU/GPU优化部署,体现了PAI云端一体的优势所在。

基于PAI AMP Pipeline,有效实现了SAN-M模型的离线后量化(PTQ: Post-training Quantization)。为了保持算法模型识别精度,经AMP INT8量化之后(回退3个Op,分类层保留为FP32实现)。

为了解决压缩率的问题,MNN模型转换和优化工具对回退的算子统一使用权重8bit存储、float计算的方式进行优化,进一步压缩模型大小。通过一套统一格式的模型压缩文件,经过PAI AMC优化的模型可以顺滑无缝地转换到MNN的格式。

MNN模型转换工具基于现有的图优化流程,根据该模型压缩文件将float模型转换成MNN模型的同时完成离线量化,具体过程如下:

  • 根据量化表中提供的tensor name,在TensorFlow的计算图中生产和消费该tensor的边上同时插入一个自定义的量化和反量化算子。
  • 将TensorFlow的计算图转换成MNN的计算图,其中自定义的量化和反量化算子转换成MNN量化(FloatToInt8)和反量化(Int8ToFloat)算子。
  • 算子融合:将支持量化的算子、输入的反量化算子和输出的量化算子融合成一个Int8的算子。
  • 最后消除成对的MNN量化和反量化算子。

image.png

最终,SAN-M模型在众包测试集上的WER绝对损失低于0.1%、SER绝对损失低于0.5%、理论压缩比约为3.19倍。

基于MNN推理引擎的实时高性能计算

image.png

为了在移动端上实现实时的端到端语音识别模型推理计算,MNN在全链路上做了诸多优化。

端到端语音识别模型基于Transformer结构,包含一个对输入音频特征编码的Encoder和一个自回归解码的Decoder。这类模型结构要求MNN支持Control Flow、Dynamic Shape和Zero Shape等特性,因此,MNN首先在框架层面对这些特性进行了支持和完善:

  • MNN重构了Control Flow支持方案,提供用户透明的functional control flow实现,并支持了TensorFlow 1.x的控制流模型转换,为用户提供一站式的部署体验。
  • 对于Dynamic Shape的支持,MNN将整图按照动态形状算子划分为多个分段子图。在代码层面,一个子图对应一个Module,Module支持嵌套,即整图被表达为一个由Module组成的调用树,树的每个叶子节点可以使用一个Session来执行,Session每次执行前resize,重新进行shape推理和分配内存。
  • Zero Shape指的是模型中某些Tensor的shape存在0值,比如 (1, 0, 256),这种情况大多是为了给while-loop中某些循环变量提供初始值而引入的。MNN在形状推理和执行逻辑上对Zero Shape进行了支持。

之后,MNN根据达摩院模型新增了LayerNorm FuseConstant Folding、重复Reshape算子消除等图优化方法。图优化之后的计算图更容易和其他优化方法组合使用,比如,Constant Folding后MatMul的一个输入可能被替换成一个Constant节点,因此就可以转换成FullyConnected或Conv1x1进行加速,并且也更容易利用模型压缩方法对权重进行量化。

而后,语音模型的耗时重点仍然是矩阵乘法。MNN通过更优矩阵乘分块、基于 NC4HW4 布局优化前后内存布局转化、Strassen 算法改进等策略,优化了整体的卷积和矩阵乘的性能,ARM 架构上性能提高了 10%-20% ,保障了语音模型的高效运行。

同时,MNN最新提出的几何计算机制也在实时语音识别起到了重要作用。几何计算是MNN为了解决设备碎片化问题而提出的一种新机制,其核心在于把坐标映射标准化,以便统一实现与优化。在几何计算的支持下,我们可以较简单地合并相邻的纯形变算子,从而降低访存需求,提升模型运行性能。

最后,在PAI-MNN云端一体化模型压缩的加持下,我们利用量化表和有限回退机制,在精度损失可控的前提下,进一步降低了移动端上的计算总量。

RTF (real time factor),即实时率,表示识别一秒钟音频需要的耗时。

image

在这一系列组合拳之下,我们才最终在目标设备上,将RTF降低到了目标值0.02以下,从而实现实时语音识别,让「一猜到底」得以走到每一个用户的面前。

总结与展望

通过这次项目合作,基于高性能推理引擎MNN,结合一流的语音模型设计和模型压缩技术,我们已经能在移动端上实现实时的语音识别,并通过了双11核心场景的考验。

但我们并未止步于此。

达摩院语音实验室在千人千面的个性化语音识别上的研究工作业已展开,在保护用户隐私的前提下实现如联系人、住址、搜索历史等词汇的识别。PAI团队会继续携手MNN团队,进一步探索围绕端侧设备的精简模型设计和自适应模型架构优化方案。而MNN团队,则会持续建设流式识别、混合计算、编译优化等机制,为ASR、NLP等AI应用在端侧的发力提供最高效、最稳定的坚实后盾。

相信在不远的未来,我们就能为用户带来更加有用、有趣的AI交互体验。

参考

===

[1] Chan W, Jaitly N, Le Q, et al. Listen, attend and spell: A neural network for large vocabulary conversational speech recognition[C]//2016 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2016: 4960-4964.

[2] Vaswani, Ashish, et al. "Attention is all you need." Advances in neural information processing systems. 2017.

[3] Zhang S, Lei M, Yan Z, et al. Deep-fsmn for large vocabulary continuous speech recognition[C]//2018 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2018: 5869-5873.

[4] Zhang S, Lei M, Liu Y, et al. Investigation of modeling units for mandarin speech recognition using dfsmn-ctc-smbr[C]//ICASSP 2019-2019 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2019: 7085-7089.

[5] Di Wu, Qi Tang, Yongle Zhao, Ming Zhang, Ying Fu, Debing Zhang, "EasyQuant: Post-training Quantization via Scale Optimization", arXiv  preprint  2006.16669, 2020.

[6] Ron Banner, Yury Nahshan, Elad Hoffer, Daniel Soudry, "Post-training 4-bit quantization of convolution networks for rapid-deployment", arXiv  preprint 1810.05723, 2018.

[7] Cong Leng, Hao Li, Shenghuo Zhu, Rong Jin, "Extremely Low Bit Neural Network: Squeeze the Last Bit Out with ADMM", arXiv  preprint 1707.09870, 2017.

[8] Markus Nagel, Mart van Baalen, Tijmen Blankevoort, Max Welling, "Data-Free Quantization Through Weight Equalization and Bias Correction", arXiv preprint  1906.04721, 2019.

查看原文

赞 2 收藏 0 评论 0

阿里巴巴淘系技术 发布了文章 · 11月17日

2020天猫双11前端体系的建设与挑战

今年双十一整体节奏从之前的“光棍节”到今年的“双节棍”,具体业务上也有很多变化和调整,应了阿里的土话“唯一不变的是变化”。面对这些变化,是挑战也是机会,我们要做的就是,“既要”高效支撑保障业务先赢,“又要”确保体验和稳定性带给用户极致体验,“还要”追求创新让前端持续演进。为了实现“既要、又要、还要”,包括技术方案、流程机制、人员组织等各方面都进行了大量的设计和保障。最终第一次双峰的双十一圆满结束,淘系前端也实现了自己的目标,包括应用大量优化手段和创新方案带来业务转化提升;将FaaS、PHA、ESR等技术应用在更多场景,分别向服务端、客户端、CDN节点进一步拓展了前端的能力和边界;应用视觉还原、一体化研发等提升研发效率,大幅缓解资源瓶颈等等。下面会整体介绍一下淘系前端在今年双11的思考和沉淀,希望对大家有所助益。后续也会有各个专项的系列文章,希望大家持续关注。

(更多干货内容可关注【淘系技术】公众号)

变化 & 挑战

今年的双十一,首先感受到的就是源源不断的变化。

单峰变双峰:双十一从之前的一个波段变成今年的两个波段,大促的三个阶段预售、预热、正式也都对应的翻倍。首先带来的是研发工作量的大幅增加,在时间排期不变、工作量增加、人员不变的情况高效的完成需求研发是第一重挑战;其次面对6个阶段的状态变化,如何保持准确切换、稳定运行、体验流畅是在双峰期间要重点保障的内容;最后面对超过20天的超长作战期,安全生产、人员状态保持、快速反应都需要有强力的组织和机制进行保障。

image.png

图:双十一节奏

首页大改版:最新的淘宝首页首屏内容有颠覆性的变化,比如首屏内容简化,推荐提前,频道作为内容嵌入推荐等。各个业务在缺少固定的流量入口的情况下,包括运营策略、产品策略、设计方案、技术方案都需要积极调整。同时在各个场景的推荐能力也需要持续增强,今年双十一通过将坑位数扩展到1000+,理论可达无限扩坑;通过智能UI提升用户点击率。

Group2.png

图:手淘版本对比

业务变化:业务创新和新玩法层出不穷,包括mini详情、旗舰店、价格表达、笔笔返、芝麻购等在内的很多业务都是全新的表达、颠覆式的升级。即是业务上新的尝试,在技术上也要解决架构选型、对账、一致性表达、排期等问题。

做好本职

首先要做的就是做好本职工作,保障需求研发和稳定性。需求研发方面,我们通过D2C实现了大部分UI模块自动开发、通过建设Eva互动体系降低互动研发成本、通过Serverless的一体化研发提升研发和运维效率,使前端不再成为资源瓶颈。稳定性上,也通过一系列机制和工具体系进行保障。同时增加一块大家平时可能不太关注的资损防控的策略和方案。

D2C研发提效

去年双十一我们设立了研发效率专项,核心就是通过 设计稿生成代码(Design to Code, D2C)平台Imgcook 来提升研发效率。最终在去年的双十一大促会中承接了 78.94% 的新增模块代码自动生成,代码可用率达到 79.34%。

今年前端智能化助力前端研发模式升级,数个 BU 共建前端设计稿识别算法模型和数据集,设计稿生成代码技术体系全面升级,如对 UI 多态、直播视频组件、循环的智能识别增强等。今年双十一会场承接了 90.4% 的新模块代码智能生成,代码可用率达到 79.26%(对比去年升级设计稿智能检查能力,视觉稿无需人工辅助调整)。得益于D2C的研发提效,今年并没有出现往年借调资源投入会场开发的情况。相比传统模块开发模式,使用设计稿生成代码技术后编码效率(模块复杂度和研发耗时比值)提升68%,固定人力单位时间模块需求吞吐量增加约 1.5 倍。

image.png

图:D2C操作流程

互动研发升级

在电商领域,互动是一个重要的用户增长方案,在提升用户黏性、活跃以及拉新上都发挥着重要的作用。今年双11,淘系互动团队推出了“超级星秀猫”,我们不盖楼、不开车,全民参与养猫出道,3只风格各异的萌猫咪一经问世,瞬间俘获了无数消费者的心。通过 EVA 互动体系一整套解决方案,大幅提升研发效率,支撑全民养猫猫在手淘、猫客、支付宝等多个 APP 互通。借助客户端能力及 EVA 互动体系将性能与内存良好控制,让多数用户体验高清稳定的互动,实现 0 故障及秒开,同时星秀猫参与人数再创新高。后续的系列文章将具体阐述淘系互动前端团队是如何做到双11互动又快又好又稳,内容涵盖互动基础、EVA研发体系和全局稳定性方案3个方面。

image.png

图:互动效果图

Node FaaS一体研发

Serverless云+端研发模式通过打通页面代码和服务代码进行一体研发,使得前端可以从前台页面到后端服务完整支撑,节省中间沟通和联调成本。在天猫榜单以及V榜的落地,使得双11 Node FaaS 相关业务整体研发效率提升38.89%。行业导购双十一需求也在云+端的新模式下支撑外包快速入场,使得整体提效约20%。

稳定性保障

稳定性保障贯穿从项目启动到结束的整个双十一周期,下面从几个重点方面进行简单的介绍:

变化评估:每年的双十一都是站在巨人的肩膀上,都经过了上一次双十一的考验。主要的风险就变成新增的部分以及变化的部分,这里的变化既包括技术上的变化也包含人员上的变化。要做到对变化的充分评估,在99大促进行验证,并且保证99大促后不再进行变化,以一个稳定的状态迎接双十一。

压测:首先要进行流量评估,借鉴去年数据的同时结合今年的变化,进行相应的机器、带宽等资源准备。完成单线路压测,保证在预估流量模型下,自己的服务和上下游都能够运转正常。进行全链路压测,核心验证在0点高峰时各业务并发的情况的运转情况,尤其是一些底层公共服务,以及优先级的保障情况。

兜底&预案:兜底一般指在大流量或其他不可控因素的情况下,如何将用户体验和业务损失降低到最小。预案需要评估可能遇到的各种情况,以及对应的处理方案。

验收:功能预演,按照用户的所有使用路径进行操作,目前这个工作仍是人工。时间穿越,将页面和系统的状态都调整为活动时间来验证,需要打通上下游的各个系统并形成联动。机型验收,基本分为高端机、中端机、低端机,分别进行验收,很多业务都需要针对低端机做功能降级。稳定性验收,单独页面的性能和稳定性各自保障,但业务叠加后很可能存在问题,尤其像会场、互动、直播、旗舰店等内存消耗大户,互相之间都有引流,切换后很难保证,需要整体全链路验收。

变更&应急:历次的故障数据表明,大部分的问题都是由于变更导致的,如何做好变更管控尤为重要。根据时间分为弱管控、强管控期;根据业务等级分为集团核心应用、BU核心应用、非核心应用等;建立变更的CR和审批的机制。应急主要指在核心活动期间,问题、舆情、故障等流转机制,针对问题发现、定位问题、修复问题时间作出要求,不同等级如何决策作出安排。

监控:淘系前端持续进行监控能力的建设和升级。需要保障大促高峰的可用性以及报警的实时性,覆盖所有的业务场景。针对越来越复杂的场景,需要端到端的监控和数据分析平台。灰度过程缺少度量和定点监控。根据这些问题和需求,jstracker提供了安全生产的整体解决方案,打造端到端的前端监控与数据分析平台,打造实时监控、多端覆盖、数据分析、智能化的数据平台。同时根据页面情况、错误日志、源站数据、FaaS日志等打造了双十一的前端数据大盘。

资损防控

一直以来前端资损防控是平台非常薄弱的一环,前端触发的资损和舆情问题不在少数。之前全靠开发同学的经验和意识来保证,缺少体系化的资损防控能力。去年开始组织了团队层面的集中筛查和人工预演,对人力和时间的消耗非常巨大,并且很难保证质量并进行积累和沉淀。所以为了能有一种成本更低、预防效果更好的方式进行资损防控,2020年 S1 伊始,就重点对资防做相关产品化的设计和实现。同时今年也重点增加了商家、运营中后台侧的资损防控。

我们将资损防控氛围了三个阶段,研发阶段、操作阶段、运行阶段。研发阶段给存在资损风险的仓库打标,将常规的价格、优惠、默认文案等case进行枚举,通过静态扫描、UI测试用例扫描等方式进行防控。操作阶段,主要是指商家、运营进行优惠、权益等设置的阶段,通过表达方式统一(避免5折、0.5折造成理解差异)、二次确认、限定边界值、低价预警等进行防控。运行阶段有快照对比、服务端数据对账等方式,运行阶段的防控相对滞后,发现时很大概率已经造成实际的影响。

然而,目前仍是预防为主,不能百分之百保障没有资损故障发生,接下来我们还在构思链路级别的、生产环境上的防控手段,建设一些告警和自动止血为平台保驾护航。

业务价值

做好本职的基础上,我们希望给业务带来增量价值。本章从会场性能优化提升转化、基础链路新方案提升转化、唤端技术定制策略提升精准率、智能UI为不同人群提供不通过UI提升点击等4个方面来介绍。

性能提升

会场是每年双十一的主角之一,会场的用户体验自然也是每年最关注的点。在日趋复杂的业务需求下,如何保障我们的用户体验不劣化甚至能更优化是永恒的命题。今年分别使用了预渲染方案和SSR方案进行优化,首先是重新定义了秒开的标准,从原来的前端时间升级到从用户点击经过跳转到页面可视的时间,增加了客户端路由、webview启动等时间,使体验的衡量更贴近用户真实的体感。覆盖了包括主会场、行业会场、外投会场等数十个场景。

预渲染

预渲染是在今年双11会场中使用的技术方案,用于提升用户打开会场的体验。将原有H5页面渲染流程中的WebView的初始化、页面资源加载、部分JS的执行等耗时的操作,提前执行,在离屏状态下完成页面“渲染”。当用户真正点击进入会场的时候,复用这个提前“渲染”的页面,大大节省打开会场的时间。用户打开会场的整体平均耗时缩短了200ms~700ms左右,秒开率提升10%-14%。优化对中低端机绝对收益更高,已实现在低端机上实现秒开会场。让用户逛会场体验更流畅了,尤其中低端手机效果更加明显。在后续的文章也会讲述包括预渲染、数据快照、并行请求等性能优化方面的实践与思考。

Android y67 对比视频.gif

图:中低端机型预渲染效果对比图

SSR

今年在不改变现有架构,不改变业务的前提下,在会场上使用了 ServerSideRendering 技术,将秒开率提高到了新的高度(82.6%);在用户体验得到优化的同时,业务指标如点击率等也有明显的增长,带来了不错的业务价值。后续的系列文章汇中会详细介绍前端在解决工程化、业务效果评估上的具体实践与方法论;服务端在解决前端模块代码于服务端执行、隔离和性能优化上的思考和方案。

循环.gif

图:中低端机型 SSR 效果对比图

基础链路

基础链路是电商核心的链路,包含首页、商品详情、微详情、交易(下单、订单、购物车、支付成功)、信息流、我的淘宝等基础业务。现有的技术方案是手淘内使用Native版本,追求极致的体验和稳定性;站外流量、包括支付宝在内的阿里系App使用H5版本,追求灵活性和可用性。随着支付宝容器化体系的完善,在其他App中的内聚,基础链路新的容器化版本具备了孵化的土壤;同时H5的一些弊端,比如资源都在远端、Native能力使用限制等也可以得到优化。

借助之前的“新奥创”和“DinamicX”方案(主要解决业务定制以及安卓、iOS、H5的三端一致,实现一处开发、三端生效),容器化版本得以快速扩展,实现四端一致。性能数据上,加载时间对比H5版本有2s的提升,基本达成秒开的目标;业务数据上,容器化版本对比H5版本UV转化率提升70+%。

目前已覆盖支付宝、特价版、优酷、高德、淘小铺、一淘等App,以及通过百川SDK集成在众多外部媒体App。业务上也接入了每日必抢、大牌直降、淘宝特价、淘宝直播、百川媒体、优酷、小铺、轻店、花呗等业务。

唤端技术

随着流量见顶、电商大战进一步升级,如何做好用户增长是各大公司必须完成的命题。用户增长涉及的面非常广泛,今年淘系前端聚焦在唤端技术,即外部流量拉起手淘App的技术体系。唤端技术的门槛很低,简单到只需要拼一个类似 URL 的 scheme 就可以触发唤端。唤端技术又很复杂,不同的渠道、不同的OS、不同的 App 都有可能针对唤端协议有限制,并有各种各样的兼容性问题;唤端链路中不同业务可能都有自己的业务定制需求,例如参数的透传;唤端链路的效率更是被关注的核心点,不同场景不同业务在效率上可能都不一样,因此还需要对唤端效果进行监测和对比。为了解决这些复杂的问题,我们在唤端技术上进行了又一次升级,建设了可定制的唤端策略,打造了详细的唤端AB测试链路。从本次双11 的效果看,不同场景下的唤端效率(唤端成功率)相对提升了 25~40%不等。

image.png

图:唤端策略图

智能UI

随着移动互联网和推荐系统的发展,人和商品的精准匹配为业务带来了效率的大幅提升。越来越多的精细化手段逐渐应用于个性化推荐领域,比如场景化推荐、人群定投技术等。同时商品的信息比以往任何时候都要丰富(买家秀,品牌背书,无忧购服务等),不同的用户对于内容的UI表达有着差异化的诉求,因此通过为不同人群找到合适的UI表达一定能带来业务效果的提升。

项目的最早期,我们通过AB实验直接定量测试,明确了相同的UI方案在不同的场景会产生差异,不同的UI方案在相同场景下也会产生差异。也就是说,针对不同场景使用不同方案是有意义的。2020年双十一大促我们第一次大规模采用智能UI产品化方案落地了多个前端模块,包括猜你喜欢模块、商品模块、店铺模块等,覆盖了双十一的预售和正式开卖阶段,承受了流量洪峰的考验,且带来了稳定的增长。覆盖300多个会场,最高的会场PV点击率相对提升10%+。

技术升级

伴随业界的技术演进和业务的发展,我们在技术上相比去年也有了新的尝试和迭代升级,其中典型的包括FaaS的深度使用、PHA渐进式的体验增强、边缘节点渲染的应用等。

FaaS

Serverless,一块深水的坚冰,逐步从深海付出了水面,阿里淘系从去年在大促实践开始,逐渐将 Serverless 应用到前端领域方方面面。今年双十一首先是在覆盖场景方面,FaaS从淘宝行业拓展到会场和营销业务,业务的复杂度得到极大的丰富。能力进一步提升,支撑的业务量级也从2k QPS提升到5W QPS,CPU水位从去年的高 QPS 规模时,精力花费降低约50%。在研发体验方面,打造解决方案体系,单元保障、大促管控、专家系统、函数盘点等能力,运维提效约50%。在研发体验方面,打造解决方案体系,降低研发门槛,支持外包快速入场。

PHA

PHA 全称 Progressive Hybrid App,是提升 Hybrid 体验的一种应用框架。提升页面加载速度和交互体验的渐进式 Web 应用,使用 PHA 开发的应用本质上没有脱离前端开发和 W3C 标准,但依然拥有原生应用的特性和体验。或许你有想到 PWA,但 PHA 有比 PWA 更强的 UI 能力和更快的加载速度。目前已经在手淘、特价版、Lazada、CBU 等多个客户端落地,支持了618、双11等多个大促。PHA联合客户端、前端团队、数据分析团队,跨栈协同,在性能优化方向上也做了很多优化工作,梳理全链路性能埋点、定义新的性能口径(从用户点击到可视),使用了预加载、预渲染、资源加速下载、离线资源等优化手段。

ESR

现在的渲染节点主要是在终端或是服务端,对应CSR(Client Sider Rendering)和SSR(Server Side Rendering),分别有适用的场景以及优势和弊端。现在借助阿里云的能力可将渲染转移到CDN节点,也就是我们要介绍的ESR(Edge Side Rendering),即能为前端提供渲染能力,同时也能将大量CDN机器上的计算资源利用起来。

阿里云推出了CDN轻量编程环境——EdgeRoutine,这为我们提供了一个新的尝试方向。我们可以在CDN节点去做提前渲染的事情。CDN的访问策略是会去寻找离用户最近的节点,就像快递运输的最后一公里一样,总会派送到离客户最近的分拨点。这么看来页面的网络调度时长是非常有优化空间的。并且我们还可以利用CDN节点资源共享的特性,将部分数据缓存到CDN节点上,减少远程的数据请求。

这套方案对于数据刷新率不高、访问量极大的页面,ESR搭配CDN的缓存能力是非常适合用的。以达人页为例,首屏时间约能提升50%左右。现在ER的技术才刚刚起步,应用场景比较局限,能力上还有很多不足,体系也需要不断地建设,但这个新技术为前端提供了更多可能,需要我们不停的去探索和完善。

双十一PM初体验

双十一作为电商年度最核心的节日,各方面投入的力度和资源都是最大的。作为参加过8次双11的老兵,作为前端PM是第一次,有很多不一样的感受。

复杂:首先是业务上,有双十一定制和特有的主会场、主互动、猫晚等,还有淘系内部本身就有导购、行业、营销、直播等数十个业务,同时联动支付宝、优酷、本地生活、阿里妈妈、菜鸟等多个集团BU,与商家、ISV、物流、媒体等的协同和合作。技术上同样复杂,前端的页面从开发、搭建、源站、CDN的全部链路,以及Node FaaS的容器、中间件、容量准备、流量调配、机房部署等。管中窥豹,对于整个体系的认知还需要更进一步的探索。

流程:双十一作为电商业务每年的大考,已经摸索出一套成熟的流程机制。包括人员的组成、沟通机制、时间排期、组织保障等各个方面都有很细致的机制进行保障。

协同:双十一是非常好的节点,可以让各团队、各岗位、各BU之间形成联动,集中力量将如此庞大的体系进一步完善。很多技术的升级和突破都是在双十一落地并进一步推广的。这次预渲染的方案就是客户端和前端紧密协同,在很短的时间内实现并验证的。

多维:看问题的视角可以更多维,不同技术岗位视角,全链路视角,业务的视角。以一次变更的审批为例,之前更多关注变更的代码实现上,对上下游的影响、对稳定性的影响、对业务的影响、是否引入新的风险、影响的范围等等都需要进行综合衡量,做一个判断往往需要从中进行取舍,而不单单是技术上的1和0。

招兵买马

最后的最后,招聘贴!

image.png

淘系前端由淘宝前端、天猫前端、手淘前端三大前端团队融合而成,在业务上负责淘宝、天猫的所有业务,如:双11&双12大促、聚划算、天猫新品、有好货等营销导购产品、淘宝直播&短视频业务、商业千牛以及开发、用户增长、互动&游戏等等,囊括了新零售域下最复杂、最多形态的业务场景;在技术上在前端工程、多端架构、Node架构、互动架构等基础体系上有着深厚的沉淀,同时在多媒体、前端智能化、云手机等新兴体系上布局&发展,在搭建&投放、小程序开放、工作台等应用体系上直接助力业务。

网址:https://fed.taobao.org/

邮箱:taobao-fed-zhaopin@list.alibaba-inc.com

职位:前端开发专家-杭州/北京端架构 TL前端技术专家(IDE方向)前端技术专家(Node.JS)互动技术专家Web多媒体领域专家-杭州/广州云手机解决方案架构师中后台领域架构师用户增长领域专家投放技术高级专家软硬件技术专家开发者平台产品经理

查看原文

赞 8 收藏 3 评论 2

阿里巴巴淘系技术 发布了文章 · 10月28日

AI for everyone,阿里淘系MNN工作台正式公测!

阿里巴巴淘系技术开源轻量级深度学习推理引擎 MNN 以来,得到了业界的普遍认可 —— 数十家企业成为 MNN 的用户,不乏有一线科技企业;此外,MNN 还与上海交大等一线院校展开合作,深度连接产学研。

除 MNN 引擎建设外,MNN 团队还深度参与了阿里内部的端AI应用实践。AI 应用门槛高、算法模型部署链路长是长期困扰我们的问题。为了解决这两个问题,我们将上百次实践中长期积累的方案沉淀为一站式 AI 研发范式 —— MNN 工作台

☞  文末可点击进入官网下载体验!

今天正式推出 MNN 工作台,这将极大降低AI应用门槛、将AI研发的效率提升数十倍,让“技术小白”也能快速上手,轻松设计自己的AI应用。

image.png

要打通AI应用的“任督二脉”,需要“十八般武艺” —— 你需要同时熟悉AI和业务,要搜得到数据、啃得了论文、改得动模型,末了还得会移动开发,打通业务流程。道阻且长,任一环节出了问题,都可能断送AI应用探索之路。

市面上其实不乏有一些云端模型训练平台,但大多只在流程中的数据和模型上下功夫。相较之下,MNN 工作台是第一个同时应对 AI 应用启蒙、无门槛训练和一键多端部署的一站式 AI 平台。

AI 应用启蒙最好的办法是参考行业的最佳实践,并且动手玩一玩。

MNN 工作台中,提供了人像分割、文字识别等主流应用的实例,无需训练就可以直接使用。通过 MNN 工作台,可以方便地在电脑和手机上体验AI的效果。AI 的视觉效果会直接叠加在相机视频流上,改变相机机位,就可以看到效果的变化。同时,还可以通过开关、滑块等来调节算法参数,同样可以实时观察到调整的影响。随手改、随心玩的即时体验,可以帮忙用户理解算法,打开想象的空间,更好地寻找AI和业务的结合。

在帮助用户无门槛训练自己的AI算法模型方面,MNN 工作台也下足了功夫。

MNN 工作台支持图像分类、文本分类等模型的训练,而且,所有的操作都可以通过图形化界面来完成。用户不需要了解模型训练的细节,只需要按照提示,提供训练所需的数据,就可以完成模型的定制。同时,MNN 工作台使用了迁移学习技术,用户仅仅需要少量的训练数据,就可以训练出效果上佳的专属模型。MNN 工作台还提供了自动化标注工具和手工标注工具,来进一步简化训练数据的准备工作。最后,在模型训练完成时,MNN 工作台还会提供模型测试报告,涵盖模型的大小、性能、精度信息,辅助决策。

应用多端部署方面,MNN 工作台为电脑和手机都提供了强大的 Python 运行环境 —— 三端一致的开发体验。

但更友好的,还是 MNN 工作台上所有的模型,都可以在电脑和手机上直接体验。是的,无需任何一行代码,试玩模型或训练模型都有对应的、已经编写好的代码!如果你需要修改算法实现,我们也提供了 Numpy、OpenCV 等常用库,尽可能降低图片、数据处理的成本。同时,在工作台上,扫码真机调试,断点、console 一应俱全,更有多端文件实时同步这样的黑科技等待你的解锁。

下面是 MNN 官网,欢迎安装下载~有疑问可联系我们

http://www.mnn.zone/

————————————————————————————————

阿里巴巴集团淘系技术部官方账号。淘系技术部是阿里巴巴新零售技术的王牌军,支撑淘宝、天猫核心电商以及淘宝直播、闲鱼、躺平、阿里汽车、阿里房产等创新业务,服务9亿用户,赋能各行业1000万商家。我们打造了全球领先的线上新零售技术平台,并作为核心技术团队保障了11次双十一购物狂欢节的成功。我们的愿景是致力于成为全球最懂商业的技术创新团队,让科技引领面向未来的商业创新和进步。

查看原文

赞 0 收藏 0 评论 0

阿里巴巴淘系技术 发布了文章 · 9月14日

聊聊鸿蒙系统与开发者生态前景

来自于阿里淘系的安卓开发同学之羲,站在开发者角度,给大家聊聊华为鸿蒙系统2.0版本后对鸿蒙生态、消费者端厂商、芯片厂商以及二三方应用开发&应用市场带来的影响。

本篇回答仅为开发者个人角度观点,欢迎大家一起讨论交流。

从1.0到2.0?

近日,中美关系的不确定性再次加大,国家层面提倡科技创新,强调把原始创新能力提升摆在更加突出的位置,努力实现更多”从0到1”的突破。在这样科技强国的大背景下,华为作为中国科技的领跑者之一,华为开发者大会9月10日在松山湖召开,再次提到举世曙目的鸿蒙操作系统,并发布了鸿蒙2.0以及最近的发展路线图。

从去年鸿蒙系统发布之始,鸿蒙系统就备受争议,其相关话题在知乎,贴吧等社区也火了一把。而最近发布的2.0,再次激发了行业内的关注。实际上,在鸿蒙开源官网,当前开源的版本仍然是标记为OpenHarmony 1.0 baseline的TAG。2.0的源码是否在路上,我们不得而知。

image.png

不可否认,去年的开源,那是千呼万唤始出来,犹抱琵琶半遮面,今年的相关文档与源码比去年完善了许多,似乎是一个可玩的版本了,可以烧在开发版上运行。 但相比Android/iOS等成熟的开发者工具链,略显简陋。确实是刚启步,我们也不能要求华为一出来就是成熟的产品。今天,笔者将从开发者生态的角度来聊聊鸿蒙系统。

鸿蒙生态的层次化

作为开发者,最近切的希望是了解未来能支持哪些设备,从鸿蒙2.0的路线图看,现在主要还是智慧屏,车机,手表等专有领域上,并没有类似手机这样的应用市场,自由上架的完整意义上的开发者生态。而据说今年年底会有可运行在手机上的beta版本(一定不要忘了beta这个词),我们再试目以待。

其实蛮喜欢华为的一句话,"没有人能够熄灭满天星光,每一位开发者,都是华为要汇聚的星星之火。"愿望很美好。华为开源的初衷,应该是为了让更多的友商,包括设备商,oem商,芯片厂商,iot商,应用开发商等一起进来合作,所以,明显华为对生态的设计上,是进行了分层的,在不同的成熟期,主要推动相应的生态合作伙伴。

消费者端厂商

分析一下,不难得出一个结论,开源的版本和商用的版本,应该是两个不同的分支,商用的分支,应该会完善很多,如果按华为上线的智慧屏是采用鸿蒙系统来看,它们之间,猜测还是有个代差,而且未来会一直保持这个代差。当然我们也不期望华为一下子把投入多年的软件资产开放出来。 因此,在当前的状态下,并不能奢望其他的消费者端的厂商开发出基于鸿蒙系统的电子产品,他们一定是等着这个系统成熟或者某个外因(众所周知的如华为中兴)而不得不用。这一层的厂商,应该是在观望中。

芯片厂商

而对于芯片厂商,如果华为鸿蒙系统有电子产品面世,必然会有一些与华为合作的厂商参与进来,目前来说,我更愿意相信,如果有,还是主要存在于华为内部。而方案集成厂商的合作,想必会更加遥远,需要基于鸿蒙的前景更加明确后,才会有厂商进来解决更大规模化的问题。

二三方应用开发&应用市场

华为当前主要推动生态参加与者,我相信更多是有合作的二方以及少量的三方应用开发商。主要以解决某些特定场景的应用为主。从目前华为提供的开发资料看,目前支持Java和JS,未来可能有更多的语言。

image.png

鸿蒙的应用,以.hap结尾,类似于android的.apk。从目前的资料看,hap的编写很类似android的开发,无论是ide或是api,都有一定的相似性。对android开发者的学习成本看起来不高。

image.png

而另一种方式,则是以小程序为代表的前端技术栈开发方式。

image.png

像阿里淘宝这样的三方开发者,要融入鸿蒙这样的生态,相信华为还有很长的一段路要走,目前还没有看到类似应用市场的发布渠道。笔者认为,目前鸿蒙上的应用开发方式,虽然类android,类小程序,好像即照顾了Android开发者,又照顾前端开发者,但终归不是兼容的。如果不能兼容android系统的runtime环境,与现有的android生态作衔接,鸿蒙的路将会非常艰难。

写在最后

尽管与国外多个优秀的操作系统相比,仍存在一定差距,不管怎样,鸿蒙作为能够运行在电子设备上可商业化的国产操作系统,的确是意义非凡。不必妄自菲薄,客观的看待它,了解它。期望鸿蒙操作系统能如同像它的名字一样,为中国科技的腾飞,开创一片天空,在科技世界的舞台上有它一席之地。

——————————————————————————————————————————

本账号主体为阿里巴巴淘系技术,淘系技术部隶属于阿里巴巴新零售技术事业群,旗下包含淘宝技术、天猫技术、农村淘宝技术、闲鱼、躺平等团队和业务,是一支是具有商业和技术双重基因的螺旋体。

欢迎收藏点赞关注我们!共同进步~ :)更多技术干货可关注【淘系技术】公众号

查看原文

赞 3 收藏 0 评论 1

阿里巴巴淘系技术 发布了文章 · 8月12日

面向5G的阿里自研标准化协议库XQUIC

XQUIC是阿里巴巴淘系架构团队自研的IETF QUIC标准化协议库实现,在手机淘宝上进行了广泛的应用,并在多个不同类型的业务场景下取得明显的效果提升,为手机淘宝APP的用户带来丝般顺滑的网络体验:

  • 在RPC请求场景,网络耗时降低15%
  • 在直播高峰期场景,卡顿率降低30%、秒开率提升2%
  • 在短视频场景,卡顿率降低20%

从以上提升效果可以看出,对QUIC的一个常见认知谬误:“QUIC只对弱网场景有优化提升”是不准确的。实际上QUIC对于整体网络体验有普遍提升,弱网场景由于基线较低、提升空间更显著。此外,在5G推广初期,基站部署不够密集的情况下,如何保证稳定有效带宽速率,是未来2-3年内手机视频应用将面临的重大挑战,而我们研发的MPQUIC将为这些挑战提供有效的解决方案。

本文将会重点介绍XQUIC的设计原理,面向业务场景的网络传输优化,以及面向5G的Multipath QUIC技术(多路径QUIC)。

QUIC

网络分层模型及QUIC进化史

图1. 网络七层/四层模型 和 QUIC分层设计

为了方便说明QUIC在网络通信协议栈中所处的位置及职能,我们简单回顾一下网络OSI模型(七层模型)和TCP/IP模型(四层模型)。从两套网络模型中可以看出,网络传输行为和策略主要由传输层来控制,而TCP作为过去30年最为流行和广泛使用的传输层协议,是由操作系统控制和实现的。

QUIC是由Google从2013年开始研究的基于UDP的可靠传输协议,它最早的原型是SPDY + QUIC-Crypto + Reliable UDP,后来经历了SPDY[1]转型为2015年5月IETF正式发布的HTTP/2.0[2],以及2016年TLS/1.3[3]的正式发布。QUIC在IETF的标准化工作组自2016年成立,考虑到HTTP/2.0和TLS/1.3的发布,它的核心协议族逐步进化为现在的HTTP/3.0 + TLS/1.3 + QUIC-Transport的组合。

QUIC带来的核心收益是什么

众所周知,QUIC具备多路复用/0-RTT握手/连接迁移等多种优点,然而在这些优势中,最关键的核心收益,当属QUIC将四/七层网络模型中控制传输行为的传输层,从内核态实现迁移到了用户态实现,由应用软件控制。这将带来2个巨大的优势:

(1) 迭代优化效率大大提升。以服务端角度而言,大型在线系统的内核升级成本往往是非常高的,考虑到稳定性等因素,升级周期从月到年为单位不等。以客户端角度而言,手机操作系统版本升级同样由厂商控制,升级周期同样难以把控。调整为用户态实现后,端到端的升级都非常方便,版本迭代周期以周为计(甚至更快)。

(2) 灵活适应不同业务场景的网络需求。在过去4G的飞速发展中,短视频、直播等新的业务场景随着基建提供的下行带宽增长开始出现,在流媒体传输对于稳定高带宽和低延迟的诉求下,TCP纷纷被各类标准/私有UDP解决方案逐步替代,难以争得一席之地。背后的原因是,实现在内核态的TCP,难以用一套拥塞控制算法/参数适应快速发展的各类业务场景。这一缺陷将在5G下变得更加显著。QUIC则可将拥塞控制算法/参数调控到连接的粒度,针对同一个APP内的不同业务场景(例如RPC/短视频/直播等)具备灵活适配/升级的能力。

在众多增强型UDP的选择中,QUIC相较于其他的方案最为通用,不仅具备对于HTTP系列的良好兼容性,同时其优秀的的分层设计,也使得它可以将传输层单独剥离作为TCP的替代方案,为其他应用层协议提供可靠/非可靠传输能力(是的,QUIC也有非可靠传输草案设计)。

XQUIC是什么、为什么选择自研 + 标准


XQUIC是阿里自研的IETF QUIC标准化实现,这个项目由淘系架构网关与基础网络团队发起和主导,当前有阿里云CDN、达摩院XG实验室与AIS网络研究团队等多个团队参与其中。

现今QUIC有多家开源实现,为什么选择标准协议 + 自研实现的道路?我们从14年开始关注Google在QUIC上的实践(手机淘宝在16年全面应用HTTP/2),从17年底开始跟进并尝试在电商场景落地GQUIC[4],在18年底在手淘图片、短视频等场景落地GQUIC并拿到了一定的网络体验收益。然而在使用开源方案的过程中或多或少碰到了一些问题,Google的实现是所有开源实现中最为成熟优秀的,然而由于Chromium复杂的运行环境和C++实现的缘故,GQUIC包大小在优化后仍然有2.4M左右,这使得我们在集成手淘时面临困难。在不影响互通性的前提下,我们进行了大量裁剪才勉强能够达到手淘集成的包大小要求,然而在版本升级的情况下难以持续迭代。其他的开源实现也有类似或其他的问题(例如依赖过多、无服务端实现、无稳定性保障等)。最终促使我们走上自研实现的道路。

为什么要选择IETF QUIC[5]标准化草案的协议版本?过去我们也尝试过自研私有协议,在端到端都由内部控制的场景下,私有协议的确是很方便的,但私有协议方案很难走出去建立一个生态圈 / 或者与其他的应用生态圈结合(遵循相同的标准化协议实现互联互通);从阿里作为云厂商的角度,私有协议也很难与外部客户打通;同时由于IETF开放讨论的工作模式,协议在安全性、扩展性上会有更全面充分的考量。

因此我们选择IETF QUIC标准化草案版本来落地。截止目前,IETF工作组草案已经演化到draft-29版本(2020.6.10发布),XQUIC已经支持该版本,并能够与其他开源实现基于draft-29互通。

XQUIC整体架构和传输框架设计

XQUIC是IETF QUIC草案版本的一个C协议库实现,端到端的整体链路架构设计如下图所示。XQUIC内部包含了QUIC-Transport(传输层)、QUIC-TLS(加密层、与TLS/1.3对接)和HTTP/3.0(应用层)的实现。在外部依赖方面,TLS/1.3依赖了开源boringssl或openssl实现(两者XQUIC都做了支持、可用编译选项控制),除此之外无其他外部依赖。

图2. XQUIC端到端架构设计 和 内部分层模块

XQUIC整体包大小在900KB左右(包含boringssl的情况下),对于客户端集成是较为轻量的(支持Android/iOS)。服务端方面,由于阿里内部网关体系广泛使用Tengine(Nginx开源分支),我们开发了一个ngx_xquic_module用于适配Tengine服务端。协议的调度方面,由客户端网络库与调度服务AMDC配合完成,可以根据版本/地域/运营商/设备百分比进行协议调度。

XQUIC传输层内部流程设计如下图,可以看到XQUIC内部的读写事件主流程。考虑到跨平台兼容性,UDP收发接口由外部实现并注册回调接口。XQUIC内部维护了每条连接的状态机、Stream状态机,在Stream级别实现可靠传输(这也是根本上解决TCP头部阻塞的关键),并通过读事件通知的方式将数据投递给应用层。传输层Stream与应用层HTTP/3的Request Stream有一一映射关系,通过这样的方式解决HTTP/2 over TCP的头部阻塞问题。

图3. XQUIC读写事件主流程设计

考虑到IETF QUIC传输层的设计可以独立剥离,并作为TCP的替代方案对接其他应用层协议,XQUIC内部实现同样基于这样的分层方式,并对外提供两套原生接口:HTTP/3请求应答接口 和 传输层独立接口(类似TCP),使得例如RTMP、上传协议等可以较为轻松地接入。

图4. XQUIC内部的连接状态机设计(参考TCP)

XQUIC拥塞控制算法模块

我们将XQUIC传输层的内部设计放大,其中拥塞控制算法模块,是决定传输行为和效率的核心模块之一。

图5. XQUIC拥塞控制算法模块设计

为了能够方便地实现多套拥塞控制算法,我们将拥塞控制算法流程抽象成7个回调接口,其中最核心的两个接口onAck和onLost用于让算法实现收到报文ack和检测到丢包时的处理逻辑。XQUIC内部实现了多套拥塞控制算法,包括最常见的Cubic、New Reno,以及音视频场景下比较流行的BBR v1和v2,每种算法都只需要实现这7个回调接口即可实现完整算法逻辑。

为了方便用数据驱动网络体验优化,我们将连接的丢包率、RTT、带宽等信息通过埋点数据采样和分析的方式,结合每个版本的算法调整进行效果分析。同时在实验环境下模拟真实用户的网络环境分布,更好地预先评估算法调整对于网络体验的改进效果。

面向业务场景的传输优化

XQUIC在RPC请求场景降低网络耗时15%,在短视频场景下降低20%卡顿率,在直播场景高峰期降低30%卡顿率、提升2%秒开率(相对于TCP)。以下基于当下非常火热的直播场景,介绍XQUIC如何面向业务场景优化网络体验。

优化背景

部分用户网络环境比较差,存在直播拉流打开慢、卡顿问题。

图6. 某节点丢包率和RTT统计分布

这是CDN某节点上统计的丢包率和RTT分布数据,可以看到,有5%的连接丢包率超过20%,0.5%的连接RTT超过500ms,如何优化网络较差用户的流媒体观看体验成为关键。

秒开卡顿模型

图7. 直播拉流模型

直播拉流可以理解为一个注水模型,上面是CDN服务器,中间是播放器缓冲区,可以理解成一个管道,下面是用户的体感,用户点击播放时,CDN不断向管道里注水,当水量达到播放器初始buffer时,首帧画面出现,然后播放器以一定速率排水,当水被排完时,播放器画面出现停顿,当重新蓄满支持播放的水后,继续播放。

我们假设Initial Buffer(首帧)为100K(实际调整以真实情况为准),起播时间 T1 < 1s 记为秒开,停顿时间 T2 > 100ms 记为卡顿。

  • 优化目标
  • 提升秒开:1s内下载完100K
  • 降低卡顿:保持下载速率稳定,从而保持管道内始终有水
  • 核心思路
  • 提升秒开核心--快
  • 高丢包率用户:加快重传
  • 高延迟用户:减少往返次数
  • 降低卡顿核心--稳
  • 优化拥塞算法机制,稳定高效地利用带宽

拥塞算法选型

常见的拥塞算法可分为三类:

  • 基于路径时延(如Vegas、Westwood)

将路径时延上升作为发生拥塞的信号,在单一的网络环境下(所有连接都使用基于路径时延的拥塞算法)是可行的,但是在复杂的网络环境下,带宽容易被其他算法抢占,带宽利用率最低。

  • 基于丢包(如Cubic、NewReno)

将丢包作为发生拥塞的信号,其背后的逻辑是路由器、交换机的缓存都是有限的,拥塞会导致缓存用尽,进而队列中的一些报文会被丢弃。

拥塞会导致丢包,但是丢包却不一定拥塞导致的。事实上,丢包可以分为两类,一类是拥塞丢包,另一类是噪声丢包,特别是在无线网络环境中,数据以无线电的方式进行传递,无线路由器信号干扰、蜂窝信号不稳定等都会导致信号失真,最终数据链路层CRC校验失败将报文丢弃。

基于丢包的拥塞算法容易被噪声丢包干扰,在高丢包率高延迟的环境中带宽利用率较低。

  • 基于带宽时延探测(如BBR)

既然无法区分拥塞丢包和噪声丢包,那么就不以丢包作为拥塞信号,而是通过探测最大带宽和最小路径时延来确定路径的容量。抗丢包能力强,带宽利用率高。

三种类型的拥塞算法没有谁好谁坏,都是顺应当时的网络环境的产物,随着路由器、交换机缓存越来越大,无线网络的比例越来越高,基于路径时延和基于丢包的的拥塞算法就显得不合时宜了。对于流媒体、文件上传等对带宽需求比较大的场景,BBR成为更优的选择。

秒开率优化

✎ 加快握手包重传

图8. TCP握手阶段出现丢包

如图,TCP在握手时,由于尚未收到对端的ACK,无法计算路径RTT,因此,RFC定义了初始重传超时,当超过这个超时时间还未收到对端ACK,就重发sync报文。

TCP秒开率上限:Linux内核中的初始重传超时为1s (RFC6298, June 2011),3%的丢包率意味着TCP秒开率理论上限为97%,调低初始重传时间可以有效提升秒开率。

同理,如果你有一个RPC接口超时时间为1s,那么在3%丢包率的环境下,接口成功率不会超过97%。

图9. TCP和QUIC握手阶段 - 伪重传模拟

另一方面,调低初始重传超时会引发伪重传,需要根据用户RTT分布进行取舍,比如初始重传超时调低到500ms,那么RTT大于500ms的用户在握手期间将会多发一个sync报文。

减少往返次数

慢启动阶段 N 个 RTT 内的吞吐量(不考虑丢包):

T = init_cwnd * (2^N-1) * MSS,  N = ⌊t / RTT ⌋

Linux内核初始拥塞窗口=10(RFC 6928,April 2013)

首帧100KB,需要4个RTT,如果RTT>250ms,意味着必然无法秒开。在我们举的这个例子中,如果调整为32,那么只需要2个RTT。

图10. 宽带速率报告

从2015到2019,固定带宽翻了4.8倍。从2016到2019,移动宽带翻了5.3倍。初始拥塞窗口从10调整为32在合理范围内。

卡顿率优化

✎ BBR RTT探测优化

图11. BBR v1示意图:ProbeRTT阶段

问题

  • BBR v1的ProbeRTT阶段会把inflight降到4*packet并保持至少200ms。会导致传输速率断崖式下跌,引起卡顿
  • 10s进入一次ProbeRTT,无法适应RTT频繁变化的场景

优化方案

  • 减少带宽突降:inflight 降到 4*packet  改为降到 0.75 * Estimated_BDP
  • 加快探测频率:ProbeRTT进入频率 10s 改为 2.5s

推导过程

  • 为什么是 0.75x?

Max Estimated_BDP = 1.25*realBDP

0.75 * Estimated_BDP = 0.75 * 1.25 * realBDP = 0.9375* realBDP

保证inflight < realBDP, 确保RTT准确性。

  • 为什么是 2.5s?

优化后BBR带宽利用率:(0.2s * 75% + 2.5s * 100%) / (0.2s+ 2.5s) = 98.1%

原生BBR带宽利用率:(0.2s * 0% + 10s * 100%) / (0.2s + 10s) = 98.0%

在整体带宽利用率不降低的情况下,调整到2.5s能达到更快感知网络变化的效果。

优化效果

保证带宽利用率不低于原生BBR的前提下,使得发送更平滑,更快探测到RTT的变化。

✎ BBR带宽探测优化**

图12. BBR v1示意图:StartUp 和 ProbeBW阶段

问题分析

StartUp阶段2.89和ProbeBW阶段1.25的增益系数导致拥塞丢包,引发卡顿和重传率升高(Cubic重传率3%, BBR重传率4%)重传导致带宽成本增加1%。

优化策略

图13. 带宽变化示意图

定义两个参数:

期望带宽:满足业务需要的最小带宽

最大期望带宽:能跑到的最大带宽

未达到期望带宽时采用较大的增益系数,较激进探测带宽。

达到期望带宽后采用较小的增益系数,较保守探测带宽。

优化效果

成本角度:重传率由4%降到3%,与Cubic一致,在不增加成本的前提下降低卡顿率。

另外,该策略可以推广到限速场景,如5G视频下载限速,避免浪费过多用户流量。

卡顿、秒开优化效果

在直播拉流场景下与TCP相比较,高峰期卡顿率降低30%+,秒开率提升2%。

写在优化最后的思考

最后,我们看看TCP初始重传超时和初始拥塞窗口的发展历程:

  • 初始重传时间
  • RFC1122 (October 1989) 为3s
  • RFC6298 (June 2011) 改为1s,理由为97.5%的连接RTT<1s
  • 初始拥塞窗口
  • RFC 3390 (October 2002) 为 min(4 * MSS, max(2 * MSS, 4380 bytes))(MSS=1460时为3)
  • RFC 6928 (April 2013) 改为 min (10 * MSS, max (2 * MSS, 14600))(MSS=1460时为10)—— 由google提出,理由为 90% of Google's search responses can fit in 10 segments (15KB).

首先IETF RFC是国际标准,需要考虑各个国家的网络情况,总会有一些网络较慢的地区。在TCP的RFC标准中,由于内核态实现不得不面临一刀切的参数选取方案,需要在考虑大盘分布的情况下兼顾长尾地区。

对比来看,QUIC作为用户态协议栈,其灵活性相比内核态实现的TCP有很大优势。未来我们甚至有机会为每个用户训练出所在网络环境最合适的一套最优算法和参数,也许可以称之为千人千面的网络体验优化:)

Multipath QUIC技术

Multipath QUIC(多路径QUIC)是当前XQUIC内部正在研究和尝试落地的一项新技术。

MPQUIC可以同时利用cellular和wifi双通道进行数据传输,不仅提升了数据的下载和上传速度,同时也加强了应用对抗弱网的能力,从而进一步提高用户的端到端体验。此外,由于5G比4G的无线信号频率更高,5G的信道衰落问题也会更严重。所以在5G部署初期,基站不够密集的情况下如何保证良好信号覆盖是未来2-3年内手机视频应用的重大挑战,而我们研发的MPQUIC将为这些挑战提供有效的解决方案。

Multipath QUIC 的前身是MPTCP[6]。MPTCP在IETF有相对成熟的一整套RFC标准,但同样由于其实现在内核态,导致落地成本高,规模化推广相对困难。业界也有对MPTCP的应用先例,例如苹果在iOS内核态实现了MPTCP,并将其应用在Siri、Apple Push Notification Service和Apple Music中,用来保障消息的送达率、降低音乐播放的卡顿次数和卡顿时间。

我们在18年曾与手机厂商合作(MPTCP同样需要厂商支持),并尝试搭建demo服务器验证端到端的优化效果,实验环境下测试对「收藏夹商品展示耗时」与「直播间首帧播放耗时」降低12-50%不等,然而最终由于落地成本太高并未规模化使用。由于XQUIC的用户态协议栈能够大大降低规模化落地的成本,现在我们重新尝试在QUIC的传输层实现多路径技术。

图15. Multipath QUIC协议栈模型

Multipath QUIC对于移动端用户最核心的提升在于,通过在协议栈层面实现多通道技术,能够在移动端同时复用Wi-Fi和蜂窝移动网络,来达到突破单条物理链路带宽上限的效果;在单边网络信号强度弱的情况下,可以通过另一条通道补偿。适用的业务场景包括上传、短视频点播和直播,可以提升网络传输速率、降低文件传输耗时、提升视频的秒开和卡顿率。在3GPP Release 17标准中也有可能将MPQUIC引入作为5G标准的一部分[7]。

技术层面上,和MPTCP不同,我们自研的MPQUIC采取了全新的算法设计,这使得MPQUIC相比于MPTCP性能更加优化,解决了slow path blocking问题。在弱网中的性能比以往提升30%以上。

图16. 弱网下相对单路径的文件平均下载时间降低比例(实验数据)

图17. 弱网下相对单路径的视频播放卡顿率降低比例(实验数据)

在推进MPQUIC技术落地的过程中,我们将会尝试在IETF工作组推进我们的方案作为MPQUIC草案的部分内容[8]。期望能够为MPQUIC的RFC标准制定和落地贡献一份力量。

下一步的未来

我们论证了QUIC的核心优势在于用户态的传输层实现(面向业务场景具备灵活调优的能力),而非单一针对弱网的优化。在业务场景的扩展方面,除了RPC、短视频、直播等场景外,XQUIC还会对其他场景例如上传链路等进行优化。

在5G逐步开始普及的时代背景下,IETF QUIC工作组预计也将在2020年底左右将QUIC草案发布为RFC标准,我们推测在5G大背景下QUIC的重要性将会进一步凸显。

QUIC/MPQUIC对于5G

对于5G下eMBB(Enhanced Mobile Broadband)和URLLC(Ultra Reliable Low Latency)带来的不同高带宽/低延迟业务场景,QUIC将能够更好地发挥优势,贴合场景需求调整传输策略(拥塞控制算法、ACK/重传策略)。对于5G运营商提供的切片能力,QUIC同样可以针对不同的切片适配合适的算法组合,使得基础设施提供的传输能力能够尽量达到最大化利用的效果。在XQUIC的传输层实现设计中,同样预留了所需的适配能力。

在5G推广期间,在基站部署不够密集的情况下,保障稳定的有效带宽将会是音视频类的应用场景面临的巨大挑战。Multipath QUIC技术能够在用户态协议栈提供有效的解决方案,然而这项新技术仍然有很多难点需要攻克,同时3GPP标准化组织也在关注这一技术的发展情况。

XQUIC开源计划

阿里淘系技术架构团队计划在2020年底开源XQUIC,期望能够帮助加速IETF标准化QUIC的推广,并期待更多的开源社区开发者参与到这个项目中来。

附录:参考文献

[1] SPDY - HTTP/2.0原型,由Google主导的支持双工通信的应用层协议

[2] HTTP/2.0 - https://tools.ietf.org/html/r...

[3] TLS/1.3 - https://tools.ietf.org/html/r...

[4] GQUIC - 指Google QUIC版本,与IETF QUIC草案版本有一定差异

[5] IETF QUIC - 指IETF QUIC工作组正在推进的QUIC系列草案:https://datatracker.ietf.org/...,包括QUIC-Transport、QUIC-TLS、QUIC-recovery、HTTP/3.0、QPACK等一系列草案内容

[6] MPTCP - https://datatracker.ietf.org/...

[7] 3GPP向IETF提出的需求说明 https://tools.ietf.org/html/d...

[8] MPQUIC - 我们正在尝试推进的草案 https://datatracker.ietf.org/...

淘系架构与基础服务团队

致力于为淘系和阿里提供基础核心能力、产品与解决方案:

•  下一代网络协议QUIC的实现与落地 - XQUIC
•  自适应高可用解决方案与核心能力 - Noah
•  新一代业务研发模式平台 - Gaia
•  支撑整个阿里的移动中间件体系(千万级QPS接入网关、API网关、推送/消息、移动配置中心等)
团队大牛云集~~ 想要加入我们,请邮件简历至:miaoji.lym@alibaba-inc.com

本篇内容来自于阿里巴巴淘系技术部,高级技术专家喵吉。
更多精彩内容可关注【淘系技术】公众号。

查看原文

赞 0 收藏 0 评论 0

阿里巴巴淘系技术 发布了文章 · 8月11日

Swift 5.3的进化:语法、标准库、调试能力大幅提升

概括

Swift 从 5.0 的 ABI 稳定到5.1 的模块稳定,Swift 终于不是《Swift 入门到重学》了。本次 WWDC2020,Swift 5.3 正式发布,Swift 依旧朝着安全、高效、易读的方向持续发力,不断的在改进语法,增强代码的表达能力和易用性。因为 Swift 的模块稳定,SPM 现在也支持了二进制模块的分发,逐渐完善的社区生态也在不断拓宽 Swift 可以涉足的领域,而不仅仅是在 Apple 平台之上。

下图展示了 WWDC2020 中 Swift 相关内容的脑图,希望可以帮助大家快速了解。

image.png

( WWDC 2020精彩内容思否专栏:https://segmentfault.com/blog...  

本篇内容来自于阿里巴巴淘系技术部,无线开发工程师星志。
更多精彩内容可关注【淘系技术】公众号。)

语言环境的完善和拓展

一门完善编程语言有三个最基本的要素:语法、标准库、调试能力。语法设计决定了语言的编程范式;标准库决定了语言的基本能力;调试能力决定了开发者的体验和语言的稳定性。

苹果在 Swift 的迭代过程中不断的强化这几点,我们可以来看看 Swift 又得到了哪些提升。

语法特性

Swift 的语法设计核心还是 OOP,但是这不妨碍 Swift 的语法在支持 POP 和函数式编程甚至 DSL 得到的强化。Swift 也因为 SDL 特性的加入,开始逐渐的适应声明式编程的方向发展,比如后文提到的 @main 等等。

Multiple trailing closure

image.png

这个改进解决了当函数最后几个参数为闭包的情况下,导致的括号嵌套的问题,API 更加简洁也更加具有表达性。SwiftUI 利用这个语言特性,也变得更加简洁易懂。

KeyPath as Function

image

现在 KeyPath 可以当做函数来使用了。这个语法糖解决的问题当我们使用类似 map 一样的函数时,只需要取出对应数据模型中的某一个属性,为此我们不得不写类似 map { $0.property } 的代码,有了这个语法糖,事情就可以简化成了 map(\.property)

Type-based program entry point (@main)

引入了新的修饰符 @main,可以标记在带有 public static func main() 函数实现的所有类型,无论 main 函数时从拓展来得还是继承来的。添加这个特性的意义在与维持声明式的语义,将声明式语义进行到底。YES!


Increase availability of implicit self in closures

以前我们写逃逸闭包时如果捕获了 self,我们需要在跟 self 有关的地方写上 self. 以警示我们注意循环引用。

image.png

如果在闭包的捕获列表中显示声明捕获 self,在闭包中对 self 相关的访问可以省略。如果是在不可变的函数中访问,self 可以直接省略(为了 SwiftUI)。

image.png

其实这一点改进有用但是覆盖面并不是很广,因为在实际的应用中,我们都是尽量先弱引用 self 后再强引用 self,来保证 self 的可访问性。在如下场景就得不到此项优化:

image

Multi-pattern catch clauses

这种写法可以自动实现错误匹配,进入到对应的错误处理中,而不需要使用 switch,增强语言的可读性。

image.png

Enum enhancements

自动符合 Comparable

编译器现在可以自动为你生成 Comparable 的相关方法,实现 Enum 的比较。

image.png

Enum case 可以用来适配 protocol

这个特性看引用场景需要吧,官方给了一个比较好的例子。具体相关内容可以参考 SE-0280。

image.png

DSL 新增对 switch 的支持

现在可以在 SwiftUI 等 Swift DSL 中使用 switch-case 来进行模式匹配,之前只有对 if-else 的支持。某种程度上也是为 SwiftUI 而生的能力。

image.png

标准库

其实这里说标准库是广义的标准库,其中包括了开发者随语言分发的标准库,如标准 I/O 库等,运行时环境,编译环境,一方库等等。苹果今年在这部分下足了功夫,因为标准库、各种各样的一方三方库才是展现一门语言能力的地方,否则再好的语法也不会有人用,语言终究还是工具,能解决问题才是关键。

Swift 5.3 在代码尺寸和运行时都有不小的提升。Swift Package Manager(SPM)增加对二进制和资源的支持,深度集成 Xcode,亲儿子的优势逐渐显示了出来。Swift 本来设计的初衷本来就是一门 General Purpose 的语言,今年苹果正式宣布 Swift 支持了 Apple platform,Ubuntu/CentOS/Amazon Linux,不久的将来也会支持 Windows,正式成为一门优秀的跨平台语言。

标准库更新

  • Float16 的支持,具有更好的运算性能
  • Apple Archive 一种功能类似 zip 的压缩文件,苹果就是用这种格式来更新系统
  • Swift System 对操作系统基础 API 的包装,让 API 更健壮易用
  • OSLog 推荐使用的 logging system

从这些更新可以看出,苹果对 Swift 的底层操作非常关心,Swift System 的出现让使用 Swift 底层开发者脱离 OS C API 的折磨,获得更一致更健壮的代码体验。

新的一方库

Code Size and Runtime

在使用 UIKit 的情况下,Swift 4.1 时生成的二进制代码已经从 OC 的两倍还多,但是在 Swift 5.3 中,这个差距已经缩小到小于 1.5 倍了。也就是说之前大量使用 Swift app 会自动得到二进制大小的优化,而对于担忧 Swift 会造成包大小问题的 App,现在已经不算是很大的问题了。因为只需要付出可以接受的代价,就能获得 Swift 带来的安全性能和开发体验。

image.png

如果 App 使用了纯 SwiftUI,二进制代码甚至可以缩小 43% 之多。可见苹果优化 Swift 的功底之深,而且这些优化,只需要从新编译一次即可享受,何乐而不为。

image.png

因为 Swift 更紧凑的值类型,运行时的内存,分配相同的对象所需的空间自然比 OC 更小。Swift 5.3 相较 5.1,运行时的必要额外信息存储要少非常多,甚至做到了比 OC 还要少,大大减小了 Swift 的运行时内存。这对低内存的设备是非常有帮助的,同时,更少的系统内存意味着更多的用户内存。而这一切,只需要重新编译即可。

image.png

Swift 底层的不断优化也让其成为一门高效的语言,降低运行时的要求,就可以提升其应用的场景。

Swift Package Manager

SPM 作为 Swift 生态非常重要的一环,也迎来了更新。

  • SPM 支持二进制包分发
  • SPM 支持了资源的打包

这两点更新已经表明了 SPM 的能力已经足够完善了。目前具有一定规模 App 的内部模块都开始使用 Cocoapods 做二进制组件化的集成,这样可以明确对代码解耦,提高打包的效率。在这样的背景之下,SPM 对这两点关键特性的支持已经可以覆盖住大型 App 需求了,而且 SPM 不单单只跟 Swift 玩,C Family 它都可以支持。

在 SPM 与 Cocoapods 的对比中,亲儿子 SPM 跟 Xcode 深入整合,Xcode 可以直接打开编辑 swift package,Xcode 因为 SPM 设计了对应的操作界面,降低了开发和使用的门槛。成熟的工具链也让联调 Swift Package 轻而易举。而 Cocoapods 由社区维护,每一次 Xcode 更新其响应也不算很及时,在针对大型 App 时因为 Podfile 与 podspec 的分离导致了许多不一致,使用 ruby 还有一定的门槛。

现在也许是拥抱 SPM 的好时机。

跨平台

现在官方支持的操作系统列表如下:

  • Apple platform
  • Ubuntu 16.04, 18.04, 20.04
  • CentOS 8
  • Amazon Linux 2
  • Windows (coming soon)

真正做到的跨平台,并且 Swift 官方支持 AWS Lambda。AWS Lambda Runtime 已经开源,支持了 AWS 的 FaaS 编程,进一步的拓宽了 Swift 涉足的领域。

调试能力(开发者体验)

调试和开发者体验也是一门语言非常重要的一环,因为没有人会写出没有错误的代码,检查错误的能力和工具对一门语言来说十分重要。苹果也十分注重这一方面,在开发者体验上下足了功夫。

更加智能的诊断信息

刚开始使用 Swift 的开发者可能经常会对 Xcode 的报错信息不知所云,在引入 SwiftUI 后,这个问题尤为明显。笔者第一次编写 SwiftUI 时,只要 body 中某个地方出错,报出来的错误都是不正确的,只能通过肉眼检查和推断才能明白自己的错误,十分痛苦。

现在苹果重制了诊断能力,现在 Swift 的错误诊断比之前准确了许多,错误没有乱报并且错误提示也变得很好理解,特别是 SwiftUI,很容易知道错在哪了。在 Swift 中,编译通过就是对正确性的一个很好的证明,除非你用不安全的方式让编译器闭嘴。

自动补全

经过强化的类型推断系统,也增强了 Swift 的代码补全能力。这个估计升级到 Xcode 12 就可以顺利体验了。同时代码缩进能力也得到了加强。

LLDB

image.png

积极拥抱 Swift

看了这么多年 WWDC,每次看时大家应该都有一种心态

只支持最新版本,我们才支持 iOS X (低版本),这些东西跟我没关系

感觉 Swift 真香,但是现实只让我使用 OC(叹口气)

什么语言不是用,OC 这么多年肯定够用了

危机

然而如果不及时做出改变,保持能用就行,在前进的路上,背上的担子就会越来越重。当发现快走不动时,又回过头来看 WWDC,就会发现,原来解决方案很久以前就已经给出来了,只是当时不觉得是个问题,这不支持那不合适,但是现在想拿出来使用的时候,面对背上那一团团的乱码,却又束手无策。

做出改变是痛苦的,但是当以前觉得痒就挠挠就解决了的事情,逐渐变成现在的痛点时,要做出改变也许会更痛苦。

Swift 的出现就是为了替代并且超越 Objective-C 的语言,虽然说苹果因为历史原因还在使用 OC,但是种种迹象表明,苹果正在做积极的工作,逐渐通过 Swift 降低 OC 在整个系统的比重。

社区也在积极的转变,许多著名的第三方库都已经迁移至 Swift,OC 版本已经不再维护,例如 Lottie 已经在 Swift 版本上出现了 OC 版本不存在的特性,并且 OC 版本不再维护。这种现象慢慢会越来越多。

改变

我们也在积极探索 Swift 在手淘的落地,取得了 Swift 5.1 能模块在手淘中正确运行起来的阶段性成就。

现在时机已经成熟,语言特性,SPM,工具链,标准库都已经足够强大,是时候做出改变了。

Swift 虽然看起来很简单,但其实它是一种下限低,上限高的语言,集团内部的 Swift 环境,需要大家来一起维护。我们未来也要加强 Swift 语言相关的培训,让开发者真正理解 Swift,上手 Swift,成为一名 Swifter 而不是 OSwifter。

手淘客户端团队正在进行社招招聘,岗位有iOS Android客户端开发工程师等,欢迎推荐。

简历投递:junzhan.yzw@taobao.com

参考

  1. SwiftUI 背后那些事儿
  2. WWDC20 What's new in Swift
  3. WWDC19 What's new in Swift
  4. WWDC18 What's new in Swift
  5. WWDC17 What's new in Swift
  6. WWDC16 What's new in Swift)
  7. WWDC20 Swift packages: Resources and localization
  8. WWDC20 What's new in SwiftUI
  9. Swift 5 时代的机遇与挑战到底在哪里?
  10. Swift Evolution

( WWDC 2020精彩内容思否专栏:https://segmentfault.com/blog...  

本篇内容来自于阿里巴巴淘系技术部,无线开发工程师星志。
更多精彩内容可关注【淘系技术】公众号。)

查看原文

赞 4 收藏 2 评论 0

阿里巴巴淘系技术 发布了文章 · 8月10日

Core Image:iOS图像处理技术追踪

简介

Core Image是苹果官方提供的图像处理框架,通过丰富的built-in(内置)或自定义Filter(过滤器)高效处理静态图片、动态图片或视频。开发者还可以通过构造Filter链或自定义Core Image Kernel来实现更丰富的效果。

在WWDC20中,苹果官方针对Core Image技术在以下三方面做了优化:Core Image对视频/动图的支持、基于Metal构建Core Image (CI) Kernel以及Core Image的Debug支持。这三方面会在下文逐一提到,文末笔者也会浅谈Core Image在手淘图片库中的应用可能以及对Core Image技术的展望。

( WWDC 2020精彩内容思否专栏:https://segmentfault.com/blog...  

本篇内容来自于阿里巴巴淘系技术部,无线开发工程师越伯。
更多精彩内容可关注【淘系技术】公众号。)

优化Core Image对视频/动图的支持

1. 创建CIContext

创建CIContext时,需要遵循一个view一个context的原则。由于视频的每一帧都会发生变化,将CIContext的cacheIntermediates属性设置为false可以大大减少内存消耗。

如果在使用Core Image时将同时运用Metal(作为输入或输出),通过设置MTLCommandQueue属性创建CIContext将会是较好选择。在不使用MTLCommandQueue的情况下,每一个Metal或CoreImage执行的任务都在不同队列中并以wait命令分隔开,导致任务执行效率低。通过设置MTLCommandQueue创建的CIContext和相应的Metal任务在同一队列中,能提高app的运行效率。

image.png

图一、不使用MTLCommandQueue的工作流程

image.png

图二、使用MTLCommandQueue的工作流程

2. 编写Core Image Kernel(在Metal中实现)

为了将效果处理得更丰富,通过Metal来实现自定义CI Kernel是个高效的选择。苹果官方提供了的许多方便部署的内置工具(都通过Metal实现),如内置CI滤镜。通过Metal实现自定义CI Kernel,不仅app的runtime编译时间将会大大减少(这段工作会移至app构建完成后进行),开发者还能获得高性能语言特性(如gather-reads、group-writes、半精度浮点数)、高效开发体验(如缩进检查、缩进高光)等功能。

3. 选择合适的View类

如果要对视频/动图应用特效,静态内容View如UIImageView或NSImageView应当被避免。AVPlayerView和MetalKit View(MTKView)是个两个不错的选择。前者为简单选择,后者为进阶选择。

使用AVPlayerView时,需要创建AVMutableVideoComposition对象,CI滤镜在block中执行图像处理任务。在进行断点debug时,通过点击CIImage对象地址右侧的眼睛图示可以浏览CI滤镜处理流程的详细信息。官方提供的案例中,Core Image还将10位的HDR视频帧数据自动从HLG转化成了Core Image working space。

image.png

图三、CI Image断点测试中展现的处理流程

使用MTKView时,开发者需要以frame和device作为参数重载init方法。VIew对应的CIContext也将在init函数中被创建。如果我们在macOS中开发支持HDR的view,color-Pixel-Format属性需要被设定为rgba16Float,wants-Extended-Dynamic-Range-Content属性需要被设定为true。设定完init方法后,开发者需要实现draw-in view方法。需要注意的是,此处并未直接将Metal材质传入CIRenderDestination函数,而是创建了一个会返回texture的block。这使得CIContext能在前面的帧尚未完成时将Metal工作入队。之后该方法会执行渲染任务(至指定目的地)并创建command buffer将当前绘制结果渲染至view。

本人也亲自尝试了通过Core Image处理视频的整个流程。以下案例使用CIVortexDistortion滤镜对视频进行逐帧处理并渲染,展示内容包含核心代码、原视频、CI滤镜处理后视频以及断点测试的滤镜逐帧处理图示。

image

代码一、测试核心代码

3.pngimage.png

断点调试时Core Image对每帧的处理流程

基于Metal构建Core Image Kernel

使用CI Kernel有诸多优势,包括上文提及的缩短runtime编译时间、高性能语言特性(如gather-reads、group-writes、半精度浮点数)、高效开发体验(如缩进检查、缩进高光)。基于Metal构建CI Kernel有5步流程,会在下文进行逐一介绍。

1. 在项目中增加自定义构建规则

苹果官方推荐在项目target中增加两项自定义构建规则。第一个构建规则针对以“.ci.metal”为后缀名的文件。该构建规则会创建一个以“.ci.air”为后缀名的二进制输出文件。

image.png

图五、针对“*.ci.metal”文件的构建规则

第二个构建规则针对以“.ci.air”为后缀名的文件(上一个构建规则的输出结果)。该构建规则会在app的资源文件夹内创建以“.ci.metallib”为后缀名的输出文件。

image.png

图六、针对“*.ci.air”文件的构建规则

2. 在项目中增加.ci.metal资源

在Xcode提供的创建面板中选择Metal File即可。开发者对Metal File进行命名时需要以“.ci”作为后缀名,这样项目中新生成的文件会以“.ci.metal”作为后缀名。

3. 编写Metal Kernel

便携Metal Kernel需要include CoreImage.h头文件,用来使用Metal和Core Image提供的各种类。官方提供的范例编写了一个CIColorKernel,输入参数为coreimage::samle_t对象(表示输入图片的一个像素)、time和coreimage::destination对象,返回float4像素。

image.png

图七、苹果官方提供的代码范例:Metal Kernel编写

苹果官方为开发者提供了描述CI Kernel中Metal Shader语言的文档,详情见「 Metal Shading Language for Core Image Kernels」。

4. 加载Kernel并应用于新图像(基于Swift)

Kernel会被CI滤镜的子类使用。苹果官方推荐开发者在实例化滤镜的CIKernel对象时使用静态属性(static property),这种情况下加载metallib资源的工作仅会执行一次(在首次需要时)。CI滤镜的子类也必须重载输出图片的属性,Kernel将在getter中进行图像处理并创建新图像。

image.png

图八、苹果官方提供的代码范例:Kernel加载与使用

Core Image的Debug支持

苹果官方在WWDC20详细介绍了Debug特性:CI_PRINT_TREE。

什么是CI_PRINT_TREE

CI_PRINT_TREE的基础框架与Xcode提供的Core Image Quick Look支持相同。Core Image Quick Look为开发者提供了快捷可视化的Core Image图片(详见上文图三),而CI_PRINT_TREE支持几种不同的模式和选项用来查看Core Image如何优化和渲染图像。

如何启用CI_PRINT_TREE

苹果官方提供了CI_PRINT_TREE的两种启动方式。最常用的方法是编辑Xcode target scheme,在Arugments窗体下的环境变量列表中加入CI_PRINT_TREE并设置值。另一种方法是在Terminal.app中通过命令行启动CI_PRINT_TREE(需要在执行应用程序前设定)。

image.png

image.png

图九、启用CI_PRINT_TREE的两种方式

如何控制CI_PRINT_TREE

CI_PRINT_TREE的字符串格式为“<graph type> <output type> <options>”

  1. graph type:表示Core Image render的若干stage,包括type-1初始图像(有助于查看被使用的色彩空间)、type-2优化后的图像(有助于查看core image对render的优化效果)、type-4级联图像(有助于查看各stage如何级联于GPU程序,以便了解render需要多少中间缓存)以及type-7(输出图像type1、2和4)。

image.png

图十、苹果官方对graph type四个stage的描述

  1. output type:输出格式可以是pdf或png。在macOS上trees会被存储在临时项目文件夹,在iOS上trees会被存储在文档(Documents)目录下。如果output type没有确定,core image会把tree以紧凑文本格式输出在标准输出(stdout)。通过设置CI_LOG_FILE="oslog",文本也可以前往Console.app(在iOS开发中更为方便)。
  2. options:对于CI_PRINT_TREE,开发者可以设定额外的选项。如通过设定context==name来限制输出(仅输出名字相同的context),或是通过设定frame-n来框定具体输出context的哪一帧。更多option及详情请见图十一。设定option对debug能提供很大帮助,但也需谨慎使用,因为生产这些文件需要额外的时间和内存。

image.png

图十一、苹果官方提供的option

image.png

图十二、type设定为7时tmp文件夹下的文件

如何获得CI_PRINT_TREE文件

在macOS中,开发者只需要进入“/tmp”文件夹就能找到生成的CI_PRINT_TREE文件。需要注意的是沙盒应用会使用特有的临时存储文件夹。在iOS中,开发者需要将Custom iOS Target Properties中的“Application supports iTunes file sharing”项设为YES(图十三)。这样生成的CI_PRINT_TREE文件可以在连接中的iOS设备上被找到并拖拽至macOS存储中。

image.png

图十三、Custom iOS Target Properties中进行设置

如何解释CI_PRINT_TREE文件

读CI_PRINT_TREE时,需要遵循以下规则:

  • 输入在底层,输出在顶层  
  • 绿色节点代表卷曲内核(warp kernel),红色节点代表颜色内核(color kernel)

image.png

图十四、绿色节点与红色节点示例

  • 在树的初始位置(initial tree)很容易找到颜色搭配节点(colormatch nodes),里面记录了搭配前后的色彩空间名称。苹果官方提供的案例为ITUR_2100_HLG_to_workingspace,即HLG色彩空间转化为Core Image线性色彩空间。

image.png

图十五、苹果官方案例中initial tree对色彩空间的描述

  • 每个节点会显示Region of Interest(ROI),表示该节点在render中被使用的范围。

如果开发者在CI_PRINT_TREE控制字符串中选择type-4并在option中设定dump-intermediates,产生的级联图片会展示中间缓存的每一次pass(除了output pass)及其耗时、像素点数量和像素点格式(用来查找耗时大、占内存大的pass)。这对render内追踪错误非常有帮助。如果树中没有展示中间图,那么说明这张图在先前渲染的时候已被缓存,因此Core Image没有渲染它的必要。

image.png

图十六、设定dump-intermediates的debug效果展示

Core Image在手淘图片库中的应用可能

手淘图片库中的CDN图片适配处理库(TBCDNImage)的核心目的是为不同终端设备、网络环境下的图片展示提供最优解。目前考虑的维度主要是终端设备硬件和网络状态,考虑的参数则是图片尺寸、压缩比率、锐化等图片属性。随着苹果在Core Image、端智能(CoreML)、硬件支持(自研芯片)等方面进行技术提升,淘的CDN图片适配处理库可以考虑增加“图片内容”作为新的维度,增加亮度、对比度、滤镜、图片种类等新参数。以下为部分应用场景:

  • 识别亮度较暗的图片,提升亮度做CDN图片适配处理
  • 判断图片内容种类(如美食),根据不同内容种类的图片增加适合的滤镜做CDN图片适配处理
  • 根据移动终端设备屏幕亮度(或深/浅色模式)修改图片色调做CDN图片适配处理,达到护眼效果

对Core Image技术的展望

总结全文,WWDC20对Core Image技术的提升主要在三方面:

  • 优化CI对视频/动图的支持,包括开发流程简化、逐帧处理性能提升等。
  • 允许开发者更自由的构建Core Image Kernel,使CI的特效处理更加丰富
  • 针对CI开发流程提供更高效的Debug支持

随着苹果未来自研芯片的底层硬件支持将提供视频流流畅的逐帧处理与渲染。笔者认为Core Image技术将会在以下场景有较大应用价值:

  • 直播滤镜/特效功能原生化(摆脱自研或第三方API),实现质量更高的实时滤镜渲染
  • 视频拍摄增加滤镜功能(如淘宝或咸鱼的商品视频录制)

参考:

① https://developer.apple.com/m...

https://github.com/duzhaoquan...

团队招人

手淘客户端团队正在进行社招招聘,岗位有iOS Android客户端开发工程师、欢迎大家加入我们。

简历投递:junzhan.yzw@taobao.com

更多有关手淘的技术内容分享敬请关注VX公众号【淘系技术】

查看原文

赞 1 收藏 0 评论 0

阿里巴巴淘系技术 发布了文章 · 7月29日

WWDC20:无线网络优化实践,带来哪些启发?

0. 引

网络技术作为互联网应用赖以存在的技术基础,速度与安全永远是其核心使命,本次WWDC的网络类topic涵盖内容基本还是围绕这两个点来展开。本次WWDC网络类session在基础网络技术上譬如新协议、新算法方面着墨并不多;也未提出新的类似NSURLSession / Network.framework之类的新网络组件。站在应用视角,本次WWDC网络类session可分为两大类:

  • 无线网络体验优化实践在系统层面的标准化;
  • 本地网络应用的权限管控增强。

在第一类议题中,我们看到很多已经在手淘中的类似实践,或标准或自研,说明手淘在网络技术的开发与应用上还是较为深入和前沿的,基本走在全球业界前列。根据我们手淘的业务特点,笔者重点关注第一类session,并简单探讨该新技术可以我们带来什么样启发和变化。

( WWDC 2020精彩内容思否专栏:https://segmentfault.com/blog...  

本篇内容来自于阿里巴巴淘系技术部,无线开发专家 无宸。
更多精彩内容可关注【淘系技术】公众号。)

1. 使用加密DNS

DNS解析是网络的连接的第一步,这里提到的"加密DNS"是什么、它解决什么问题?

1.1 解决什么问题

一是传统Local DNS的查询与回复均基于非加密UDP,我们常见的DNS劫持问题

image.png

二是Local DNS Server本身不可信,或者本地Local DNS 服务不可用

image.png

其实针对DNS解析过程中以上两个问题,在实践中早就有了解决方案,就是HTTPDNS, 各大云厂商也都有成熟产品售卖,那苹果这里的加密DNS与我们的现有HTTPDNS有何不同呢?现有HTTPDNS有两个很大的问题:一是对业务的侵入性,即如果某个网络连接需要使用HTTPDNS的能力,首先他需要集成服务商提供的SDK, 引入相应的Class,然后修改网络连接的阶段的代码;二是面临各种技术坑,比如302场景的IP直连处理、WebView下IP直连如何处理Cookie、以及iOS上的老大难的SNI问题等,这些都需要业务开发者付出极大的努力和尝试。

iOS 14 上的 Encrypted DNS 功能很好的解决了现有HTTPDNS的存在的问题。

1.2 规范与标准

iOS 14 开始系统原生支持两种标准规范的 Encrypted DNS, 分别是 DNS over TLS 与 DNS over HTTPS.

image.png

具体协议标准可以参见:rfc7858 (DoT)rfc8484 (DoH)

1.3 如何实现

iOS 14 提供了两种设置加密DNS的方法。第一种方式是选择一个DNS服务器作为系统全局所有App默认的DNS解析器,如果你提供的是一个公共DNS服务器,你可以使用NEDNSSettingsManager API编写一个NetworkExtension App完成系统全局加密DNS设置。或者如果你使用MDM(Mobile Device Management)管理设备的企业设置;你可以推送一个包含DNSSettings paload的profile文件完成加密DNS设置。

image.png

使用NetworkExtension设置系统域全局DNS服务器示例代码:

图1.png

上述代码首先通过NEDNSSettingsManager加载配置,加载成功后,创建一个基于DoH协议的NEDNSOverHTTPSSettings实例,对其配置DNS IP地址和域名,DNS IP地址是可选配置的。然后将NEDNSOverHTTPSSettings实例配置到NEDNSSettingsManager共享实例的dnsSettings属性,最后保存配置。

一条DNS配置包括DNS服务器地址、DoT/DoH协议、一组网络规则。网络规则确保DNS设置兼容不同的网络。因为公共DNS服务器是无法解析本地网络的私有域名,比如只有企业WiFi网络内的DNS服务器可以解析员工访问的私有域名,这类情况就需要手动指定网络规则兼容企业WiFi网。网络规则可以针对不同网络类型定义行为,比如蜂窝网、WiFi、或者具体的WiFi SSID。在匹配的网络下,你可以禁用配置的全局DNS设置,或者对私有域名不使用DNS设置。而在一些情况下,兼容性会自动处理。比如强制门户网络(captive portal), 手机在连接上某个WiFi的时候,自动弹出一个页面输入账号密码才能连接网络。这种情况下系统域全局DNS配置会做例外处理。

网络规则设置示例代码:

图2.png

上述代码设置了三个网络规则,第一个规则表示DNS配置应该在SSID="MyWorkWiFi"的WiFi网络生效,但对私有企业域名enterprise.example.net不开启。 第二个规则表示规则在蜂窝网下应该被禁止使用;第三个NEOnDemandRuleConnect表示DNS配置应该默认开启;因为配置DNS是系统支持的,所以在编写NetworkExtension App时不需要实现Extension程序,只需要在Network Extensions中勾选DNS Settings选项。

图7.png

运行NetworkExtension App,DNS配置将会被安装到系统,为了让DNS配置生效,需要前往设置->通用 & Network->DNS手动启用。

图3.png

一些网络可能会通过策略阻止你使用加密的DNS服务器。这些网络尝试分析DNS查询请求来过滤流量。对于此类网络,系统会被标记隐私警告提示,在该网络下的网络连接将会失败。

图4.png

第二种方式是针对单个App的所有连接或部分连接启用加密DNS。

image.png

如果你只想为你的App使用加密DNS,而非涉及整个系统域。你可以适配Network framework的PrivacyContext,对你的整个App开启加密DNS,或者仅对某一连接开启。不管使用的是URLSessionTask,或Network framework连接或getaddrinfo的POSIX API,这种方式都有效。

对单个连接使用加密DNS示例代码:

图5.png

验证请求是否使用加密DNS:

截屏2020-06-26 上午1.24.27.png

如果你想在App范围内使用加密DNS,你可以配置默认的PrivacyContext;App内发起的每个DNS解析都会使用这个配置。不管是URLSessionTask,还是类似getaddrinfo的底层API。

图6.png

1.4 现有实践对比及启发

  • 与现有实践对比

上文已经提到过HTTPDNS产品,手淘的域名解析,采用的是类似于HTTPDNS原理,但更加复杂的调度方案。但是相比于这种系统层面的标准化方案,解决了现有实践中的两大难题:

  • 对业务的侵入性:业务必须修改现有网络连接的阶段的代码;
  • 交互的标准兼容性不足:IP直连下的302问题、Cookie问题、SNI问题等
  • 带来的变化

一是在应用内部,我们可以对业务透明提供提供全局的域名调度或者域名兜底解析能力, 不再是只有用到特定组件或SDK才可以。二是苹果放开系统级别DNS接管后,用户设备上的服务相比原Local DNS的“中立性”如何管控?对特定业务是否甚至会造成恶化?如果对外部应用的这种“中立性”疑问或担心确实存在,则这种系统标准化的加密DNS对手淘这种大型应用则是必选项。

2. 受限网络中推送

2.1 解决什么问题

当向iOS设备推送消息时,业务服务器需要将消息先发送给APNS服务器,APNS服务器再将消息转换为通知payload推送给目标设备。如果设备所在的WiFi网络没有连接互联网或者当前网络受限,比如在游艇、医院、野营地这些地方,设备没有与APNS服务器建立有效连接,APNS消息投递将会失败。

截屏2020-06-27 上午12.46.47.png

对于一些App来说,接收推送消息是App的一项非常重要的功能,即使在没有互联网连接的情况下也需要持续稳定工作。为了满足这一需求,iOS 14中增加了本地推送连接(Local Push Connectivity)API,这是NetworkExtension家族中新的API。本地推送连接API允许开发者创建自己的推送连接服务,通过开发一个App Extension,在指定的WiFi网络下可以直接与本地业务服务器通信。

截屏2020-06-27 上午1.02.19.png

上图中,App Extension主要负责保持与本地业务服务器之间的连接,以及接收业务服务器发来的通知。因为没有了APNS,开发者需要为业务服务器与App Extension定义自己的通信协议。主App需要配置具体在哪个WiFi网络下使用本地推送连接。当App加入到指定的WiFi网络,系统会拉起App Extension, 并在后台持续运行。当App断开与指定WiFi网络的连接,系统将停止App Extension运行。

2.2 如何实现

本地推送连接对那些推送功能非常重要,而设备所在网络受限的场景非常适合。而对于常规的推送需求,依然推荐使用PushKit或UserNotification API处理APNS推送消息。每台设备和APNS服务器之间只建立一条APNS连接,设备上所有App都公用这一条连接,所以APNS非常省电。

APNS与本地推送连接对比:

截屏2020-06-27 上午1.25.28.png

新的本地推送连接API由两个类组成:NEAppPushManager和NEAppPushProvider。NEAppPushManager在主App中使用,主App使用NEAppPushManager创建一个配置,配置中指定具体哪个WiFi网络下运行本地推送连接。你可以使用NEAppPushManager加载/移除/保存配置。NEAppPushProvider则在App Extension使用。在App Extension中实现一个NEAppPushProvider的子类,子类中需要覆盖生命周期管理方法,这些方法在App Extension运行和停止时被调用。

App Extension主要处理两类推送,一类是常规的推送通知,一类是VoIP呼叫通知。如果是常规的推送通知,App Extension收到消息后,可以使用UserNotification API构造一个本地推送显示推送信息。如果是VoIP呼叫通知,App Extension使用NEAppPushProvider类将呼叫信息报告给系统。如果此时主App不在运行,系统将唤醒主App,并将消息投递给它,最后主App再使用CallKit API显示呼叫界面。

截屏2020-06-27 上午11.40.13.png

下面是在主App中使用NEAppPushManager的示例代码:

截屏2020-06-27 上午1.44.40.png

上述代码创建了一个NEAppPushManager实例,并配置实例的各个属性值。matchSSIDs表示在指定的WiFi网络下才启用本地推送连接。providerBundleIdentifier表示App Extension的包名,providerConfiguration是传给App Extension的一些配置,在App Extension内可以通过NEAppPushProvider的providerConfiguration属性获取。isEnabled表示使用这个配置开启本地推送连接。最后调用saveToPreferences方法持久化配置。下面是App Extension实现NEAppPushProvider子类的示例代码:

截屏2020-06-27 上午1.46.47.png

系统调用start(completionHandler:)方法启动App Extension,在这个方法内App Extension与本地业务服务器建立连接。当App Extension停止运行,系统调用stop(with:)方法, 在这个方法内App Extension断开与业务服务器的连接。handleIncomingVoIPCall(callInfo:)方法在收到VoIP呼叫时被调用,在方法内App Extension调用reportIncomingCall(userInfo:)将该事件上报给系统。随后系统将会唤醒主App,并将呼叫信息传递给主App。主App处理系统传入的呼叫信息示例代码:

图8.png

以上代码在AppDelegate的didFinishLaunchingWithOptions方法内使用NEAppPushManager加载所有配置,并设置每个NEAppPushManager示例的代理属性。系统会在主线程中将接收到呼叫信息通过didReceiveIncomingCallWithUserInfo方法投递给主App。主App必须通过CallKit API将呼入信息上报给CallKit展示呼叫界面。

2.3 价值场景

如果只考虑推送本身,对于手淘或者大部分消费类应用来说,笔者认为价值并不大,因为此类APP不可能在一个封闭的本地网络里去部署资源来提供服务能力。这里一个可应用的点在于:设备一旦进入特定网络环境,触发App Extension, 进而唤起主App,应用可在后台完成一定事务。因为 iOS App 一直缺乏后台服务能力,这种特定网络环境的触发唤醒,极大的补充了这一能力。

3. 现代网络技术的应用

苹果在这次WWDC中,把一些较新的网络技术,对应用的体验提升,做了一个简单综述,包括IPv6、HTTP/2、TLS1.3, MTCP、以及HTTP/3。这些技术在手淘基本都有涉及,有些是已经是大规模部署、有些是正在逐步推进中。对各个应用来说,如果已经在应用这些技术了,则云端均尽可能标准化,便于进一步推广和复用。这里简单的对苹果的综述做一个搬运:

3.1 IPv6

苹果根据最新统计,苹果全球设备TCP连接占比中,IPv6占比26%,IPv4占比74%,其中74%的占比中有20%是因为服务端没有开启IPv6支持。在建连时间方面,由于减少了NAT使用,提高了路由效率,IPv6的建连时间比IPv4快1.4倍。开发者只需使用URLSession和Network.framework API,IPv6网络适配将自动支持。

截屏2020-06-29 下午7.44.02.png

以上是苹果的数据。阿里巴巴集团从18年开始大力推进IPv6的建设,目前我们在IPv6整体应用规模上在业界是属于头部大厂。但根据我们应用的实际效果数据,以及业界友商的应用数据,性能提升并不明显。以及工信部的IPv6建设目标来看,性能提升也不是IPv6建设的目标,只要达到IPv4同等水平即可。IPv6 的意义就在解决IPv4地址空间枯竭的问题,更多的在规模、安全,而不是性能提升。就企业而言,例如可以降低IPv4地址的购买费用;就国家而言,IPv6 突破了IPv4中国境内无DNS根结点的风险。IPv6目前阶段在国内尚处于发展中,基础运营商覆盖、家用网络接入设备支持、应用服务的支持,正在快速发展中。

3.2 HTTP/2

HTTP/2的多路复用特性使得对同一服务器的多个请求复用到单个连接上,不必等待前一个请求响应结束才能发送下一个请求,不仅节省了时间也提升了性能。头部压缩特性提升了带宽利用率,通过简化消息内容,从而降低消息的大小。根据最新统计,在Safari中HTTP2 Web流量占比79%,HTTP/2比HTTP/1.1快1.8倍。如果服务端支持HTTP/2,URLSession将默认使用HTTP/2。

截屏2020-06-29 下午11.02.47.png

在手淘业务中,全面应用HTTP2已经有三四年之久,其使用规模比苹果统计的结果要高的多,取得了巨大的体验提升收获。手淘的核心流量分为两类:API请求MTOP于图片CDN请求,这两类的HTTP2的流量占比约超过 98%,基本实现核心流量全部长连化。但当前手淘的HTTP2技术在设备支持之前即大规模应用,协议栈完全自研,为进一步提升建联速度,又做了一些预置证书的优化。下一步将逐步使基础网络依赖标准化平台能力,降低对私有协议栈的依赖,可降低包大小以及提升产品复用体验。

3.3 TLS1.3

TLS1.3通过减少一次握手减少了建连时间,通过形式化验证(Formal Verification)与减少被错误配置的可能性,提高了通信安全。从iOS 13.4开始,TLS1.3默认在URLSession和Network.framework开启。根据最新统计,在最新的iOS系统上,大约49%的连接使用TLS1.3。使用TLS1.3比使用TLS1.2建连时间快1.3倍。如果服务端支持TLS1.3,URLSession将默认使用TLS1.3。

截屏2020-06-29 下午11.02.24.png

目前手淘的HTTP/2 的TLS version仍然还是基于TLS1.2,不过为了解决低版本TLS的性能之殇,手淘网络通过预置证书与自定义 SSL 握手流程,创新自研了slight-ssl协议,实现了 0rtt 的效果。TLS 1.3 标准在系统层面的全面支持,对应用来说是一个明确的技术趋势信号,我们的网络协议需尽快标准化,对网络管道两端来说,客户端应用层网络接口需全面升级到NSURLSession或Network.framework, 实现对系统标准能力的应用;云端也许全面支持TLS1.3,可不依赖端侧SDK即可提供更新安全、高效、标准的网连接。

3.4 MultiPath TCP

MultiPath TCP 允许在一条TCP链路中建立多个子通道。当设备切换网络时,单个TCP连接依然可以继续使用。苹果的Apple Music与Siri服务都使用了MultiPath TCP。Apple Music在使用MultiPath TCP之后,音乐播放卡顿次数减少了13%,卡顿持续时间减少了22%。开启MultiPath TCP需要客户端和服务端都支持才能生效,服务端支持MultiPath TCP可参考:http://multipath-tcp.org/

其实手淘在这方面也有类似的优化尝试:多网卡:同时通过Wi-Fi与蜂窝网连接目标服务器,提升数据传输速度。其技术原理与MTCP不一样,但也是想在上层起到类似作用:通过多路连接,提升数据交换带宽。 业界也有类似的产品,例如华为的 LinkTurbo。

3.5 HTTP/3

HTTP/3是下一代HTTP协议,它是构建在新的QUIC传输协议之上,QUIC协议内建了对TLS1.3的支持,并提供了与HTTP/2一样的多路复用功能,并进一步减少了队头阻塞的发生,让单个请求或相应的丢失不影响到其他请求。使用QUIC的HTTP/3还具有较高的保真度信息,以提供改进的拥塞控制和丢包恢复。同时也包括内建的移动性支持,这样网络切换不会导致正在进行的操作失败,可以无缝在不同网络之间切换。不过HTTP/3目前还处于草案阶段,iOS 14和MacOS Big Sur包括了一个对使用URLSession的HTTP/3的实验预览支持,这个功能可以在开发者设置中开启。同时Safari的HTTP/3支持也可在开发者设置中开启。

截屏2020-06-30 上午12.48.15.png

在手淘中,我们的QUIC应用应该会早于苹果系统先行支持,目前已经在灰度中。

( WWDC 2020精彩内容思否专栏:https://segmentfault.com/blog...  

本篇内容来自于阿里巴巴淘系技术部,无线开发专家 无宸。
更多精彩内容可关注【淘系技术】公众号。)

——————————————————————————————————————————————————

手淘客户端团队正在进行社招招聘,岗位有iOS Android客户端开发工程师等,欢迎推荐。

简历投递:junzhan.yzw@taobao.com

查看原文

赞 0 收藏 0 评论 0

阿里巴巴淘系技术 发布了文章 · 7月23日

Apple Widget:下一个顶级流量入口?

0x00 前言

2020 年 6 月 22 日,苹果召开了第一次线上的开发者大会 - WWDC20。这可谓是一次可以载入史册的发布会,宣布了 ARM 架构 Mac 芯片、软硬件的生态大统一、iOS 14 系统界面大改等一系列激动人心的消息。

当然,最让我感兴趣的就是让 iOS 界面大改的 Widget 了。过去几年,iOS 的桌面交互体验可谓是一言难尽,Widget 的加入无疑是一次比较大的破局。在看发布会的时候,我的脑海里就浮现出一个问题:“这会是下一个互联网公司竞争的流量入口吗?”

先不抛结论,让我们先看一下 WWDC20 介绍了哪些关于 Widget 的新东西。

( WWDC 2020精彩内容思否专栏:https://segmentfault.com/blog...  

本篇内容来自于阿里巴巴淘系技术部,高级无线开发工程师柘剑。
更多精彩内容可关注【淘系技术】公众号。)

0x01 什么是 Widget?

Widget 不是一个小型的 App,它是一种新的桌面内容展现形式,主要是用于弥补主应用程序无法及时展示用户所关心的数据。如下图所示:

image.png

一个优秀的 Widget 需要有三个特点:简单明了(Glanceable)恰当展示(Relevant)个性化定制(Personalized)

简单明了(Glanceable)

Widget 不是一个小型的 App,这句话被反复提起。一般用户每天进入主屏幕的次数超过 90 次,但停留的总时长不过几分钟。通常来说用户只会在主屏幕上停留片刻时间,就会跳转到其他地方,所以并不需要任何复杂的交互设计来增强 Widget 的作用,也不需要复杂的样式来丰富 Widget 的内容,简单明了的内容才是 Widget 的关键。

和安卓的 Widget 不太一样,苹果设计的 Widget 并不支持任何交互行为,也不建议大家设计过于复杂的样式来呈现内容,这也非常符合苹果对于主屏幕的改进一直保持克制的特点。

恰当展示(Relevant)

苹果期望 Widget 可以和正在执行或者考虑的事情紧密的结合。比如,早上起床,用户最关心天气怎么样,Widget 可以展示一下天气情况;起床后,用户就要了解一下一天的行程,Widget 可以展示一下 Reminders 中的内容;等到一天忙完了,准备睡觉的时候,可以用 Widget 打开音乐稍微放松一下。为此,苹果系统提供了一个叫智能叠放(Smart Stacks)的功能,智能叠放是一个 Widgets 的集合。系统会根据每个人的习惯,借助端智能的能力,自动的显示准确的 Widget 在最顶部。

image.png

当然,苹果也考虑到了一些特殊的场景,比如 Widget Gallery 浏览时,提供了 Snapshot 的能力给到开发者可以定制展示样式,当加载内容的时候提供了 Placeholder UI API 而不是单调的 loading 加载框来避免过多的白屏的尴尬局面。这些设计的目的只有一个,苹果期望 Widget 可以在任何特定的场景都可以展示合理的样式。

个性化定制(Personalized)

Widget 需要一定的定制能力,比如当我添加一个天气 Widget,我只需要关心杭州的天气怎么样。为了实现这个能力,苹果给 Widget 提供了 Configuration 的能力。顾名思义,就是可配置。一共有两种配置类型:

image.png

  • StaticConfiguration,也就是用户无需配置,展示的内容只和用户信息有关系。
  • IntentConfiguration,支持用户配置及用户意图的推测功能。

IntentConfiguration 的实现是基于 Intents.framework,开发过 SiriKit 和 Shortcuts 一定知道 Intents API 是用于了解用户意图的。其实就是一个智能的表单系统,开发者创建一个 SiriKit Intent Definition File 之后,只需要简单的配置,Xcode 会自动帮你生成对应的代码和类型。

image.png

当开发者编写完配置之后,会借助 Intents.framework 的能力,在运行的时候直接绘制出一个配置页面(如下图所示),开发者并不需要关心如果编写这个页面。

image.png

0x02 Widget 的刷新方式


Widget 的刷新方式是很特别的,相当的克制。在展开讲刷新方式之前,要讲一个概念,叫 Timeline。顾名思义,就是时间线,下面的图就是一条 Timeline。

image.png

当系统的 WidgetKit 调用 Reload Timeline API 之后,会要求 Widget Extension 的 Timeline Provider 提供一组 TimelineEntry 和 ReloadPolicy,用来后续刷新页面。

这里的概念比较多,我们一个一个来解释。

首先,Widget 的刷新完全由 WidgetCenter 控制。开发者无法通过任何 API 去主动刷新 Widget 的页面,只能告知 WidgetCenter,Timeline 需要刷新了。

系统提供了两种方式来驱动 Timeline 的 Reload。System Reloads 和 App-Driven Reloads。

System Reloads: 这个行为由系统主动发起,会调用一次 Reload Timeline 向 Widget 请求下一阶段刷新的数据。系统除了会按时发起 System Reloads 之外,还会借助端智能的能力,动态决策每个不同的 TimeLine 的 System Reloads 的频次。例如被查看次数很大程度上直接决定了 System Reloads 的频率。当然还有一些由于设备环境变化触发的行为也会触发 System Reloads,比如设备时间进行了变更。

App-Driven Reloads:指的是 App 请求 Widget 下一阶段刷新的数据。这里也要分两种场景,应用在前台运行和应用在后台运行。当应用在前台运行的时候,App 可以直接请求 WidgetCenter 的 API 来触发 Reload Timeline;而当应用处于后台时,后台推送(Background Notification)也可以触发 Reload Timeline。

image.png

注意,前面所提到的 Reload Timeline 并不是直接刷新 Widget,而是 WidgetCenter 重新向 Widget 请求下一阶段的数据。而 Timeline Provider 就是提供这个数据的对象。

而 Timeline Provider 提供的数据有两部分,一部分是 TimelineEntry,另外一部分是 ReloadPolicy。

TimelineEntry 是某个时间节点下 Widget 需要呈现的视图信息和时间点。

而 ReloadPolicy 则是接下来这段时间 Timeline 的刷新策略,一共有三种:

  • atEnd: 是指 Timeline 执行到最后一个时间片的时候再刷新。
  • atAfter: 是指在某个时间以后有规律的刷新。
  • never:是指以后不需要刷新了。什么时候需要重新刷新需要 App 重新告知 Widget。

当 Timeline Provider 提供完下一阶段的数据之后,就会停止运行。系统也会根据 entry 的信息,到点对 Widget 的展示内容进行刷新。值得一提的是,WidgetKit 会把 Timelines 所定义的 Entries 对应的 Views 结构信息缓存到磁盘,然后在刷新的时候才通过 JIT 的方式来渲染。这使得系统可以在极低电量开销下为众多 Widgets 处理 Timelines 信息。

简而言之,苹果对 Widget 的刷新相当的克制。开发者无法直接决定 Widget 刷新,只能提供刷新策略。具体的时间和节奏全部由系统来控制。苹果这么做,大概率是为了提高主屏幕的性能和减少电量开销上的考虑。

0x03 Widget 和 SwiftUI

Widget 只能用 SwiftUI 来进行开发,确切的说,Widget 的本质是一个随着时间线而更新的 SwiftUI 视图

image.png

当我最开始知道这个限制的时候,说实话是相当震惊的。众所周知,SwiftUI 是一个去年才发布的新技术,而且最开始的时候 SwiftUI 是相当不稳定的,以至于苹果自己都是建议开发者暂时不要用到生产环境上,Widget 作为系统主屏幕的功能,强制使用这么新的技术,会不会太激进了?

显然是不会。苹果要求 Widget 只能使用 SwiftUI 主要是基于几点考虑:

  1. SwiftUI 经过一年的发展,有了很大的提升,不仅可以使用 SwiftUI 来构建整个应用程序,而且在一些方面已经优于基于 UIKit 的开发方式了。具体的内容,大家可以看一下 《详解 WWDC 20 SwiftUI 的重大改变及核心优势》
  2. 苹果正在布局跨平台,大统一的策略。Widget 作为系统的核心功能,使用 SwiftUI 是唯一的选择。SwiftUI 精美的 DSL 设计,使得开发者使用一套代码在 iOS、iPadOS、macOS、watchOS 和 tvOS 等多个平台展示不同的样式可以轻松的实现。(Widget 只会在 iOS、iPadOS 以及 macOS 上展示)
  3. 使用了 SwiftUI 使得 Dynamic Type 和 Dark Mode 等问题适配起来成本很低。
  4. 只有使用 SwiftUI 才能达到很多对于 Widget 的限制。倘若可以使用 UIKit 开发者可能有无数种办法绕过苹果的限制。比如开发无法使用 UIViewRepresentable 来桥接 UIKit,只要使用任何 UIKit 的元素会直接 Crash。
  5. 将 Swift 语言和 SwiftUI 的重要程度提升了一大截。

0x04 Widget 的展示形式

一个 App 可以对应多个 Widget Extension

你可以使用 WidgetBundle 来进行组装。苹果并没有对 Widget Extension 有数量上的限制。所以为了避免大家开发过多的 Widget Extension 导致搜索起来麻烦,在 Widget Gallery 中只能看到一个条目。

normal-video.gif

一个 Widget Extension 一共只有三种尺寸。

考虑到简单明了的特点以及手机屏幕的空间有限的问题。苹果只提供了三种样式可以选择,systemSmall(2 * 2 icon 区域)、systemMedium(2*4 icon 区域)、systemLarge(4 * 4 icon 区域)

image.png

同一种 Widget 可以被多次添加到主屏幕中

而且对于每一个 Widget 来说,都有其对应的独立 TimeLine,相互独立,互不干扰。

image.png

开发者无法开发智能叠放(Smart Stacks)

开发者无法开发一个 Widget 的集合。智能叠放(Smart Stacks)是一个系统特有的能力,对于开发者来说,唯一可以做的就是主动提供相关性信息。前文提到了 Timeline 的数据又一组 TimelineEntry 组成,而每个 TimelineEntry 除了包含时间点和视图信息以外,还可以包含一个 TimelineEntryRelevance 对象,用来表示这个 entry 的相关性。

不可交互,只可点击

Widget 的 UI 是无状态的,不支持滚动,也不支持像 Switch 一样的互动元素。唯一开放的能力只有通过点击和DeepLink 来唤起主 App。

苹果提供了两种 API 给到开发者,第一种是 SwiftUI widgetURL API),代码如下所示:

image.png

而 widgetURL 的可点击区域如下:

image.png

对于 systemSmall 类型来说,只支持 widgetURL 的方式,但是 systemMediumsystemLarge 还可以使用 SwiftUI Link API,代码如下所示:

image.png

而 Link 的可点击区域如下:

image.png

同时,为了性能和耗电量的考虑。Widget 不能展示视频和动态图像。所以期待通过动效吸引用户眼球的方式可以暂时息熄火了~

0x03 总结与展望

Widget 的出现,让 iOS 系统的桌面有了破局,一定会有很多产品都期待借助 Widget 来丰富自己产品的内容表达。

但是,Widget 设计的初衷是简单明了的在恰当的时机展示一些带有个性化定制的内容,为了不让主屏幕的整体使用体验变得复杂,Widget 从技术上就做的很克制,限制了很多很多的能力。因此我认为Widget 不会成为下一个互联网公司竞争的流量入口,它会成为 App 提高用户体验的利器。

从技术角度看,SwiftUI Only 这种看似“激进”的策略其实也是一种信号,其实也是在告诉大家苹果对于 Swift 以及 SwiftUI 的重视程度。

虽然,从目前来看 Pure SwiftUI 的设计,可以做的事情真的很少,但是我也相信,苹果会不断优化 Pure SwiftUI 的能力。让开发者可以以最低的开发成本,适配更多的平台。

最后,也期待大家可以好好研究一下 Widget,结合自己的产品,给到用户极致的用户体验。

( WWDC 2020精彩内容思否专栏:https://segmentfault.com/blog...  

本篇内容来自于阿里巴巴淘系技术部,高级无线开发工程师柘剑。
更多精彩内容可关注【淘系技术】公众号。)

参考

iOS 14 Preview: https://www.apple.com.cn/ios/ios-14-preview/

Widgets code-along: https://developer.apple.com/news/?id=yv6so7ie

Meet WidgetKit: https://developer.apple.com/videos/play/wwdc2020/10028/

What's new in SwiftUI: https://developer.apple.com/videos/play/wwdc2020/10041/

Add configuration and intelligence to your widgets:https://developer.apple.com/videos/play/wwdc2020/10194/

Build SwiftUI views for widgets: https://developer.apple.com/videos/play/wwdc2020/10033/

Creating a Widget Extension: https://developer.apple.com/documentation/widgetkit/creating-a-widget-extension

Building Widgets Using WidgetKit and SwiftUI:https://developer.apple.com/documentation/widgetkit/building_widgets_using_widgetkit_and_swiftui

Making a Configurable Widget: https://developer.apple.com/documentation/widgetkit/making-a-configurable-widget

Keeping a Widget Up To Date: https://developer.apple.com/documentation/widgetkit/keeping-a-widget-up-to-date

团队招人

负责手淘移动端的基础PaaS及平台技术。涉及移动网关、网络加速、长连通道、图片体验等基础技术,以及海量消息推送、浮层搭投全域触达等平台型技术,并对移动端系统进行前沿探索,打造了全站IPv6、iOS用户态网络栈、Android最小核、自适应线程调度等高性能技术和架构。

在这里,你会面临超级App在性能、体验、安全等方面的极致追求;在这里,你会站在业务和数据视角针对目标进行充分了解和深入优化;在这里,你会与业界各领域大牛并肩作战、快速成长。

我们期待有技术、有理想的你加入,与我们共享积极、透明、开放的团队氛围,伴随着各种干货满满的分享培训以及业务和技术挑战,我们将一同在技术领域不断攻坚、推陈出新,共同驶向属于我们的星辰大海。

职位:iOS 开发、Android 开发、C++开发、Java 服务端开发、前端开发、数据工程师、算法工程师

感兴趣的同学可将简历发送到:zhejian.wzj@alibaba-inc.com,获取优先内推资格!

查看原文

赞 4 收藏 1 评论 0

阿里巴巴淘系技术 发布了文章 · 7月21日

Swift 5.3 又更新了什么新奇爽快的语法?

Swift 发展里程碑

Swift 在 WWDC14 正式发布到 2019,经过 5 年的不断迭代,这其中经历了标准库变动,语法的增减。首先使用 Swift 作为开发语言的开发者们都苦不堪言,戏称《Swift 从入门到重学》,几乎每一年 Swift 都会迎来比较大的改动,甚至 API 都发生了变化。

WWDC 19 苹果发布了 Swift 5.0,苹果终于宣布 Swift 的 ABI 稳定。这标志着 Swift 这门语言已经趋于稳定,在 2019 至 2020 的迭代中,Swift 5.2 也做到了模块稳定,之前的大修大改已经不会在出现了。

image.png

有意思的是,在 WWDC16 中有一页 PPT 写下了 Goals for Swift 3:

  • Develop an open community
  • Portability to new platforms
  • Get the fundamentals right
  • Optimize for awesomenss

如今已经 2020 年,再回头看这些目标,Swift 5.3 几乎完全实现了。Swift 可谓一直不忘初心,朝着认为正确的方向不断的努力。

( WWDC 2020精彩内容思否专栏:https://segmentfault.com/blog...  

本篇内容来自于阿里巴巴淘系技术部,无线开发工程师星志。
更多精彩内容可关注【淘系技术】公众号。)

语法的不断成熟

每年 WWDC 比较期待的一个点就是看看 Swift 又加了一些什么新奇爽快的语法。我先列举一下 Swift 5.3 新增的语法:

  • [SE-0249] KeyPath as Function
  • [SE-0279] Multiple trailing closure
  • [SE-0281] Type-based program entry point (@main))
  • [SE-0266] Synthesized comparable conformation for enum types
  • [SE-0269] Increased availability of implicit self in closure
  • [SE-0276] Multi-pattern catch clauses
  • [SE-0280] Enum cases as protocol witnesses
  • [SE-0267] Where clauses on contextually generic declarations
  • [SE-0270] Collection operations on noncontiguous elements
  • [SE-0264] Standard library preview package
  • [SE-0253] Callable values of user-defined nominal types
  • [SE-0263] String initializer with access to uninitialized storage

上面列举的 12 个语法改动,有兴趣的同学可以到 swift-evolution 去查看详细的内容。其中比较有意思的几个改动就是 [SE-279],[SE-281]和[SE-0269],我们来细细评味一下。

Design for SwiftUI

[SE-279] Multiple trailing closure 多重尾闭包这个新特性算是一个非常大的改动。这个特性的出现影响了 Swift 非常重要的地方,API 设计。先来几个官方的例子:

屏幕快照 2020-07-21 下午3.36.44.png

上面的代码中 2 的情况是经常出现的,尾闭包的含义就不够明确,以前最佳的方式应该为 3,但是两个闭包被套在一个小括号里,使得括号多重嵌套,可读性下降。为了解决这个问题,苹果使用了第 4 中方法--多重尾闭包。可以从代码看出可读性得到了很大的提升。

这一看似优雅的设计其实引入了很多语言的复杂度,有了这个特性你甚至可以写出类似下面的代码,看上去就像是创造了一个 if-else 语句,但其实它是一个函数。

屏幕快照 2020-07-21 下午3.49.07.png

这就对 SDK 的开发者提出了更高的要求,需要小心的使用这个特性来设计 API,防止这个特性被滥用导致代码的可读性下降,甚至造成歧义。苹果在 WWDC20 中也强调了这一点。

还有两个特性其实很简单,[SE-0281] 是 @main 来标记程序入口,[SE-0269] 是让开发者在特定的情况下不需要再写多余的 self.

苹果推出了这几个语言特性,就是为了让战略性的项目 SwiftUI 的 API 更加简洁明了。可以看下面的例子:

屏幕快照 2020-07-21 下午3.49.44.png

苹果也不是第一次为了 SwiftUI 改 Swift 的语法,[SE-0255] Implicit returns from single-expression functions 就是为了让 SwiftUI 的 body 不用写 return,强化 DSL 风格。

苹果为了 SwiftUI,推出了 functionBuilder 来实现 DSL 形式的代码;为了 SwiftUI,推出了许多让它更漂亮的语法特性;为了 SwiftUI,不惜为语言引入更多的复杂度。

下限低,上限高

Swift 的最初的设计方向就导致了它是一门下限很低上限很高,入门容易精通难,使用容易设计难的语言。它一系列的语法糖和语法设计,包括类型推断系统,都是让它成为十分亲民的语言,而它的一系列语法特性,让它在设计 API、SDK实现的时候其复杂程度也不亚于其他语言。

Swift is a general-purpose, multi-paradigm, compiled programming language developed by Apple Inc. for iOS, iPadOS, macOS, watchOS, tvOS, and Linux.

---- Wikipedia

维基百科的后半部分可能有些局限了,但是前半部分说明了它是一门多编程范式的语言,Swift 可以支持 面向对象编程(OOP),面向协议编程(OPP),声明式编程(DP),函数式编程(FP),泛型编程(GP)。

Objective-C 已经发展了这么多年,如此成熟,为什么现在苹果要开始抛开它?Objective-C 本来就是生于一个面向对象编程范式起飞的一年,与 C++ 一样为了拓展 C 命令式编程范式而诞生的语言。当时 C 语言虽然也可以实现 OOP,但是语法设计成为了限制。在当代计算机编程语言研究演进下,出现了很多编程范式的新理论,如函数式编程,元编程等等,同样 OC 可以通过它的方式来实现,但是语言的冗杂和 OOP 的设计已经不能更好的表达这些概念,就犹如纯 C 来表达OOP 一样。

苹果推出 Swift 就是为了摆脱 OC 的束缚,让它能更好的践行现代的编程理论,所以才会诞生出 SwiftUI,才会有 Combine、map/filter/reduce 等这些库和 API。类型推断和元编程的理论也让 Swift 在保留强类型的环境下还能保持如此简洁优雅,可读性强的代码。而这些是 OC 无法做到的。尝试使用 OC 对这些现代概念做表达的 SDK 都会显得十分冗杂。

现在 Swift 语法已经不会再大变,有如此现代、安全、稳定、富有想象力的语言,有什么理由不真香呢?

土壤已经肥沃

我们先通过下面的脑图感受一下 Swift 更迭到 5.3 已经取得的成就。

image.png

现在 Swift 生态环境已经自成一派,有一套完整的工具链保证开发,有更独立的标准库让它可以自由迁移,包管理让丰富了它的 SDK,同时还具有 Native 语言的各种优势。在这么多年的发展中,它的能力已经触及到了 AI、Server、Mobile Device、FaaS,强大的标准库让它甚至可以当脚本语言使用。

Swift 如今已经不再孤立无援,开源让 Swift 变得生机勃勃,合理优雅的设计和开放的态度让全球的开发者们都在不断的完善它。

在 Swift 的大生态中,包管理工具是最值得一说的。一门语言它的能力,取决于它是否有强有力的 SDK,还有就是获取他们的途径。基础的 Swift 的能力都由工具链和标准库提供,而强有力的 SDK 最好的方式就是通过包管理工具快速获取。Swift Package Manager 就是 Swift 的军械库。

Swift Package Manager

看一下 Swift Package Manager(SPM) 的发展历程,SPM 从 Swift 3.0 时就发布,当时只支持 Git 远端仓库,支持支源码发布。WWDC 19,Xcode 引入了一个新的架构 XCFramework,一个旨在能打包多个平台 framework 的文件结构。WWDC20 SPM 宣布正式支持发布二进制 framework。

WWDC20 SPM 走出的这一步标志着功能的完善。为什么这么说,因为在 iOS 届,解决了 Xcode 无包管理工具难题,让众多优秀的开源库能被快速获取的包管理工具 -- Cocoapods。在 SPM 出现之前,Cocoapods 的功能已经非常完善,打败了当时另外的一款包管理工具 Carthage。

Cocoapods 作为基于 Xcode 开发的第三方包管理工具,通过修改 Xcode 的工程信息来实现处理各个包的依赖问题。它支持依赖的二进制分发、源代码分发,基于 framework 良好的资源管理。现在许多公司的大型 App 也是用 Cocoapods 做模块化组件分离,通过二进制依赖的方式来提高打包速度。

然而比较可惜的是它工作流是脱离 Xcode 的,Podfile 更新等操作都是在工程之外。语言使用的是 Ruby,虽然使用了一些操作使 Podfile 变成了 DSL,但是对于开发者而言是有一定门槛的,特别是需要编辑发布 SDK 所使用的 podspec 时,对照文档,无代码提示的编写让写正确配置文件都成了难事。Cocoapods 还不得不设计出 podspec lint 来帮组开发者确认这个事情。

对于 Swift PM 这个亲儿子而言,就不存在这个问题,SPM 已经深入的集成到了 Xcode 中,所有的操作都可以利用 Xcode 完成。在编写 Swift Package 时,Xcode 现在已经具备将 Package.swift 作为工程项目打开,并且现在工程模板中已经包含了 Swift Package。强大的 Xcode 自动补全让编写 Package.swift 不再是一件难事。如果脱离 Xcode,利用 swift-lsp 结合现在热门的文本编辑器,如 VSCode 等都可以实现相应的功能。SPM 现在已经是独立于 Xcode 的存在,可以为 Swift 提供强有力的支持。

SPM 在功能层面已经不逊于 Cocoapods,在 WWDC20 时,SPM 已经支持以二进制库形式分发 Package,SPM 也可以管理包中的资源和本地化,基本的能力已经与 Cocoapods 差异不大,然而最关键的是,SPM 是纯 Swift ,开源,还有苹果官方支持的包管理工具。

新瓶酿酒酒更香

国外的不少 APP 已经迁移到了 Swift;三方开源库如 AFNetworking 已经用 Swift 重写为 Alamofire,Lottie 已经完全被 Swift 重写替代。苹果也推出了许多 Swift Only 的库。苹果也在利用 Swift 为 UIKit,GCD 等基础库不断提供更具有表现力的 API。

Uber 完成了迁移,收获了 Swift 极强的稳定性。Alamofire,SnapKit 用  Swift 重写,获得了更加具有表现力的 API,开发者更容易接受且喜爱。 Reactive 系列的编程风格在 Swift 上大放异彩。

机会与展望

现在 Swift 发展了这么多年,遍地开花,Objective-C 已经有在逐渐被废弃的趋势。现在很有可能都很难招到认真学习过 OC 的应届生了。

Swift 在集团内部的发展,还有很多的工作要做,这其中充满了挑战。我们也在积极探索 Swift 在手淘的落地,取得了 Swift 5.1 能模块在手淘中正确运行起来的阶段性成就。但是比较遗憾的是还有很多模块是无法让 Swift 正确跑起来的,以现在的工具链来说甚至源码依赖调试都无法做到。

但是这都是暂时的,现在时机已经成熟,Swift的语言特性,SPM,工具链,标准库都已经足够强大。未来,我们会尽快大力升级 Swift 的基建。让 Swift 的花在集团内开起。先定个小目标,希望 Swift 能成为集团 iOS 客户端开发的首选语言。

( WWDC 2020精彩内容思否专栏:https://segmentfault.com/blog...  

本篇内容来自于阿里巴巴淘系技术部,无线开发工程师星志。
更多精彩内容可关注【淘系技术】公众号。)

参考

  1. SwiftUI 背后那些事儿
  2. WWDC20 What's new in Swift
  3. WWDC19 What's new in Swift
  4. WWDC18 What's new in Swift
  5. WWDC17 What's new in Swift
  6. WWDC16 What's new in Swift)
  7. WWDC20 Swift packages: Resources and localization
  8. WWDC20 What's new in SwiftUI
  9. Swift 5 时代的机遇与挑战到底在哪里?
  10. Swift Evolution

淘宝基础平台团队正在进行社招招聘,岗位有iOS Android客户端开发工程师、欢迎 转岗推荐, 简历投递:junzhan.yzw@taobao.com

查看原文

赞 6 收藏 1 评论 0

阿里巴巴淘系技术 发布了文章 · 7月20日

Metal新特性:大幅度提升iOS端性能

前言

Metal 是一个和 OpenGL ES 类似的面向底层的图形编程接口,通过使用相关的 api 可以直接操作 GPU ,最早在 2014 年的 WWDC 的时候发布。Metal 是 iOS 平台独有的,意味着它不能像 OpenGL ES 那样支持跨平台,但是它能最大的挖掘苹果移动设备的 GPU 能力,进行复杂的运算,像 Unity 等游戏引擎都通过 Metal 对 3D 能力进行了优化, App Store 还有相应的运用 Metal 技术的游戏专题。

阿里巴巴淘系技术部的闲鱼团队是比较早在客户端侧选择Flutter方案的技术团队,当前的闲鱼工程里也是一个较为复杂的Native-Flutter混合工程。作为一个2C的应用,性能和用户体验一直是闲鱼技术团队在开发中比较关注的点。而Metal这样的直接操作GPU的底层接口无疑会给闲鱼技术团队突破性能瓶颈提供一些新的思路。

下面会详细阐述一下这次大会Metal相关的新特性,以及对于闲鱼技术和整个淘系技术来说,这些新特性带来了哪些技术启发与思考。

( WWDC 2020精彩内容思否专栏:https://segmentfault.com/blog...  

本篇内容来自于阿里巴巴淘系技术部,无线开发工程师岑彧。
更多精彩内容可关注【淘系技术】公众号。)

Metal相关新特性

1.Harness Apple GPUs with Metal

这一章其实主要介绍的是Apple GPU的在图形渲染上的原理和工作流,是一些比较底层的硬件原理。当我们使用Metal进行App或者是游戏的构建的时候,Metal会利用GPU的tile-based deferred rendering (TBDR)架构给应用和游戏带来非常可观的性能提升。这一章主要就是介绍GPU的的架构和能力,以及TBDR架构进行图像渲染的原理和流程。总之就是号召开发者们使用Metal来构建应用和游戏。因为这个session没有涉及到上层的软件开发,就不对视频的具体内容进行赘述了。详情可见:Harness Apple GPUs with Metal

2.Optimize Metal apps and games with GPU counters

这一章主要介绍了Xcode中的GPU性能分析工具Instrument,这个工具现在已经支持了GPU的性能分析。然后从多个方面分析了GPU的性能瓶颈,以及性能瓶颈出现时的优化点。总体来说就是通过性能分析工具来优化我们的App或者游戏,让整个画面更加流畅。整个章节主要分为五个部分:

1.总体介绍

这个环节主要是快速回顾了一下Apple的GPU的架构和渲染流程。然后因为很多渲染任务都需要在不同的硬件单元上进行,例如ALU和TPU。他们对不同的吞吐量有着不同的度量。有很多GPU的性能指标需要被考虑,所以推出了GPU性能计数器。这个计数器可能测量到GPU的利用率,过高和过低都会造成我们的渲染性能瓶颈。关于计数器的具体使用,参考官方的video效果会更好:Optimize Metal apps and games with GPU counters(6:37~9:57),主要使用了Instrument工具,关于工具的全面详细的使用可以参考WWDC19的session videoGetting Started with Instruments

2.性能瓶颈分析

这一章主要介绍了造成GPU性能瓶颈的各个方面以及它们的优化点。主要分为六个方面,如下图所示:

1.Arithmetic(运算能力)

GPU中通常通过ALU(Arithmetic Logic Unit)来处理各种运算,例如位操作,关系操作等。他是着色器核心的一部分。在这里一些复杂的操作或者是高精度的浮点运算都会造成一些性能瓶颈,所以给出以下建议来进行优化:

如上图所示,我们可以使用近似或者是查找表的方式来替换复杂的运算。此外,我们可以将全精度的浮点数替换为半精度的浮点数。尽量避免隐式转换,避免32位浮点数的输入。以及确保所有的着色器都使用Metal的“-ffast-math”来进行编译。

2.Texture Read and Write

GPU通过Texture Processing Unit来处理纹理的读写操作。当然在读写的过程中也会遇到一些性能瓶颈问题。这里从读和写两个部分分别来给出优化点:

1.Read

如上图所示,我们可以尝试使用mipmaps。此外,可以考虑更改过滤选项。例如,使用双线性代替三线性,降低像素大小。确保使用了纹理压缩,对Asset使用块压缩(如ASTC),对运行时生成的纹理使用无损纹理压缩。

2.Write

如上图所示,我们应该注意到像素的大小,以及每个像素中唯一MSAA样本的数量。此外,可以尝试一些优化一些逻辑写法。

3.Tile Memory Load and Store

图块内存是一组存储Thread Group和ImageBlock数据的高性能内存。当从ImageBlock或是Threadgroup读取或写入像素数据时,比如在使用Tile着色器时或者是计算分派时,可以访问到Tile内存。那当使用GPU性能计数器发现这个方面的性能瓶颈时,我们可以如下图所示进行优化。

考虑减少threadgroup的并行,或者是SIMD/Quadgroup操作。此外,确保将线程组的内存分配和访问对齐到16字节。最后,可以考虑重新排序内存访问模式。

4.Buffer Read and Write

在Metal中,缓冲区只被着色器核心访问。在这个地方发现了性能瓶颈。我们可以如下图所示进行优化:

可以更大力度的压缩打包数据,例如使用例如packed_half3这样小的类型。此外,可以尝试向量化加载和存储。例如使用SIMD类型。避免寄存器溢出,以及可以使用纹理来平衡工作负载。

5.GPU Last Level Cache

如果在这个方面,我们的GPU性能计数器显示一个过高的值。我们可以如下图这样优化:

如果纹理或者是缓存区也同样显示一个过高的值,我们可以把这个优化放到第一优先级。我们可以考虑减小工作集的大小。如果Shader正在使用Device Atomics,我们可以尝试重构我们的代码来使用Threadgroup Atomics。

6.Fragment Input Interpolation

分段输入插值。分段输入在渲染阶段由着色器核心进行插值。着色器核心有一个专用的分段输入插值器。这个是比较固定和高精度的功能。我们能优化的点不多,如下图所示:

尽可能的移除传递给分段着色器的顶点属性。

3.内存带宽

内存带宽也是影响我们GPU性能的一个重要因素。如果在GPU性能计数器的内存带宽模块看到一个很高的值。我们就应该如下图所示来进行优化:

如果纹理和缓存区也同样显示比较高的值,那优化优先级应该排到第一位。优化方案也是较少Working Set的大小。此外,我们应该只加载当前渲染过程需要的数据,只存储未来渲染过程需要的数据。然后就是确保使用纹理压缩。

4.Occupancy

如果我们看到整体利用率比较低,这意味着Shader可能已经耗尽了一些内部资源,比如tile或者threadgroup内存。也可能是线程完成执行的速度比GPU创建新线程的速度快。

5.避免重复绘制

我们通过GPU计数器可以统计到重复绘制的区域,我们应该高校使用HSR来避免这样的重绘。我们可以如图所示的顺序来进行绘制。

3.Build GPU binaries with Metal

这一章主要给开发者们介绍了一种使用Metal的编程工作流,可以通过优化Metal的渲染编译模型来增强渲染管线,这个优化可以在应用程序启动,特别是首次启动时大大减少PSO(管线状态对象)的加载时间。可以让我们的图形渲染更加的高效。整个章节主要分为四个部分:

1.Metal的Shader编译模型概述

众所周知,Metal Shading Language是Apple为开发者提供的Shader编程语言,Metal会将编程语言编译成为一个叫做AIR的中间产物,然后AIR会在设备上进一步编译,生成每个GPU所需的特定的机器码。整个过程如下图所示:

上述过程在每个管线的生命周期中都会发生,当前Apple为了加速管线的重新编译和重新创建流程,会缓存一些Metal的方法变体,但是这个过程还是会造成屏幕的加载耗时过长。而且在当前的这个编译模型中,应用程序不能在不同的PSO(管线状态对象)中重用之前生成的机器码子程序。
所以我们需要一种方法来减少这个整个管线编译(即源代码->AIR->GPU二进制代码)的时间成本,还需要一种机制来支持不同PSO之间共享子程序和方法,这样就不需要将相同的代码多次编译或者是多次加载到内存中。这样开发者们就可以使用这套工具来优化App首次的启动体验。

2.Metal二进制文件介绍

Metal二进制文件就是解决上述需求的方法之一,现在开发者们可以直接使用Metal为二进制文件来控制PSO的缓存。开发者可以收集已编译的PSO,然后将它们存储到设备中,甚至可以分发到其他兼容的设备中(同样的GPU和同样的操作系统),这种二进制文件可以看做一种Asset。下面是一些例程和示意图:

屏幕快照 2020-07-20 上午9.53.14.png

屏幕快照 2020-07-20 上午9.53.53.png

屏幕快照 2020-07-20 上午9.53.53.png

屏幕快照 2020-07-20 上午9.54.31.png

总的来说就是这个Metal二进制文件可以提供开发者手动管理管线缓存的方法,这样就可以从一个设备中获取这些文件并部署到其他兼容的设备上,在iOS环境下,极大地减少了第一次安装游戏或应用以及设备重启后的管道创建时间。可以优化应用的首次启动体验和冷启动体验。

3.Metal对动态库的支持

动态库将允许开发者编写可重用的库代码,却可以减少重新编译程序的时间和内存成本,这个特性将会允许开发者将计算着色器和程序库动态链接。而且和二进制文件一样,动态库也是可序列化和可转移的。这也是解决上述需求的方案之一。
在PSO生成的时候,每个应用程序都需要为程序library生成机器码,而且使用相同的程序库编译多个管线会导致生成重复的机器码。由于大量的编译和内存的增加,这个可能会导致更长的管线加载时间。而动态库就可以解决这个问题。
Metal Dynamic Library允许开发者以机器码的形式动态链接,加载和共享工具方法。代码可以在多个计算管线中重用,消除了重复编译和多个相同子程序的存储。而且这个 MTLDynamicLibrary是可序列化的,可以作为应用程序的Asset使用。MTLDynamicLibrary其实就是多个计算管线调用的导出方法的集合。
大致的工作流程如下:我们首先创建一个MTLLibrary作为我们指定的动态库,这个可以将我们的metal代码编译为AIR。然后我们调用方法makeDynamicLibrary,这个方法需要指定一个唯一的installname,在管线创建时,linker将会使用这个名字来加载动态库。这个方法可以将我们的动态库编译成为机器码。这就完成了动态库的创建。
对于动态库的使用来说:通过设置MTLCompileOptions里的libraries参数,就可以完成动态库的加载和使用了。代码如下:

屏幕快照 2020-07-20 上午10.04.56.png

4.开发工具介绍

这个部分主要介绍了构建Metal二进制文件和构建动态库的具体工具和方法。以视频的形式可能会更好的表现,详情可见:Build GPU binaries with Metal (从22:51开始)

4.Debug GPU-side errors in Metal

这一章主要介绍的是GPU侧的bug,当前如果我们的应用程序出现了GPU侧的bug,他的错误日志常常都不能让开发者很直观的定位到错误的代码范围和调用栈。所以在最新的Xcode中,增强了关于GPU侧的debug机制。可以像在代码侧发成的错误一样不但能定位到错误原因,还有错误的调用堆栈和各种信息都可以详细的查看到。让开发者能更好的修复代码造成的GPU侧的渲染错误。

1.Enhanced Command Buffer Errors

这是当前的错误日志上报,我们可以看到GPU侧的错误日志不像Api的错误日志一样可以让开发者很快的定位到错误原因和错误的代码位置。

而最新的Metal debugging工具就增强了这方面的能力,让Shader的code也可以像Api代码一样提供错误定位和分类能力。

我们通过以下代码便可以启用增强版的commandbuffer错误机制

屏幕快照 2020-07-20 上午10.05.27.png

错误一共有五种状态:

我们也可以通过以下代码来打印error:

屏幕快照 2020-07-20 上午10.06.00.png

开发者可以在开发时和测试时启用优化版的错误机制

2.Shader Validation

如上图所示,这个功能可以在GPU侧发生渲染错误时自动定位和catch到错误并定位到代码,以及获取回溯栈帧。

我们可以在Xcode中按照以下流程来开启这个功能:

1.开启Metal中的两个Validation选项

2.开启issue自动断点开关并配置类型和分类等选项

Video中用了一个demo来展示整个工作流,具体参见Debug GPU-side errors in Metal(11:25~14:45)大致流程如下图所示:

这是一个Demo应用程序,很明显它在渲染上出现了一些异常,但是因为是GPU侧的问题,所以开发者很难定位。但是通过上述的工作流开启Shader Validation之后。

Xcode会自动断点到发生异常的地方,并展示出异常信息,这样就可以极大的提升开发者的错误修复效率。

5.Gain insights into your Metal app with Xcode 12

这一章主要讲的是Xcode12给Metal App提供了更多调试和分析的新工具。大致如下图所示:

主要分为两个部分:

1.Metal Debugger

这个工具可以让开发者在App运行时,获取到想分析和调试的任何一帧,然后再进入Xcode提供的各种分析界面,总体情况,依赖情况,内存,带宽,GPU,Shader等各种具体的界面来对这一帧进行更加详细的分析和调试。整个过程使用视频的方式可能会更加高效,所以这里不会进行详细的赘述和分析。详情可以参见Gain insights into your Metal app with Xcode 12

2.Metal System Trace

整个工具跟之前提到过的Debugger相比,他的功能主要是让开发者可以随着时间的推移来捕获应用程序的各种信息和特征,可以让开发者很好的调试一些例如终端,帧丢失,内存泄漏等问题。而Debugger主要是对某一帧进行调试和分析。
他提供了一个叫做编码时间线的工具,可以让开发者查看到GPU在应用运行中的运行各种命令缓冲的情况。然后提供了一个叫做着色器时间线的工具,可以让开发者查看到各种着色器在代码运行期间运行的过程。然后还有GPU计数器的工具,这个工具我们在前文进行了详细的分析,主要是用于解决GPU的绘制性能问题的工具。然后最后一个工具就是内存分配跟踪工具,可以让开发者查看到应用程序运行过程中各种内存的分配和释放,可以帮助开发者解决内存泄漏问题或者是降低应用内存占用。

技术启发与思考

WWDC 20关于Metal的Session中,比较重要的就是官方提供了很多可供开发者进行GPU级别的调试工具以及性能分析工具。给比较成熟庞大而复杂的工程突破性能瓶颈,提供更加优秀的用户体验提供了一些思路。

闲鱼作为一个电商类App,随着功能和增多和以及工程的复杂化,在所难免的会遇到性能瓶颈,而闲鱼团队当前面对挑战的方式是从工程级别来进行优化。从Flutter的角度来看,WWDC 20 对于Metal的调试工具和性能分析工具的完善,无疑提供了更多的优化思路。这为未来运行在iOS上的应用的调优和突破性能瓶颈带来了新的思路和可能性。

对于跨平台框架,Apple有自家的SwiftUI,这也是此次大会的重点项目。不过无论是Flutter,还是SwiftUI,大家最后对应用的性能瓶颈突破和优化一定是殊途同归的,也就是深入到GPU级别来进行开发和调试以及性能分析。对于未来的客户端开发人员,理解GPU和进行GPU级别的编程肯定是不可或缺的技能点之一。

( WWDC 2020精彩内容思否专栏:https://segmentfault.com/blog...  

本篇内容来自于阿里巴巴淘系技术部,无线开发工程师岑彧。
更多精彩内容可关注【淘系技术】公众号。)

查看原文

赞 4 收藏 1 评论 0

阿里巴巴淘系技术 赞了文章 · 7月16日

Twitter 帐户遭到比特币骗局攻击,比尔盖茨、马斯克、奥巴马等账号悉数被窃取

clipboard.png
技术编辑:徐九丨发自 思否编辑部

“在接下来的 30 分钟内,只要你往这个数字钱包地址打钱,我就返给你双倍金额。大家都让我回报社会,现在时候到了!”

今天凌晨,比尔盖茨、埃隆·马斯克、杰夫·贝佐斯、巴拉克·奥巴马、乔·拜登、坎耶·韦斯特、苹果官方账号等等大佬的推特,不约而同的发了类似内容的 Twitter,真的如推特内容所言,早起的鸟儿有虫吃?大佬们要回馈社会了么?

答案当然是否定的,这是一起黑客入侵事件,背后是一场比特币骗局。

Twitter 安全漏洞

这些推文内容都是由黑客在窃取了目标账号之后,批量发布的。业内安全专家表示,这次的事件问题是由 Twitter 服务的安全漏洞引起的,而不是由目标人群自身的风险行为导致。

Facebook 前首席安全官亚历克斯·斯塔莫斯说,研究人员目前普遍认可的一个理论是,黑客已经获得了该系统的加密密钥,从而使他们能够从本质上窃取授予个人帐户访问权限的“令牌”。他认为所有理论都表明,黑客是进入了 Twitter 的系统,而不是窃取单个用户的密码。

这些推文在发布几分钟后便被删除,Twitter 官方也表示采取了特殊的设置,限制了很多蓝V账号的发推权限。但据社交媒体显示,大部分账号仍然被发布推文,并且无法重置账号密码。

根据公开可用的区块链记录,目标账户推文中显示的链接已经收到了数百笔捐款,总计超过 100,000 美元(80,000 英镑)。

网络安全公司 CrowdStrike 的联合创始人德米特里·阿尔佩罗维奇在媒体采访中表示:“这似乎是社交媒体平台上最糟糕的一次黑客攻击。”

比尔·盖茨的发言人也表示:“这似乎是 Twitter 面临的更大问题的一部分。”

Twitter 首席执行官杰克·多尔西则表示,“这对我们来说是「艰难的一天」。我们都感到这件事发生的可怕。我们正在诊断,并会在我们对发生的事情有更全面的了解后分享我们所能提供的一切。”

黑客利用 Twitter 控制面板盗取账户

据两位接近地下黑客社区的消息人士称,黑客是利用了 Twitter 员工与用户账户进行交互的控制面板盗取了这些账户并发布了诈骗信息。

witter 员工与用户账户进行交互的控制面板

目前,Twitter 已经删除了流传出去的控制面板截图,并以内容违反公司规则的原因封禁了传播这张图片的用户。

code面板对被​​黑帐户之一BINANCE的访问/code

知名人士 Twitter 账户被盗取也引起了美国政府方面的重视,事件发生仅一小时后,共和党参议员 Josh Hawley 就致信 Twitter 首席执行官 Jack Dorsey 询问黑客攻击是否影响了美国总统特朗普的账户,并要求 Twitter 提供此次黑客攻击事件的更多信息,包括黑客攻击的方式、信息泄露的用户数量等。

对此,Jack Dorsey 表示,“正在评估黑客入侵情况,将在可能的情况下公布更多信息。”

此前也发生过类似的事件

“翻倍返还比特币”的骗局操作,多年来 Twitter 上时有发生,但类似这次大量公众人物账号被劫持的事件是前所未有的。

去年,Twitter 首席执行官杰克·多尔西(Jack Dorsey)的帐户就曾被黑客入侵,但该公司表示已修复了使他的帐户容易受到攻击的漏洞。

此次众多不同用户同时遭到入侵的事实表明,Twitter 平台本身可能仍然存在很大的问题。

万幸的是这次黑客并没有利用他们的访问权瞄准任何重要的机构或基础设施,而是索要比特币。但此次事件表明,他们有能力造成更大的破坏。

据业内专家表示,目前没有证据表明是谁发动了袭击。但根据美国情报机构进行的初步评估,认为这很可能是单个黑客的工作,而不是某个国家的政治行为。

clipboard.png

查看原文

赞 4 收藏 0 评论 0

阿里巴巴淘系技术 发布了文章 · 7月16日

iOS14 隐私适配及部分解决方案

背景

Trust is built over time, and starting out by showing respect for users data by asking for access to as little as possible is a great first step.
  • 在刚刚结束的线上 WWDC 2020 发布会上苹果向我们展示了新的 iOS14 系统。
  • iOS14 的适配,很重要的一环就集中在用户隐私和安全方面。在 iOS13 及以前,当用户首次访问应用程序时,会被要求开放大量权限,比如相册、定位、联系人,实际上该应用可能仅仅需要一个选择图片功能,却被要求开放整个照片库的权限,这确实是不合理的。对于相册,在 iOS14 中引入了 “Limited Photos Library” 的概念,用户可以授予应用访问其一部分的照片,对于应用来说,仅能读取到用户选择让应用来读取的照片,让我们看到了 Apple 对于用户隐私的尊重。
  • 这仅仅是一部分,在 iOS14 中,可以看到诸多类似的保护用户隐私的措施,也需要我们升级适配。
  • 最近在调研 iOS14 的适配方案,本文主要分享一下 iOS14 上对于隐私授权的变更和部分适配方案,欢迎补充指正。

( WWDC 2020精彩内容思否专栏:https://segmentfault.com/blog...  

本篇内容来自于阿里巴巴淘系技术部,无线开发工程师岚遥。
更多精彩内容可关注【淘系技术】公众号。)

适配点

相册

  • iOS14 新增了“Limited Photo Library Access” 模式,在授权弹窗中增加了 Select Photo 选项。用户可以在 App 请求调用相册时选择部分照片让 App 读取。从 App 的视角来看,你的相册里就只有这几张照片,App 无法得知其它照片的存在。
  • iOS14 中当用户选择“PHAuthorizationStatusLimited” 时,如果未进行适配,有可能会在每次触发相册功能时都进行弹窗询问用户是否需要修改照片权限。
  • 对于这种情况可通过在 Info.plist 中设置 “PHPhotoLibraryPreventAutomaticLimitedAccessAlert” 的值为 YES  来阻止该弹窗反复弹出,并且可通过下面这个 API 来主动控制何时弹出 PHPickerViewController 进行照片选择。

屏幕快照 2020-07-16 下午2.42.21.png

  • 在 iOS14 中官方推荐使用  PHPicker 来替代原 API 进行图片选择。PHPicker 为独立进程,会在视图最顶层进行展示,应用内无法对其进行截图也无法直接访问到其内的数据。
  • UIImagePickerController  -> PHPickerViewController, UIImagePickerViewController 功能受限,每次只能选择一张图片,将逐渐被废弃。
  • PHPicker 支持多选,支持搜索,支持按 image,video,livePhotos 等进行选择。
  • 新API及迁移demo:

屏幕快照 2020-07-16 下午2.43.54.png
屏幕快照 2020-07-16 下午2.44.06.png

  • 需要注意的是,在 limit Photo 模式下,AssetsLibrary 访问相册会失败;在 writeOnly 模式下,AssetLibrary 也会有显示问题。建议还在使用 AssetsLibrary 的同学尽快迁移到新 API。
  • 授权相关:旧 API 废弃,增加 PHAccessLevel 参数。如果再使用以前的API来获取权限状态,PHAuthorizationStatusLimited 状态下也会返回 PHAuthorizationStatusAuthorized

屏幕快照 2020-07-16 下午2.45.53.png
屏幕快照 2020-07-16 下午2.46.01.png

定位

  • 在 iOS13 及以前,App 请求用户定位授权时为如下形态:一旦用户同意应用获取定位信息,当前应用就可以获取到用户的精确定位。
  • iOS14 新增用户大致位置选项可供用户选择,原因是大多数 App 实际上并不需要获取用户到用户最准确的定位信息。iOS14 授权弹窗新增的 Precise的开关默认会选中精确位置。用户通过这个开关可以进行更改,当把这个值设为 On 时,地图上会显示精确位置;切换为Off时,将显示用户的大致位置。
  • 对于对用户位置敏感度不高的 App 来说,这个似乎无影响,但是对于强依赖精确位置的 App 适配工作就显得非常重要了。可以通过用户在 “隐私设置” 中设置来开启精确定位,但是可能用户宁可放弃使用这个应用也不愿意开启。这个时候,iOS14 在 CLLocationManager 新增两个方法可用于向用户申请临时开启一次精确位置权限。
    使用方式也很简单,需要首先在 Info.plist 中配置“NSLocationTemporaryUsageDescriptionDictionary”字典中需要配置 key 和 value 表明使用位置的原因,以及具体的描述。
    在本例中,key 即为获取用户权限时传的 "purposeKey",最终呈现给用户的就是左图,右图为当App主动关闭精确定位权限申请。
  • 对于地理位置不敏感的App 来说,iOS14 也可以通过直接在 info.plist 中添加 NSLocationDefaultAccuracyReduced  为 true 默认请求大概位置。
  • 这样设置之后,即使用户想要为该 App 开启精确定位权限,也无法开启。
  • 也可以直接通过API来根据不同的需求设置不同的定位精确度。
  • 需要注意的是,当 App 在 Background 模式下,如果并未获得精确位置授权,那么 Beacon 及其他位置敏感功能都将受到限制。

Local Network

  • iOS14 当 App 要使用 Bonjour 服务时或者访问本地局域网,使用 mDNS 服务等,都需要授权,开发者需要在 Info.plist 中详细描述使用的为哪种服务以及用途。下图为需要无需申请权限与需要授权的服务:
  • 在 "隐私设置" 中也可以查看和修改具体有哪些 App 正在使用 LocalNetwork  
  • 如果应用中需要使用 LocalNetwork 需要在 Info.plist 中配置两个选项,详细描述为什么需要使用该权限,以及需要列出具体使用 LocalNetwork 的服务列表。
  • 对于使用了下列包含 Bonjour 的 framework,都需要更新描述

Wi-Fi Address

  • iOS8 - iOS13 ,用户在不同的网络间切换和接入时,mac 地址都不会改变,这也就使得网络运营商还是可以通过 mac 地址对用户进行匹配和用户信息收集,生成完整的用户信息。iOS14 提供 Wifi 加密服务,每次接入不同的 WiFi 使用的 mac 地址都不同。每过 24 小时,mac 地址还会更新一次。需要关注是否有使用用户网络 mac 地址的服务。
  • 下图为 iOS13 及之前用户接入网络时 mac 地址并不会进行改变
  • 下图为 iOS14 用户接入 Wi-Fi 时 mac 地址的变化情况
  • 并且用户也可以自行选择是否开启 private Wi-Fi address

剪切板

  • 在 iOS14 中,读取用户剪切板的数据会弹出提示。
  • 弹出提示的原因是使用 UIPasteboard 访问用户数据,访问以下数据都会弹出 toast 提示。
  • 兼容方案:如果应用访问剪切板仅仅用于判断是否为URL格式,则 iOS14 新增了两个 API 可以用于规避该提示。如果应用想直接访问剪切板的数据,暂时可能无法做到规避该提示。 iOS14 新增两种 UIPasteboardDetectionPattern。
  • 上面的两个 API 可用于规避提示,但只能用于判断剪切板中是否有 URL,并不是真正的访问剪贴板数据,也拿不到剪切板的真实数据。下面两个 API 可以获得具体的 URL 信息,但是会触发剪切板提示。并且实测当用户剪切板中包含多个 URL 时只会返回第一个。
  • 使用示例

屏幕快照 2020-07-16 下午2.47.30.png

相机和麦克风

  • iOS14 中 App 使用相机和麦克风时会有图标提示以及绿点和黄点提示,并且会显示当前是哪个 App 在使用此功能。我们无法控制是否显示该提示。
  • 会触发录音小黄点的代码示例:

屏幕快照 2020-07-16 下午2.48.07.png

  • 触发相机小绿点的代码示例:

屏幕快照 2020-07-16 下午2.48.14.png

IDFA

  • IDFA 全称为 Identity for Advertisers ,即广告标识符。用来标记用户,目前最广泛的用途是用于投放广告、个性化推荐等。
  • 在 iOS13 及以前,系统会默认为用户开启允许追踪设置,我们可以简单的通过代码来获取到用户的 IDFA 标识符。

屏幕快照 2020-07-16 下午2.49.28.png

  • 但是在 iOS14 中,这个判断用户是否允许被追踪的方法已经废弃。
  • iOS14 中,系统会默认为用户关闭广告追踪权限。
  • 对于这种情况,我们需要去请求用户权限。首先需要在 Info.plist 中配置" NSUserTrackingUsageDescription " 及描述文案,接着使用 AppTrackingTransparency 框架中的 ATTrackingManager 中的 requestTrackingAuthorizationWithCompletionHandler 请求用户权限,在用户授权后再去访问 IDFA 才能够获取到正确信息。

屏幕快照 2020-07-16 下午2.49.40.png

上传 AppStore

  • 更加严格的隐私审核,可以让用户在下载 App 之前就知道此 App 将会需要哪些权限。目前苹果商店要求所有应用在上架时都必须提供一份隐私政策。如果引入了第三方收集用户信息等SDK,都需要向苹果说明是这些信息的用途。

总结

  • 对于这次 iOS14 的隐私权限大升级和新尝试,体现了苹果对于用户隐私的尊重。
  • 从用户角度来说,近年来越来越精准的广告投放让我们越来越感觉自己被”监视“着,此次升级后,我们有了更多保护自己隐私的方式以及避免广告骚扰的方法,苹果此举无疑会加大我们对其的好感度和信任感。
  • 但从另一个角度来说,对于 IDFA 的限制,可能会导致之前许多依靠广告投放收入的免费 App 难以继续维持生计,也可能也会导致免费 App 的数量有所降低。从开发者的角度来说,除了对 iOS14 隐私升级的积极适配外,也让我们感受到了 iOS14 中对于用户隐私的重视无疑会提高获取用户行为信息的成本。
  • 冲击最大的应该就是广告行业,对于目前的推荐算法和用户拉新都会受到影响,如何在充分尊重用户隐私的前提下进行广告的精准投放对于开发者和广告商来说都是一个不小的机遇和挑战。

参考资料

  • WWDC 2020 Apple Developer
  • Developer Documentation

广告

欢迎大家加入手淘客户端的小程序与跨平台技术部!我们是支撑小程序、小游戏、Flutter 等跨平台技术的核心团队,有技术广度和也有技术深度,我们需要 iOS、Android、C++、Flutter、Canvas、游戏引擎、WebGL 等各方面的人才。如果你善于学习,这是一个很好的接触跨领域知识的机会。如果你是个对技术有追求对小伙伴,请别犹豫,立刻联系我!lanya.sly@alibaba-inc.com

更多有关手淘的技术内容分享敬请关注VX公众号【淘系技术】

查看原文

赞 12 收藏 3 评论 0