【干货】阿里资深无线技术专家孙兵谈闲鱼社区技术架构演进 - 阿里技术

近期在ArchSummit北京会议上,阿里巴巴资深无线技术专家孙兵(花名酒丐)发表了《网格社区-闲鱼技术架构演讲》主题演讲。孙兵2011年加入阿里巴巴,先后在B2B、淘宝、手机淘宝等部门负责过会员、物流、O2O、导购等系统的架构和研发;目前担任阿里创新业务闲鱼的技术负责人,负责产品的技术研发工作。他从技术负责人的视角来分享闲鱼社区的技术架构演变历程,以及在这个过程中不同阶段把握不同重点,通过技术驱动社区架构建立与发展,并且就每个阶段的具体实践给大家带来精彩的实例分享。

演讲全文:

孙兵:非常感谢主持人的介绍。不太习惯北京热情的雾霾,所以可能讲的不那么好,大家将就着听。简单自我介绍一下,我是2011年加入阿里,在阿里五年多的时间经历了很多业务,开始从会员到物流、从物流到手机淘宝,然后是闲鱼,现在我的位置其实是闲鱼的技术负责人。一开始我给大家讲一下,作为一个架构师,关于驱动你每天工作的愿景或者说是使命的问题,或者说这只是一个工作。架构师每天的工作是做架构,架构我们会说要有原则,要有目的,要有解决的问题。但是实际上来说,驱动你去做这些事情真正的理由是什么?如果没有这个理由很多事情就没有出发点,好比说我做架构的目的是怎么让我自己快乐,那么你可能做的这个东西虽然不好用,但是很有技术含量很有设计感。

架构每个人其实都有自己的愿景或者出发点,如果出发点不对的话,其实后面讲的已经是一些术的选择,道的这部分其实对于我来说可能是更关键的部分。这是你作为架构师的使命。你相信架构可以带来什么?或者放大一点,就是作为一个对技术选择负责的人,你应该相信什么?选择什么?

给大家讲一下闲鱼,闲鱼这个项目是2014年5、6月份开始做的。这个时候已经不是一个很好的时间点,不符合当时阿里巴巴整体的战略选择。当时大背景是阿里集中投入开始做无线,倾向集中力量建设几个大型APP如手机淘宝或支付宝钱包,这是当时的策略。我们当时在招募项目成员的时候给大家讲,闲鱼的使命是什么?我们希望做一个P2P的、有交易的社区。很多人觉得,从逻辑上来说还是一件很有机会的事情。当然每个人的出发点都不同,有的觉得这个业务可能让我得到提升自己的机会,有人觉得这个业务会让我的年底绩效比较好,有人会觉得这是一个新业务,可能我后面有机会可以当上更高职位的领导者。

这些机会有很多,其实一开时招募的人也很多。在做项目kick off的时候,公司的高层会挑战这个事情,认为作为一个初创团队需要这么多人吗,而且是跟大的战略不那么契合。初创项目首先要证明自己是work的,如果你们觉得这是真爱,公司给你选择的机会,到财年底公司不投任何营销费用,做到日活一百万;既然你是相信这个事情,那没有做到年底0加薪0年终奖。这样说完以后,第二天走了一半人,一个星期之内再走掉一大部分人,最后留下来相信这个事情的,只有十几个人。闲鱼这两年的成长过程,经过很多次这样的洗刷。当时我们抱怨老板怎么可以这样?其实我们回头想,这件事真正决定了闲鱼的基因与做法。闲鱼团队后面的成长也在有意选择真正相信这件事的人。真正相信的是什么?我相信最后留下的,每个人会有不同的看法和不同的出发点,甚至想要得到的东西不一样。但是他已经不是那么功利,会在做事上有更长远的选择。

后面的选择,还是有人选择离开,觉得付出和回报不成正比,或者这个东西不是他想要的。但是不要紧,留下来的都是相信这个事情的人,这个比较重要。真正相信的是什么东西?我们希望留下的真爱通常会是什么?我现在跟别人沟通,发现我很难从别人的角度去说服别人,这个问题太难了,我根本想不到对方想什么,因为个体差异太大,所以我通常说我怎样想这个问题,这个问题在我看来是什么,我只要让我觉得我自己说的是真话,我可以让别人感受到。

