【百川云栖分享】鬼道:手机淘宝 H5 和 Weex 容器的构建实践-阿里云开发者社区

开发者社区> 阿里百川> 正文

【百川云栖分享】鬼道:手机淘宝 H5 和 Weex 容器的构建实践

简介:

【2016杭州·云栖大会】阿里百川在“淘宝移动技术实践&开放”专场演讲中,分别邀请了来自淘宝移动平台基础平台部负责人吴志华(花名:天施)和阿里百川负责人斯登宇(花名:承渊)等嘉宾分别做了精彩演讲。以下是鬼道的演讲实录:


徐凯(鬼道)阿里巴巴高级技术专家:我们就开始说一下淘宝的H5和Weex容器,现在我的团队是在同时做这两个容器,所以就由我来说。


   简单地介绍一下目前在这样一个团队,之前做过前端的架构,也做过客户端,然后再往前也做过一些SDK。


   做H5容器,这张图在座的很多同学,无论是前端的同学,或是做网络的同学,或是和浏览器相关的同学都做过这张图,从这张图可以看到一个浏览器,不限于浏览器,包括像Weex这样的容器,这张图都是有参考意义的。与客户端进行交互,或在客户端上加载的页面,它会经历一些过程,有些过程比较关心,有些过程不太关心,关心的主要是箭头指向的这几个过程,第一步要考虑到资源的提前加载,这个加载是资源第一次访问之前就已经出现在客户端上,这系预加载。第二是DNS,这在移动端上有一系列的优化,刚才孤星也提到了一部分。第三是TCP,TCP优化再往下是SPDY、渲染层和交互层,大家可以看到整个做H5容器到现在做Weex容器,它其实是一脉相承的,很多技术上,比如说我们今年的双11上相当多的技术其实是直接我们做H5容器时代就继承过来的。


   我们看从时间大的区分上来看有三年:第一年,2014年主要做Weex容器的API,到现在内部大概是在200个API左右,各类业务的API,包括扩充操作系统的API,透出到H5这一端。另外的事情是平台化,包括页面的管理等;到2015年,下载时这一块做得比较多一点,包括预加载,还包括HTTP-DNS、SPDY;到了2016年,我们着重在渲染的层面去做,渲染的层面在4月份,应该是去年的11月,我也分享过一些渲染的方案,到今年的年初我们其实整体已经转向了Weex这一套方案。


   那今天的主要两块就是H5和Weex容器。


   第一块是预加载,去年双11的一个数据,从这个数据来看,它还是H5页面,用了预加载和不用预加载的效果,它有一个秒开的站点。


   从H5的整体实现有一个分支判断,有没有本地文件命中。


   从这张图展开来看的话,大一些,只不过上半部分的虚线框是客户端部分可以分为资源的初始化、资源的拦截规则以及资源的更新规则。在服务端下有几朵云,因为是预加载,它会有一个资源打包的概念,这些包会在CDN上,一些配置也会扔在CDN上,那左下角有一个发布平台,这样一个平台其实就是维护这样一个预加载包的权限管理、增删改查、发布一些细碎的参数的控制。


   我们看其应用范围,我个人是手机淘宝,这个产品是是诞生于手机淘宝,但用这样一个技术是遍布整个集团的,我看最大的淘宝还不到一半,其他的几个比较大的一些DU,其实也是比较大的规模在用,这些数据是两个多月前的数据,现在还会再多一些。


   那我们看这样一个预加载到底有没有效果,从图里面有四个数据,第一个数据,刚好找到一定的业务,它之前没有加载,然后这个图有一个明显的波峰是因为之前用了,中间有一段时间,因为业务关了,到某一个时间点又重新启动预加载,能够看到一个明显的峰,一个断崖式的下降,这是一个整体的趋势。


   到第二个是数据里有一个0.01和0.99,这说的是我们这个业务或这个页面上所有的资源在客户端中的这样一个分布的比例。99%是预加载,我们看到预加载的这个加载情况,能够岔开两个以上。这是第三个数据。第四个数据,按照各种网络类型展开来看的话,每一种网络类型下的预加载和非预加载的整体的加载时间是在2倍及2倍以上。


   这是单张页面资源的加载情况,我们可以看到,我用红线框标出的大概都是在1毫秒或10毫秒之内,这是本地的才能做到的。没有标的是几百毫秒,甚至更高的,这是做网络的。


   我抽了一个最简单的页面,大家可以看一下效果,这是第一个,当我们这张页面如果做一张预加载,没有大家想象中的容易,到平台上点一个按钮,H5页面的首屏资源要确保在预加载的资源中,这一张页面知道它是发一个请求,发一条日志,但这条日志显然拖慢了整个页面的加载速度。


   第二,当我们把这个请求干掉之后,几乎完全看不到它的状态。


   这是Bad Casc,也做了预加载,打包在预加载包里,整个预加载效果是没有什么明显的改变的,是完全没有改变的,这是做预加载过程当中的一个小心得。


   后面的几张图可以看到预加载的系统型的指标,在2015年初统计一下,因为预加载说到底是一种缓存,那肯定有一个本地命中率的概念,本地命中率,我们当时到2015年初,其实大概做了一天的话,80%(红色部分,已改进),到2015年底,这是双11当天的数据,这张数据大家可能是看到到,这个数据比较典型的是在双11当天下午的一点半左右,我们做了一个发布,图里面的没掉色的话,黄色和橙色部分有一个明显的交替,是因为发了一个新的包,在1分钟之内超过的70%,到1个小时的整体更新率过了90%了,这个数据算是偏好的,因为在双11当天,相信大家的网络会相对好一些,在家或在公司的网络环境会好一些。平常的话,放在一天性也是在90%以上,到最近的数据。


   我们可以稍微提一下,为什么会关心这个数据?因为这个资源包提升了加载速度,但必然拉慢了效果。以前发一个H5页面,1分钟之内就可以百分之百生效了,但现在发一个包,这个包要是服务端推送到客户端,这个下载的过程有一个推送的过程,所以它必然拉慢你的更新速度,所以我们非常在意,也非常地去推动这个预加载的到达率,即更新的及时性,其实有一个更直观的推动指标,刚才是不区分在线和离线设备的,在线设备是说所有和我服务器连通的这个设备中,我能不能尽快地让它接收到这个包的消息,服务端一发送客户端能够立刻收到通知,并快速地下载下来,这会一个工作,从数据来看,它应该是3分钟的到达率,过了86%,到10分钟是98%以上,这个也相当程度取决于刚才孤星同学讲的推送机制,ORANGE的机制,可以快速、高可靠地将服务的信息推送到客户端,所以推送的通道走的有相当大的保障。下载的话,我们也做了一些优化。


   另外是网络这方面的优化,这一块的优化,其实从最底层来说,其实也不复杂,无非就是在IOS上,系统用URL Protoccol为(音)去做拦截,我们还做了安卓的UC异步网络接口,将异步的网络接口透出来,然后我们去做网络拦截。再往下的话我们用了阿里的HTTP-DNS,让DNS的效力更高,再往下的走的是SPDY,将整个网络的长连,包括网络的及时性,从我们角度而言是及时性。


   这些大家都是可以需查的。


   从前端优化而言,服务端要做拦截,客户端配合SPDY做一个域名收敛,在首屏上部分把所有资源做一个请求结果,做到预加载的话,这些页面的效果未必会好,所以这两点我们觉得我们做过的所有优化中效果对明显的。比如像域名收敛,收敛前有这么多域名,我们收敛的域名大概是这么多,粗略估计在20个以上,最后收敛的应该是控制在2、3个。

   下一部分是Weex,其实我们做Weex,大家也看过很多不同的观点,就我们的观点是,首先Native开发是有痛点的,这个痛点一方面是在平台,就是IOS、安卓的产品,大家都幻想做跨平台的开发,你说这个是幻想也好,或是说这是一种追求也好,但实际上这对我们来说仍然是很重要的一件事情。


   第二个是的大规模的集成,大家也听到刚才玄黎给大家介绍我们用多大的人力、物力最终才逐步地将几百人同时开发的这样一个大的环境才最终地给它搞定,我相信在关于相当多的公司,你们漟同样的坑。


   第三是从三端降到最终的一端开发,在丰火讲到如何用Weex提升整体的开发效率,这是关于视频的。


   当然,Web开发也有痛点,接触过H5,和H5的同事聊过的,相信都能够看到这个痛点,首先它被诟病最多的肯定是体验,体验我们如果再细分的话我觉得首先是加载的体验,这一点大家可以稍微想象一下,Native是没有所谓的代码,业务逻辑代码要从服务端去加载的,但H5作为这种开发模式或Web开发模式本身而言是天然的,如果放在手机端的话,反而成为一种负担,尤其在网络和设备的能力还没有达到PC这样相当高的条件的情况下,这本来是天然的属性变成了一个天然的屏障和瓶颈。


   第二个的话,前面是加载,那第二点就是运行期的一些性能,包括滚动不是那么流畅,动画流畅性也没有Native那么高,这是大家最直观的感受,认为Weex无法将这些做好,很难将产品专向H5,或用H5仅仅做一个圈子里的简单的产品的推广或简单的活动,大家没有信心将H5做更复杂的应用,现在Weex想要解决这两个方面的痛点,能否形成这样一套新方案?在这样一个新方案下,既然是解决痛点,就将对方的优点融入进去。


   Weex做得很简单,在开发端用的是Weex的技术,用的是HTML/CSS/JS=NativeUI,经过Weex的转换,我们将输入HTML/CSS/JS,最终是等于NativeUI。


   最顶上是NativeUI,就是这“三大件”,追歼是Virtual Dom,这样一个数据结构,从这个角度而言它这样一个结构,它就是一棵树,是一棵树的话,每棵树,本身是一个节点,上面带了信息,还有结构信息。到了下一层就是IOS引擎、安卓引擎,甚至在Weex上也做了引擎。大家可以这么想,我写了一个Weex的页面,其实你写的是一个我们认为是Weex的特殊的语言,但对于你们来说,它可以同时渲染到IOS一端、安卓一端、H5一端,在我们来看H5也是独立的一端。


   上一张图自然地演化到这一张图是开发最简化的一个流程,从左上角写这样的一个Weex File,转到JS Bundle,推到服务器上,上面部分是在客户端完成的,底下是客户端,在客户端上首先是JSFramework,为何会跑到这上面?两个原因:它比较大;第二,我们希望在客户端上做初始化方案。相信大家用过其他的动态化方案是有这样的体验。


   再往下可以看到这条链路,这条网路往下走在IOS和安卓这两端,会通过JSCore/V8,再往下是JS/Native Bridge。只有两个入口,一个是CollJs,一个是CallNative。再旁边是Weex的RenderEngine,这是三端,如何保证真正系做到三端一致?不是一系列能够搞定的,要真正地将底层的三个作为独立的对象,并且是平等对待的,这样才能保证最终出来的组件是在三端上的,这三端占比比较大,包括未来整个加入到Weex File以及移动行业的。


   我们最终下发的是JS Bundle,在开发期就能够解决的问题,不需要放在运行期去转换 ,目标是提升运行期的一些性能。


   那我们再看,讲整个渲染流程抽出来看的话,会看到输入的是这样一个Virtual Dom,这样扔给Native,首先会创建一个Native的树状结构,这只是一个内存中的结构,然后将样式复制上去会创建出真正的Native Vieg,再是Event,再是Css Layout,再是IOS叫Frame,最终产出Native view或H5view。


   再是两个接口,一个是CALLNative,一个是CALLJS,在所有的一切涉及到互调的,只有它们两个,只有它们的通信接口的简单为后续的整个扩展提供了便利性,这是一个真实的通信过程,我们仅仅能看到这两个通信。


   这是一个Native MJU(音),最终形成了一个散状的树状结构。


   最简单的对应了右边这样一个组件,并且它有一个组件的子节点。


   简单罗列一下Weex的非常基本的组件。这是Weex已经发布的组件,除此之外可以在第三方提供的Weex的独立的一些组件,包括我们自己官方有的Weex的官方库里面也可以找到很多使用的组件,可以看到容器级的,第一行是偏容器级的非常常用的,第二是长列表的内存以及流畅性问题。第三是容器级别、框架级别的组件。


   再往下是Module,我们定义的Native是Module实现。


   我们列几个最近用得比较的,像Modal对话框、Storage、clipboard、time等。


   这边的话,这是一个Weex的整体的结构图,还是做了一些简化,一些细节大家在前面的那几张图里已经看到了,这里相对简单一些,在Weex的最底层,这一层是RX(D2),以及J无S Framework以及JSFM(Vue2.0),这一条在社区的分支上能够看到代码了,Rx是内部面向业务端的一套框架,这套框架也会在12月份的D2(音)大会上去发布。


   业务模块的话,我这里列了几个现在业务开发中一直在用的,如页面的发布系统,因为Weex在这一端来看只是一个容器,要将整个业务跑通的话,要将发布系统、组件库以及常用的API,这是一个开源的引擎,争取将这些引擎跑到Weex上,再往上是业务这一层,包括过去大家听到比较多的大促线相关的Weex产品,未来其实已经在过去的6个月,其实这一块已经有了非常多改变,那从客户端上的话,我列了几个算是目前用得比较多的,还没有列得特别全。


   这边大概是这一些。然后业务上的话,这是从去年双11到6月的活动,包括现在正在做的双11,一个月以后大家都可以看到一些消息。


   左边是大促,右边是我们的微淘,这是一个详情页里面的一个页面,这是店铺的页面,包括我们有提到刚才在直播里面的互动层的页面,还有很多诸如此类的产品页面都在用Weex。


   那我们说了一些Weex,也做了一些对比,实际上Weex真正的价值是什么?至少我们目前看到的这三方面相对有一些体现,第一是觉得整个发版的速度,刚才玄总也说了,可以动态部署2、3天做到80%、90%,如果走常规渠道的话,到60%还得耗费两周。IOS现在快一点。现在Weex/H5,已经觉得了其更新是很快的,用1分钟加上整个系统发布、上CDN的时间等,1分钟也够了,足够到60%,1分钟到达到90%以上也够了。第二是开发效率,安卓/IOS/H5三端开发,保守估计节省50%,未来的话应该是远高于50%的。第三个是体验的提升,这个我们举一个例子就是安卓的低端机,同样一个页面帧率就上升了40%—50%,这是一个明显的差别。


   我们听到Weex是从去年双11到今年1月份已经有了第一个独立的SDK版本,所有的方案都可以用,而不是定制的方案,到3月份是UI的扩充和API的扩充也做了持续两个月的调整,到4月份的话,我们有一个OPEN SOURCE(内测)。6月份正式地开源,更多的业务正在逐步地上来。


   这是从几个特性来说:


   第一个特性是:多端一致。这是一个安卓上的APP。这是IOS上的。


   语法足够轻量,大家用一个小时去上手的话,我觉得应该问题不大,如果你有前端经验,直接你看了之后直接就能够做了。


   第二是轻量SDK,这是昨天拉的数据不含V8的情况下只有600多K,如果APP里有V8的话,600多K也够了,V8压缩会1.5兆的样子。IOS增量的话是700多K。


   高性能这一块,这之前可能也放出来过这个数据了,可以看到在整个加载时间上,这是一个页面,实际的页面会好很多,这是6个月以前的,现在加载时间会好一点。然后是内存上的控制。CPU没有做后台的静默的工作,进入后台是不会再用的,所以CPU的峰值相对而言还是可以的。


   性能这一块,之后我们会一些更具体的文章,这里我写了一些我们觉得到目前为止比较能值得一提的东西,包括几块,包括它得打开得快,它得用得非常流畅,它又不能对CPU内存有过大的损耗,对于内存的损耗,等稳定性有影响,对CPU,手机发热,电池耗得快,这三块是我们关注的。在秒开,在H5做预加载,它是一个通用的服务,这样的一套机制既可以用在H5上,也可以用在Weex上,现在Weex已经将预加载的机制用起来了。执行阶段将Framework+JSBundle进行拆分,每一次页面的初始化时间可以得到保证。第三是渲染阶段,渲染阶段做的事情比较多,比较直观的是后面有一个小例子,分块的选择,传统上,我们渲染一个页面,一个节点过来就渲染了,现在可以定义一个所谓的快状结构可以定义一棵树来整体渲染,这样可以加快整体的渲染效率,也可以减少通讯的次数,这两块都是可以提升整体的渲染效率的。


   第二在流畅上,能够脱离主线程的工作全部脱离主线程。


   这是图层合成,它是平的,下面是不图层,它是非常多层的结构,多层结构带来的问题是整个渲染过程会变得更加复杂,更耗时。


   再往下节能的话,做JSCore GC策划优化,然后文本渲染也是做了一些工作。

  

   这是用node做的,我下载到了一部分的node结构,就会立刻渲染,这样的好处是实时性更快,但未必在所有场景合适,一个列表里面的元素,你不把一个下完,本身意义也不是很大,而且对性能的影响是比较大的,这是node的表现。

   这是Tree的表现,它拿到了数据,拿到整个Tree的数据结构,然后它渲染出来,这是一个比较直观的对比。


   然后我们大概从6月份就开始做工具,那时候用Weex调试工具,相对来说比较粗糙一些,只能看一些简单的。


   这里用到DevTools,查看网络的部分,除了像极少的不是那么常用的工具,还有一个是审计的功能,目前还没有做,其他大部分标签里审计到的功能都已经在线上,大家都能用到。


   这是我们昨天最新的一张表,DevTools完全不是从零开始里,这是用STETHO进行开源的框架。最早的是Ponydeb Ugger,用来调Native Tree(音),Weex这一块也是直接在底层用了它们,在上层的功能上做了更多的扩充。


   这几个功能简要地介绍一下,多设备的调试,可以开多个应用或多个设备,多个设备直接去进行连接,然后是JS debugger,功能会比我说的更多一些。大家在JS里,用JS的同学会知道,对JS的需求,一些断点功能基本做上去了。


   因为我们在刚才也看到,我们有时候是希望看到Vdom inspector。最后,我们的屏幕映射是做了反向映射的,这边也给大家做了扩展。


   再开源这一块,我们大概是6月底,大概6月30号左右正式开源了,有一些小数据,第一天在CHECK(音)网的第一。


   社区运作,宏观来看是三块:一块是在需求里做一些讨论,进入Coding为期,第三块会拉得比较长一些。


   这是一个比较典型的需求,会给予自定义的特性,我们会要求整个进行扩展,他要做一些定义必须要写得比较清楚,后面会让大家来讨论你对这个写出来的这份建议有没有一份看法或修正,会有这样一个讨论的过程,到代码发起PR,会有一个持续的沟通过程,也会有专门的同学为大家提交了代码去做PR。


   最后的话,开源,我觉得的收获,开源的确给我们带来更多的表现,大量边界条件,强化稳定性。第二,这是我们自己主观的感受,服务好开发者的事情,并不像想象中的那么简单,需真正投入精力,还有代码、文档、工具、线上交流、线下活动,还是有很多交流要去做的。我的沟通就到此结束。

  

   主持人:下面是提问环节,大家有没有关系。

  

   提问:谢谢老师,我之前有了解过Native,Weex跟Native感觉很接近,我想说这两个怎么理解,有什么区别吗?

  

   徐凯(鬼道)阿里巴巴高级技术专家:有一个比较大的区别,它并不想做三端一致,它希望同一套JS开发理念能够去跑写IOS,写安卓的,我们举一个最简单的例子,它就不想因为追求三端一致,让整个代码的结构完全用同一份的BASE(音),二者在这个点上是有明确差异的,在Native不会看到有IOS开头的,在AND社区(音)里逐渐地推出了新的组件库,他们在帮助其做新的工作。在大家的业务里,游戏是偏业务性的内容,三端一致性对你们绝对是刚需,我就说这一点。给这边同学。

  

   提问:我想请教一下,Weex的话有没有提供,因为刚才演讲的过程当中提到了你们做Weex时做了一些压测,基于Weex的工具和容器,有没有给开发者提供压测的条件和最佳的实践?

  

   徐凯(鬼道)阿里巴巴高级技术专家:有压侧页面的,PR Bundle(音),你可以扩展10倍来做。


