一起来造一个RxJava,揭秘RxJava的实现原理

一类创业者基本都是做传统行业的,这类创业者非常大胆,也非常舍得投入。很多时候他们如果看到或者想到一个商机,就会投入成千上百万,先把产品做出来,然后再去想怎么开拓市场。

  这类传统行业的老板,问我最多的问题就是,我有很好的产品,为什么就是没有销量,怎么用微信把销路打开?

  还有一类创业者,甚至不能叫创业者,只能叫创业爱好者。他们往往每天都会看到或者想到很多商机,然后基本只是停留在想的阶段,几乎从来不执行。

  这类创业爱好者问我最多的问题就是,我有个很好的想法,你觉得我应该去创业吗?你觉得应该怎么开始最保险?

  这2类创业者看起来是2个极端,一个是什么都不管不顾,先砸钱做了再说,一个是什么都前思后想,非常谨慎,从来不行动。

  虽然这2类人看起来区别很大,但是其实是硬币的2端而已,基本都是同一类人。

  为什么这么说?

  因为这2类人的共性都是眼里只有产品,没有用户,都是产品思维,不是用户思维。

  产品思维的的人,觉得只要有好产品,就能够打动市场,就能够取得很好的销量。

  可惜现在已经不是30年前了,现在产品是供大于求,好产品已经是标配了,好产品多如牛毛,再多一根牛毛,用户也不会感知到。

  光有好产品就可以打遍天下的时代已经过去了。

  现在应该是用户思维。

  要知道我的用户是谁,他们有什么痛点,我如何找到他们,我如何把他们最大的痛点找出来,然后想办法满足他们的痛点。

  对有用户思维的创业者来说,他们不会盲目的看到一个商机或者想到一个商机,就马上做产品。他们也不会整天在脑海来跑马,不断去猜测各种商机,然后迟迟不动手。

  对于有用户思维的创业者来说,他们如果决定要开始一个项目之前,会花很少的钱,大量的时间在用户身上。他们会通过微信公众号,个人号,微信群,把用户圈进来。

  用户圈进来后,再想办法让用户互动起来,在这个过程中收集用户痛点,找出用户最大的痛点,然后再找寻找解决方案,或者自己做一个解决方案出来。

  这样的创业者,一开始投入非常少,甚至一开始就赚钱,然后过程中可以持续赚钱,基本上可以做到最低成本创业,而且创业成功率非常高。

  好了,今天简单写到这吧,大家有兴趣可以多关注我的公众号,我会持续不断告诉大家如何通过用户思维来创业。

  我是秦刚,希望我的微信公众号,能够给大家带来一些不同的声音。

  秦刚简介:自明星天使投资人,现居加拿大,1999年从事垂直网站工作,历任太平洋电脑网总编,太平洋汽车网市场总监,IT世界网CEO,39健康网联席总裁。随着不同终端(Pad/Mobile/PC)的兴起,对开发人员的要求越来越高,纯浏览器端的响应式已经不能满足用户体验的高要求,我们往往需要针对不同的终端开发定制的版本。为了提升开发效率,前后端分离的需求越来越被重视,后端负责业务/数据接口,前端负责展现/交互逻辑,同一份数据接口,我们可以定制开发多个版本。

  这个话题最近被讨论得比较多,阿里有些BU也在进行一些尝试。讨论了很久之后,我们团队决定探索一套基于NodeJS的前后端分离方案,过程中有一些不断变化的认识以及思考,记录在这里,也希望看到的同学参与讨论,帮我们完善。

  一、什么是前后端分离?

  最开始组内讨论的过程中我发现,每个人对前后端分离的理解不一样,为了保证能在同一个频道讨论,先就什么是”前后端分离”达成一致。

  大家一致认同的前后端分离的例子就是SPA(Single-pageapplication),所有用到的展现数据都是后端通过异步接口(AJAX/JSONP)的方式提供的,前端只管展现。

  从某种意义上来说,SPA确实做到了前后端分离,但这种方式存在两个问题:

  WEB服务中,SPA类占的比例很少。很多场景下还有同步/同步+异步混合的模式,SPA不能作为一种通用的解决方案。

  现阶段的SPA开发模式,接口通常是按照展现逻辑来提供的,有时候为了提高效率,后端会帮我们处理一些展现逻辑,这就意味着后端还是涉足了View层的工作,不是真正的前后端分离。

  SPA式的前后端分离,是从物理层做区分(认为只要是客户端的就是前端,服务器端的就是后端),这种分法已经无法满足我们前后端分离的需求,我们认为从职责上划分才能满足目前我们的使用场景:

  前端:负责View和Controller层。

  后端:只负责Model层,业务处理/数据等。

  为什么去做这种职责的划分,后面会继续探讨。

  二、为什么要前后端分离?

  关于这个问题,玉伯的文章Web研发模式演变中解释得非常全面,我们再大概理一下:

  2.1现有开发模式的适用场景

  玉伯提到的几种开发模式,各有各的适用场景,没有哪一种完全取代另外一种。

  比如后端为主的MVC,做一些同步展现的业务效率很高,但是遇到同步异步结合的页面,与后端开发沟通起来就会比较麻烦。

  Ajax为主SPA型开发模式,比较适合开发APP类型的场景,但是只适合做APP,因为SEO等问题不好解决,对于很多类型的系统,这种开发方式也过重。

  2.2前后端职责不清

  在业务逻辑复杂的系统里,我们最怕维护前后端混杂在一起的代码,因为没有约束,M-V-C每一层都可能出现别的层的代码,日积月累,完全没有维护性可言。

  虽然前后端分离没办法完全解决这种问题,但是可以大大缓解。因为从物理层次上保证了你不可能这么做。

  2.3开发效率问题

  淘宝的Web基本上都是基于MVC框架webx,架构决定了前端只能依赖后端。

  所以我们的开发模式依然是,前端写好静态demo,后端翻译成VM模版,这种模式的问题就不说了,被吐槽了很久。

  直接基于后端环境开发也很痛苦,配置安装使用都很麻烦。为了解决这个问题,我们发明了各种工具,比如VMarket,但是前端还是要写VM,而且依赖后端数据,效率依然不高。

  另外,后端也没法摆脱对展现的强关注,从而专心于业务逻辑层的开发。

  2.4对前端发挥的局限

  性能优化如果只在前端做空间非常有限,于是我们经常需要后端合作才能碰撞出火花,但由于后端框架限制,我们很难使用Comet、Bigpipe等技术方案来优化性能。

  为了解决以上提到的一些问题,我们进行了很多尝试,开发了各种工具,但始终没有太多起色,主要是因为我们只能在后端给我们划分的那一小块空间去发挥。只有真正做到前后端分离,我们才能彻底解决以上问题。

  三、怎么做前后端分离?

  怎么做前后端分离,其实第一节中已经有了答案:

  前端:负责View和Controller层。

  后端:负责Model层,业务处理/数据等。

  MVC分

  试想一下,如果前端掌握了Controller,我们可以做urldesign,我们可以根据场景决定在服务端同步渲染,还是根据view层数据输出json数据,我们还可以根据表现层需求很容易的做Bigpipe,Comet,Socket等等,完全是需求决定使用方式。

  3.1基于NodeJS“全栈”式开发

  如果想实现上图的分层,就必然需要一种web服务帮我们实现以前后端做的事情,于是就有了标题提到的“基于NodeJS的全栈式开发”

  Node带来的全栈时代

  这张图看起来简单而且很好理解,但没尝试过,会有很多疑问。

  SPA模式中,后端已供了所需的数据接口,view前端已经可以控制,为什么要多加NodeJS这一层?

  多加一层,性能怎么样?

  多加一层,前端的工作量是不是增加了?

  多加一层就多一层风险,怎么破?

  NodeJS什么都能做,为什么还要JAVA?

  这些问题要说清楚不容易,下面说下我的认识过程。

  3.2为什么要增加一层NodeJS?

  现阶段我们主要以后端MVC的模式进行开发,这种模式严重阻碍了前端开发效率,也让后端不能专注于业务开发。

  解决方案是让前端能控制Controller层,但是如果在现有技术体系下很难做到,因为不可能让所有前端都学Java,安装后端的开发环境,写VM。

  NodeJS就能很好的解决这个问题,我们无需学习一门新的语言,就能做到以前开发帮我们做的事情,一切都显得那么自然。

  3.3性能问题

  分层就涉及每层之间的通讯,肯定会有一定的性能损耗。但是合理的分层能让职责清晰、也方便协作,会大大提高开发效率。分层带来的损失,一定能在其他方面的收益弥补回来。

  另外,一旦决定分层,我们可以通过优化通讯方式、通讯协议,尽可能把损耗降到最低。

  举个例子:

  淘宝宝贝详情页静态化之后,还是有不少需要实时获取的信息,比如物流、促销等等,因为这些信息在不同业务系统中,所以需要前端发送5,6个异步请求来回填这些内容。

  有了NodeJS之后,前端可以在NodeJS中去代理这5个异步请求,还能很容易的做Bigpipe,这块的优化能让整个渲染效率提升很多。

  可能在PC上你觉得发5,6个异步请求也没什么,但是在无线端,在客户手机上建立一个HTTP请求开销很大,有了这个优化,性能一下提升好几倍。

  淘宝详情基于NodeJS的优化我们正在进行中,上线之后我会分享一下优化的过程。

  3.4前端的工作量是否增加了?

  相对于只切页面/做demo,肯定是增加了一点,但是当前模式下有联调、沟通环节,这个过程非常花时间,也容易出bug,还很难维护。

  所以,虽然工作量会增加一点,但是总体开发效率会提升很多。

  另外,测试成本可以节省很多。以前开发的接口都是针对表现层的,很难写测试用例。如果做了前后端分离,甚至测试都可以分开,一拨人专门测试接口,一拨人专注测试UI(这部分工作甚至可以用工具代替)。

  3.5增加Node层带来的风险怎么控制?

  随着Node大规模使用,系统/运维/安全部门的同学也一定会加入到基础建设中,他们会帮助我们去完善各个环节可能出现的问题,保障系的稳定性。

  3.6Node什么都能做,为什么还要JAVA?

  我们的初衷是做前后端分离,如果考虑这个问题就有点违背我们的初衷了。即使用Node替代Java,我们也没办法保证不出现今天遇到的种种问题,比如职责不清。我们的目的是分层开发,专业的人,专注做专业的事。基于JAVA的基础架构已经非常强大而且稳定,而且更适合做现在架构的事情。

  四、淘宝基于Node的前后端分离

  淘宝基于NodeJS的前后端分离

  上图是我理解的淘宝基于Node的前后端分离分层,以及Node的职责范围。简单解释下:

  最上端是服务端,就是我们常说的后端。后端对于我们来说,就是一个接口的集合,服务端提供各种各样的接口供我们使用。因为有Node层,也不用局限是什么形式的服务。对于后端开发来说,他们只用关心业务代码的接口实现。

  服务端下面是Node应用。

  Node应用中有一层ModelProxy与服务端进行通讯。这一层主要目前是抹平我们对不同接口的调用方式,封装一些view层需要的Model。

  Node层还能轻松实现原来vmcommon,tms(引用淘宝内容管理系统)等需求。

  Node层要使用什么框架由开发者自己决定。不过推荐使用express+xTemplate的组合,xTemplate能做到前后端公用。

  怎么用Node大家自己决定,但是令人兴奋的是,我们终于可以使用Node轻松实现我们想要的输出方

  为了尽可能的简单,将Subscriber简化如下:

  publicabstractclassSubscriberimplementsObserver{

  publicvoidonStart(www.gouyily.cn){

  Observable(订阅源)

  Observable(订阅源)在RxJava里面是一个大而杂的类,拥有很多工厂方法和各式各样的操作符。每个Observable里面有一个OnSubscribe对象,只有一个方法(voidcall(Subscriber subscriber);),用来产生数据流,这是典型的命令模式。

  publicclassObservable{

  finalOnSubscribeonSubscribe;

  privateObservable(OnSubscribeonSubscribe){

  this.onSubscribe=onSubscribe;


  publicstaticObservablecreate(OnSubscribeonSubscribe){

  returnnewObservable(onSubscribe);

  }

  publicvoidsubscribe(Subscriber subscriber){

  subscriber.onStart();

  onSubscribe.call(subscriber);

  }

  publicinterfaceOnSubscribe{

  voidcall(Subscriber subscriber);

 

  实践

  到此,一个小型的RxJava的雏形就出来了。不信?我们来实践一下吧。

  Observable.create(newObservable.OnSubscribe(){

  @Override

  publicvoidcall(Subscriber subscriberwww.weicaiyule.cc){

  for(inti=0;i<10;i++){

  subscriber.onNext(i);

  }

  }

  }).subscribe(newSubscriber(){

  @Override

  publicvoidonCompleted(www.feifanyule.cn){

  }

  @Override

  publicvoidonError(Throwablet){

  }

  @Override

  publicvoidonNext(Integervar1){

  System.out.println(var1);


  添加操作符

  其实,强大的RxJava的核心原理并没有想象中那么复杂和神秘,运用的就是典型的观察者模式。有了基本雏形之后,我们继续为这个框架添砖加瓦吧。RxJava之所以强大好用,与其拥有丰富灵活的操作符是分不开的。那么我们就试着为这个框架添加一个最常用的操作符:map。

  那么RxJava是如何实现操作符的呢?其实,每调用一次操作符的方法,就相当于在上层数据源和下层观察者之间桥接了一个新的Observable。桥接的Observable内部会实例化有新的OnSuscribe和Subscriber。OnSuscribe负责接受目标Subscriber传来的订阅请求,并调用源Observable.OnSubscribe的subscribe方法。源Observable.OnSubscribe将Event往下发送给桥接Observable.Subscriber,最终桥接Observable.Subscriber将Event做相应处理后转发给目标Subscriber。流程如下图所示:

  这里写图片描述

  接着,我们用代码实现这一过程。在Observable类里面添加如下代码:

  publicObservablemap(Transformer

posted @ 2017-05-11 12:00  王二狗的人生  阅读(2190)  评论(0编辑  收藏  举报