那么谈我相信的事情,我在阿里五年有很多次想选择离开换一个地方,包括我进去的时候也没有想过待很久。过程中也有很多的不爽或者纠结或者怎样,但是回头来看我会说,我很享受那样的一个过程,有机会从0做到1,然后从1到N的过程,这两个过程我有幸参与。从0到1,从无到有的过程,其实是非常煎熬的过程。通常这个过程可能要一年时间,那个时间你不断尝试,不断被别人鄙视。你做的很多事情都是失败案例,你探索的都是不成功的道路,所有人都看不起你,所有人都是居高临下的教你怎么做。你要学会怎么在这种情况下生存,并且找到亮光,这个是我很享受的。如果你已经到了这个阶段,找到了你真正的成长方式,接下来就是野蛮成长。其实我也有幸经历了这个过程,包括物流或者手机淘宝,我觉得都是这个过程,就是从千万级到亿级。通常来说这个过程,就是尽情奔跑与碾压竞争对手,压死当初看不起我的,拿结果告诉你应该是这样做的,这个过程也是我很享受的过程。

因为今天分享的是我在闲鱼的经历,首先讲一下闲鱼是什么东西?闲鱼在大家眼里面是一个上亿商品的货架,但对你来说根本感受不到那么多商品。如果有几千个商品,对你来说就是海量,对你来说,首页这里的信息只是跟你最相关的部分。然后是可能骚扰或有益的提醒,它会跟你产生连接。这个如果是在电商领域就是商品。但是怎么把有益的商品组织起来,把这些商品活跃起来,并且找到这个商品所需要的人。并且在一些关键的时间节点,和这个用户产生连接,这是一个非常难的过程。每个电商产品整个效率的差异就在这里。最高效率的淘宝已经把电商的效率做到极致,它的UV价值已经做到令人发指的地步。

那么在这种情况下,所有的电商产品有意无意的与它产生差异。我们从来没有选择做电商的这条道路,我们在做一个共享经济的社区平台,这是我们的愿景。这个区别最大的地方在哪儿?我会组织用户,产生用户和用户之间的连接。这个差异在我们的产品形态上其实就是鱼塘这个产品,这个产品我们会通过地域和兴趣把用户连接在一起。用户可以成为发布者也可以成为信息的收获者。今天我可能强调的特点会是闲鱼线下线上的连接部分,我给大家看到的照片会说明一些东西。

在闲鱼我们会有线下和线上互动,我们闲鱼到现在是一个很小的团队,在线下做O2O的时候,更多是靠闲鱼30万的塘主进行运营。我们发现这里进行交易的用户都是非专业用户,他通常想要出售的东西,通常不是为了钱。我们在这个点上会发现,当然也是在实际上面运作的时候才发现,通常在线下交易的人是大学生或者有孩子的。有孩子的其实很容易理解,几个大人在那里跟人家讨价还价,就五块钱或者六块钱的事情,其实很没份。其实大家都是有身份的人,做这个事情很丢脸。但是带了娃这个事情就会变性,就会变成我让我的小孩参与一个社会实践活动,让他理解金钱的重要性,让他知道什么东西都是有代价的。大学生就会更明显,其实这个里面通常是交友,通常交换的东西超过交换的本身,比如说教课书或者是师姐的一床被子。我下面讲的是跟技术相关的部分。

所有的技术架构的演进跟业务形态都是强相关的,你处于什么阶段要解决什么问题?首先描绘一下我们开始的业务架构的模型。我们看一下我们最开始的闲鱼的架构其实很简单。这个架构的背景是什么?当时闲鱼的人,整个开发是十人的状态。很不幸的事情就是没有测试,闲鱼最开始上线就是这样子,我们没有测试直接上线。开发工程师做好了以后就直接上线,我们也没有很大的能力去做很多的基础的架构的工作。我们更多是在复用淘宝PC或者手机淘宝相关的工程结构。

这个阶段里面,我们有自己的核心关注点,这个阶段的架构原则是什么?就是用速度换质量。我们其实是在牺牲线上质量来换取更快的开发速度,基本上我们是想到一个功能,想到一个可能性我们就希望它立刻可以体现在线上。那么在这个过程中,我们会遇到一个很悲催的事情,客户端发版并不是我想要它多快就可以多快,开发可以一下午打包发出去。但是这个做不到,因为当时2014年Apple审APP速度非常慢,一般来说是3到7天,有时候比这个时间还长,如果中间拒审可能两个礼拜才上线,这是一个非常痛苦的过程。动态性,其实这个阶段就是我们在找真正适合我们的商业模式,到底是什么?用户可以产生共鸣的点在哪儿?动态性这个问题上面,我们并没有使用特别复杂的技术方式解决这个问题。