TB2q2sXXYaI.eBjy1XdXXcoqXXa_!!0-martrix_TB2.aSeao5O.eBjSZFxXXaaJFXa_!!0-martrix_TB2w9yaafOM.eBjSZFqXXculVXa_!!0-martrix_TB284AaXY1J.eBjSszcXXbFzVXa_!!0-martrix_TB2BRmgaheK.eBjSZFuXXcT4FXa_!!0-martrix_

TB2i7ZmX3OI.eBjSszhXXbHvFXa_!!0-martrix_TB2aHOcaiGO.eBjSZFpXXb3tFXa_!!0-martrix_TB2PDOgafSM.eBjSZFNXXbgYpXa_!!0-martrix_TB2oUSgaheK.eBjSZFlXXaywXXa_!!0-martrix_TB2TzQcXYWJ.eBjSspdXXXiXFXa_!!0-martrix_

TB22gIgXY1J.eBjSspnXXbUeXXa_!!0-martrix_TB2rUCfaX5N.eBjSZFvXXbvMFXa_!!0-martrix_TB2A0MgX4mI.eBjy0FlXXbgkVXa_!!0-martrix_TB2NPcbXY1K.eBjSsphXXcJOXXa_!!0-martrix_TB2K7gcXYWJ.eBjSspdXXXiXFXa_!!0-martrix_

TB2T_1faiGO.eBjSZFEXXcy9VXa_!!0-martrix_TB2rTidaXOP.eBjSZFHXXXQnpXa_!!0-martrix_TB29AwmX89J.eBjy0FoXXXyvpXa_!!0-martrix_TB2_vGsXOgSXeFjy0FcXXahAXXa_!!0-martrix_TB2e1WeamiK.eBjSZFsXXbxZpXa_!!0-martrix_

TB2ctQfX9uJ.eBjy0FgXXXBBXXa_!!0-martrix_TB2W2eeamiK.eBjSZFsXXbxZpXa_!!0-martrix_TB2zmKeaduO.eBjSZFCXXXULFXa_!!0-martrix_TB2_s7iX9GI.eBjSspcXXcVjFXa_!!0-martrix_TB23H3eX9iJ.eBjSspfXXbBKFXa_!!0-martrix_

TB2Ov9eaX5N.eBjSZFKXXX_QVXa_!!0-martrix_TB24kgbXY1K.eBjSsphXXcJOXXa_!!0-martrix_TB2e8KfakWM.eBjSZFhXXbdWpXa_!!0-martrix_TB2FhkXXYaI.eBjy1XdXXcoqXXa_!!0-martrix_TB2H2.dX4eI.eBjSsplXXX6GFXa_!!0-martrix_