我们使用的技术方法,即使我扔上去也不能改变苹果审的速度。所以我们选择了HyBird的架构,我们选择用H5解决这个问题的动态性。基于此我们在下面做一个,其实我这里蓝色部分就是我关注的几个点。一个是URLRoute这个装置,不知道大家有没有理解。这个手淘应该讲了很多次,我们会利用客户端将所有请求路由到一个H5的连接。这个装置会通过URLRoute通过URI Schema到达到真正的客户端的一个页面,如果找不到对应的时限就会用H5的实现来做它的打底。如果这个部分native没有开发出来,就用H5版本顶上去。这样的话,安卓和IOS的版本不同步的问题解决了,因为安卓通常比较快,这个时候上去安卓已经有了,跟它对应的装置就是开关中心。

开关中心这个东西就是我们为了实现一些灵活的配置情况下,我们需要一些针对这个流程做一些配置。可能需要将某一个路由进行转接,也可能需要再额外加一个调用的参数,甚至加版本或者人群的分割。其实都是客户端的动态改变,它可以到开关中心进行调整。

通过开关中心已经实现我们想要跑多快就跑多块,不用担心发布跟版本录用迭代不匹配的问题。我的版本发多了会有多个版本的问题,在多个版本的问题我怎么实现服务端的问题,这个参数可能不存在,其实这里我们会基于一个网关的多版本兼容的体制,每个API的访问都会加上版本号,在相同API不同版本的实现是通过一层一层复用的机制,保证对上一个版本的支持。其实在服务端我们会做一个通行的老版本,基于此我们会利用开关中心跟ABtest的关系,我们会切分成进行测试的分口,通过这个下发到每个客户端,在不同的人群里面,它的界面表现和数据表现是不同,实现一个端上的动态测试。这是我们第一个阶段,其实就是说整体的试错的过程。

我们在端上的界面,比较痛苦的事情是做活动,运营他们可以想起来的日子都可以做活动,这个活动他们希望有一个前端的入口,最好是首页或者关键的资源页能够动态投放相关内容。通常来说这个问题其实解法是,你把全网可以挖出资源位的地方都出来预置好。对于我们刚开始做一个APP的时候,去哪里挖资源位,其实是把整个复杂度提升了。这种情况我们选择了一个动态挖资源位的方法,其实就是Poplayer,我们会进行页面切换,它会根据当前切换的页面进行页面的加载,它有一定的透明度。比如说在首页上面,圣诞节加一个圣诞老人或者雪橇,其实这个资源位我可以通过Poplayer加上去,这个牵扯到一个前后端配合的工程技术装置。

接下来我们会说, 比较勉强进入到0.1的阶段,就是发展阶段。我们认为对于我们来说我们整个的交易在过亿的时间节点,我们认为我们做到0.1的状态。这个阶段我们整个系统的架构原则是什么?我们会发现其实我们已经能够比较模糊的看到了商业的模式,或者是用户的价值点。在这个状态的时候,对我来说架构的挑战就是效率和能力的问题。这个地方还要提一下对于效率的开发,开发效率,研发工程师关注效率永远不是错误的事情。但是你关注效率的目的有不同,有的同学会说我关注效率的目的是让整体的成本降下来,但是这个阶段来我们关注的不是成本,而是我有机会做更多的有可能的事情。

在这个阶段我怎样提升架构?架构原则是说你怎样提升效率?我的架构原则其实就是没有沟通的协作是效率最高的。就是在你不改变整体的生产工具的先进性的情况下来改变生产方式。在我看来就是没有任何的沟通,是最有效率的开发方式。在这个地方我们会更加关注整个的前后端的协同的协议和约定和契约和工具的自动化。这个时间点,蓝色部分我们会发现,比如说我们在活动这一端会有MBaas的装置,你客户端想要存储用户参与这个抽奖或者用户进入这个页面有一个点赞工作,这是一次性的工作你不要来烦服务商量。在后端不需要增加任何接口就可以实现这样的业务,这是一次性业务。在我们这里我们会提供一个MBaas的结构,这个装置不需要关注服务端到底有什么东西?

我们在客户端开发关注两个点,一个是说我新做一个功能或者说新做一个页面,新做这个页面整个的组装它需要哪些组件进行组装?在这种情况下其实是对于业务的逻辑,将原有的UI组件进行组装。这是一个开发过程,第二个过程是说我对原有的界面的重新梳理我需要加一个功能,或者加一个点赞的按纽。这两个逻辑我们会规范到组件的完善过程中,另外一个就是业务的逻辑梳理。