TB2oWAfXZeK.eBjSszgXXczFpXa_!!0-martrix_TB2pEChagCN.eBjSZFoXXXj0FXa_!!0-martrix_TB2K53eX91I.eBjy0FjXXabfXXa_!!0-martrix_TB2_9efakWM.eBjSZFhXXbdWpXa_!!0-martrix_TB24YuhalaM.eBjSZFMXXcypVXa_!!0-martrix_

TB2ah.dXW9I.eBjy0FeXXXqwFXa_!!0-martrix_TB2o.WgaheK.eBjSZFuXXcT4FXa_!!0-martrix_TB24xCsXOgSXeFjy0FcXXahAXXa_!!0-martrix_TB2O1AkX3SI.eBjy1XcXXc1jXXa_!!0-martrix_TB2ZjeeaiGO.eBjSZFPXXcKCXXa_!!0-martrix_

TB21WObafOM.eBjSZFqXXculVXa_!!0-martrix_TB260.eX9iJ.eBjSspfXXbBKFXa_!!0-martrix_TB2h3ZjXZaK.eBjSspjXXXL.XXa_!!0-martrix_TB2IbwkX9OI.eBjSspmXXatOVXa_!!0-martrix_TB2_5SiahaK.eBjSZFBXXagMXXa_!!0-martrix_

TB2nMsfX9uJ.eBjy0FgXXXBBXXa_!!0-martrix_TB2eg4TXLTJXuFjSspeXXapipXa_!!0-martrix_TB2SnIcXYeI.eBjSspkXXaXqVXa_!!0-martrix_TB2l5kgX9KI.eBjy1zcXXXIOpXa_!!0-martrix_TB2f_1daiGO.eBjSZFjXXcU9FXa_!!0-martrix_

TB2kSGealyN.eBjSZFIXXXbUVXa_!!0-martrix_TB2IxSdaiKO.eBjSZPhXXXqcpXa_!!0-martrix_TB2YNlTXLTJXuFjSspeXXapipXa_!!0-martrix_TB2.b1haX5N.eBjSZFmXXboSXXa_!!0-martrix_TB2XNUjXZaK.eBjSspjXXXL.XXa_!!0-martrix_

TB2FPmsXOgSXeFjy0FcXXahAXXa_!!0-martrix_TB2o7QgXY1J.eBjSspnXXbUeXXa_!!0-martrix_TB2aLWbajm2.eBjSZFtXXX56VXa_!!0-martrix_TB2YVagakWM.eBjSZFhXXbdWpXa_!!0-martrix_

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
+ 订阅

阿里百川是阿里巴巴无线开放平台

官方博客
官网链接