我们现在的做法其实是组装逻辑会下沉到服务端,客户端它没有业务逻辑,只在服务端有逻辑。整个你看到的这些数据这些数据的组装模式其实都是服务端下发,客户端只提供界面能力的组装,它解析然后进行渲染,但是它不理解这里面是什么?

客户端更多的工作是支持更多交互的基础的UI组件和动态适配性。这个过程中我们强调的就是整个的事件驱动的开发模型和整个UI组件库的建立。在服务端因为我们会将大量的一次性工作抛弃了以后,使我们有时间做一些新场景的探索,包括怎样线上跟线下的衔接?这个部分后面会讲到。更多的其实是在数据上的应用,在前面已经说了,其实几亿条商品用户不关心,关心的是几十条和我产生连接的内容。

现在的闲鱼的技术架构,我们认为现在已经接近了到1的过程。在这个状态的时候其实我们会更加关注的是我们当初的愿景的实现的过程。我们怎样可以让更多的业务在我们这个共享经济平台上能够落地?我能真正的可以成为一个平台?在这种情况下其实我想要的事情,已经远远超出我们自己的能力。这种情况下野心大于能力的时候,只能选择我可能去做更多的更基础的一些规划。然后把更多的可能性更多的动态性留给二方或者三方完成。这个里面我们做的更多的事情是对外整个的连接的协议的梳理和调用协议的梳理。那么这个里面我们会演化成,在容器这端我们演化成Service Bus,这个类似服务端的ESB。我们在客户端里面会基于原生的消息的和服务调用的方式,通过服务调用。

这一层我们的Service Bus是有一个包装的,我们不会让用户上层的调用代码直接访问Service Bus,我们会在这个上面做一个SDK,来屏敝各个版本之间的差异性,来保证它的兼容性。我们会把自己的基础的展示能力,整个结构化一个Parser,这样一个架构来解析未来在界面上展示的类型,使得未来我们扩展到其他业务类型的时候,不需要所有的参与者,都要从头开始做对应的展示的基础组件和至上的组装。

这个就是跟服务端对应上面是有一个模型,服务端要提供数据接入,在端上面能够展出来。在数据这一层我们会更加跟算法的能力的衔接,其实我们通过两条通路。一条路是实时的数据的流入,是基于我们在客户端上面的日志,这是分钟级日志实时反馈到我们的算法平台,然后包括业务数据直接打进我们的算法平台,然后拉到我们的搜索算法整个的机制里面。这里比较详细的会说一个闲鱼的架构演进,整体就是由我们的容器的中心跟消息的订阅发布机制和我们前端最主要的展示结合,形成一个前端架构。

前面讲的是说端上的架构,这一页其实是因为写完了以后,服务端的同学不是很开心,希望我加一页。其实我觉得服务端的架构其实在过去阿里的分享,也分享的很多。这里加的更多是说我们在数据上面的整个的数据的流向,怎样去跟算法进行结合,进行离线和增量数据的实时汇聚,跟前端整个打通的一个机制。

我们在线上线下的联动会遇到一个问题。这个问题在O2O行业已经讲了好几年,真正做成的业务可能到现在也没有,难就难在没有实现真正的线下线上联动。我们到这里也会遇到了同样的问题,这就是线下用户身份识别,并且把用户的线上数据跟线下行为衔接起来,这个问题对于我们来说很难解决。这个人到这里我能知道他是谁,对我来说是一个最难的过程。这个部分我们会做了一套身份识别和设备的校验机制,对用户进行识别,并且进行反向的交互,结合访问量进行用户的访问量交互。

最后给大家说一下数据驱动的开发的工作方式。其实很多同学都会说,我是相信的。但是实际上真正在做事情的时候,可能大家又会按照习惯逻辑说我觉得这样做会更好,这样我们会陷入无休止的纠缠,PD说我觉得怎样,但技术觉得不靠谱,然后就会说我觉得这个不怎样,那个又会说那个怎样。大家都是在说感觉,那么在这种情况下我们到底有什么样的机会可以让我们整个做事的内容能够回归到我们最开始的愿景?对我来说是比较关键的。我们现在的做法是,整个产品KPI,整个核心数据的KPI,它全部指向我自己的关键诉求。

对我们来说现在的关键诉求就是用户规模。这个场景如果跟用户规模不相干,它的关联性,如果偏弱。那么我会让位给另外一个产品,这是我在产品迭代里面的原则。我们发现首页的资源效率是不同,应该给谁更多流量?我们会做整个产品组合的最佳收益点。这个流程包括整个数据的挖掘,因为很多收益不是单目标决策,是多目标决策。我们是追求它的空间距离的问题。那么在这里我们怎样去选择我们的最大获益点?获益点我们找到了以后,我们希望整个的结果是可以通过数字去表达,我做一件事情,整个的结果是可以进行预测的。这个方法这个方案是有一个持续迭代和修改,在线上需要提供ABtest和迭代的能力,让我看一下这些数据是否能够在线上复现,就是样本空间里面证明的是正确的,在整个的实际的用户空间里面证明它是可复现的。

数据这块更敏感,实在是没有办法举这个例子,这个里面都是很敏感的数据。但是我可以说几个案例,这几个案例包括我怎样去留住新用户?我想所有做APP的同学可能都会关心这个问题,每个新用户的引入成本,便宜的几块钱,最贵的几百块钱,这个新用户怎样留下来?这是一个最要命的问题。如果新用户留不住,这个APP永远没有成长机会。这个里面我们分析流失的路径,然后可以强化它的行为。比如说举个例子,一开始所有人都会觉得让用户进行一次交易,会使他的流失降到最低。我们认为这个特征是最有效的特征,所有的行为都会指向让用户完成一个交易。当然这个有很多方法,比如成交成本更低的操作,可以让他完成交易。

最后我们发现这不是最有效的用户留存。我们反而发现一个用户连续来三天,比你完成一笔交易,整个贡献的效率更高。这只是一个发现,大家不用直接搬回去用。我就讲这些,谢谢大家!

Q

&

A

Q1:刚才提到有一个针对SDK的支持,我想知道这一层,能不能介绍一下。因为我们知道每一个SDK它是有很多新的功能组合,也有很多老的功能,然后是怎样抽象出来的?刚才提到有一个H5的支持,这一层的功能是把活动实现,然后从后端打通到前端,我也想知道这一层,能不能稍微介绍一下。

孙兵:首先确认一下问题。第一个问题是说接口的兼容问题。我们其实每一次版本的发布,我们会把这个版本打在配置文件里面,所有API的版本是一个通用版本,我们不需要定义每个API的版本是什么?我只要告诉你这个程序的版本号。然后到我们服务端,我们所有的请求我都会告诉你这个APP的版本是什么?这个APP的版本默认在服务端的时候,会选择跟它最接近的上一个版本,跟它间隔是最小的那个版本。如果他觉得我有必要为这个版本做一个升级,因为可能有更多的参数,或者需要更多的反馈,那么我在这个版本里面加一个针对这个版本的适配。这个其实对整个服务端整个的改写成本会降很低,因为默认的版本不需要做任何动作。如果我觉得这个版本之后需要额外做一些事情,我就需要在这个版本里面会做新的版本API动作。

第二个问题是说后端不用管前端的MBaas的结构,MBaas的结构,现在在链接里面也有公有的MBaas,它的原理很简单,就是前端需要后端提供存储服务,或者一个计算。这个存储服务,客户端在第一次申请的时候,给他动态的创建他所需要的schema,你进行操作的时候,所有的逻辑包括+1-1,或者你想加一个动态的赞,这个你可以在后端进行操作。因为客户端跟你个人相关,我不需要关注群体逻辑,这可以用MBaas的结构来做,其实就是有一个对应的服务端结构,这是根据你的请求去动态创建的schema。

Q2:第一个问题是服务端有很多代码,然后用覆盖这个方式来做代码支持。

孙兵:会覆盖掉上一个版本,通常来说。

Q3:第二个问题,其实主要是针对个人,这个解决方案不能解决每个个人用户他的计算,他的计算是不同的。

孙兵:聚合是比较难的。我们会有一些通行的接口,我们会用搜索解决大量的个性化的数据,我们会有一个通用的搜索接口,这个就是所有的可以进行索引的索引词,可以用搜索查询解决这个问题,但是聚合计算要单列了。

更多阿里双11技术干货,请关注《不一样的技术创新》-阿里巴巴双11技术电子书!10万余字纯干货,8个领域27篇文章,涵盖基础设施、存储、中间件、云计算、业务架构、大数据、认知计算与人工智能、交互技术及安全等技术领域!

5