Spring WebFlux 要革了谁的命?

 mp.weixin.qq.com
托梦

Java国王昨晚做了一个梦。

梦中有个白胡子老头儿,颇有仙风道骨, 告诉他说:“你们Java啊,实在是太弱了,连一个基本的功能都实现不了!”

国王大为惊奇:“什么功能是我堂堂大Java搞不定的?”

老头儿展示了两行代码:

float salary = 1000;float tax =  salary * 0.1;

国王说:“这不很正常吗,薪水(salary)是1000, 税(tax)等于100,我国小学生都能算出来。”

老头儿说:“我要是现在让salary=2000,那tax等于多少啊?”

“还是100! 因为tax没有被重新计算!”

“薪水变了,为什么税不变呢? ”

“这个......”

看到国王不说话了,老头儿继续说:“你们得建立变量tax和变量salary之间的关联,让他们像Excel一样,一个单元格的值变了,Excel的公式自然会更新另外一个单元格,让它随之变化。”

float salary = 1000;//假设这个命令建立了tax和salary之间的关联float tax <=  salary *0.1salary = 2000 ;assertEquals(200,tax);  //现在tax自动变成了200

国王说道:“你这么做有什么用啊,再说这也不是Java的问题,所有的语言都有这个问题啊......”

仙风道骨的老头儿没有回答, 慢慢消失了。

发布-订阅模式

第二天早朝,国王给大臣们讲了自己这个奇怪的梦,看看谁能帮自己解一解, 没想到大臣们七嘴八舌,说自己也做了同样的梦。

这就奇怪了,难道有神灵故意给大家托梦吗? 在梦中,仙人老头儿给大家举的例子都是一模一样的。

集合大臣小心翼翼地说道:“难道他是在暗示我国的税收太高了吗, 有10%,要降低一点?”

国王瞪了他一眼:“胡说些什么?我们的税一点都不高,起征点提高到了5000,除了五险一金扣除,我们还有房贷减免,租房减免,独生子女减免,赡养老人减免等一系列政策, 怎么能叫高呢?”

集合大臣赶紧噤声。

IO大臣继续说:“陛下不用烦恼,老头儿说的问题,我们Java早已经提供了对应的解决方案,那就是发布者-订阅者模式啊。如果把Salary当成一个数据源的发布者, 把Tax当成一个订阅者,注册到Salary当中, 每当Salary有变化,就发送一个事件给Tax,Tax收到后,做相应的计算就可以了。”

“这不就是一种把数据持续推送给观察者或者订阅者的一种模式嘛,这种小儿科的东西,有什么用?” 老对头线程大臣说道。

“在这个场景下确实没啥用处,但是这种事件流的方式,如果处理好了,也许能解决大问题。” IO大臣虽然不太服气,但是也想不出什么好的应用场景出来。

高并发

国王看到两个老家伙又要干起来,马上转移话题:“听说我们Java在高并发方面遇到了一点儿问题?”

IO大臣立刻兴奋起来,顺杆就爬:“没错,这二十来年,我们Java一直使用Tomcat那种线程池的方式,现在在越来越差劲了,难以应对高并发了。”

这一下子把Tomcat大臣,线程大臣,甚至Servlet大臣都给拉了进来,国王暗自后悔。

IO大臣继续侃侃而谈:“现在的模型每来一个请求都会有一个线程来处理,如果这个请求涉及到IO或者网络操作,这个线程不得不阻塞等待,没法干别的事情。”

“如果用户的请求太多,那线程池中的线程很快就会被用光。这时候就没办法对外提供服务了。”

这确实是实情,基于Servlet的线程模型,就是这么工作的。

国王问道:“那个线程调用RPC服务的时候,为什么要等待呢? 让它去干别的事情,比如处理另外一个请求不就可以了?”

“陛下圣明,这就是关键所在,要充分地利用线程,一点出现IO调用,立刻走开,去干别的事情,等到IO调用结束了,就可以通知线程去处理,这样我们用少量的线程,就可以实现大量的并发了。”

国王说:“爱卿言之有理,你已经可以实现这种NIO的方式了,对吧?”

“没错,现在我们要做的就是要改造Tomcat,改造甚至替换Servlet !”

回调地狱

Servlet大臣一听就急了,自己就是传统的工作方式,一个请求一个线程,要是这么搞,自己位置不保,他把目光投向了忠实的盟友线程大臣。

线程大臣心领神会:“IO大臣的办法其实就是把同步的阻塞调用改成异步的非阻塞调用,不是那么容易啊,别的不说,这异步编程,对我们臣民来说就很不容易。”

“你不是有什么Future,Callable之类的东西吗? 可以让臣民们去用啊!”  IO大臣不依不饶。

线程大臣笑了:“你是只知其一,不知其二,当你调用那个future.get()的时候,如果线程的工作(例如数据库查询)还没有做完,当前线程还得等待,还是阻塞的。”

IO大臣有点儿后悔,自己怎么忽略了这一层呢?

线程大臣趁胜追击:“还有啊,即使是按你所说,所有的操作都是异步的,都是事件驱动的,那回调会大量存在,这代码中回调地狱问题,你考虑了吗?”

fun1(param,new Callback(){    void onSuccess(...){        ......执行业务逻辑......        fun2(param,new Callback(){              void onSuccess(...){                ......执行业务逻辑......                fun3(param,new Callback(){                    void onSuccess(...){                        ......执行业务逻辑......                        fun4(param,new Callback(){                            void onSuccess(...){                                ......执行业务逻辑......                                                          }                            void onError(...){                            }                        });                    }                    void onError(...){                    }                });            }            void onError(...){            }        });    }    void onError(...){    }});

IO大臣看到这如同乱麻般的代码,头嗡的一声就大了,这异步操作居然这么变态!

国王看到IO大臣神色有异,不再说话,赶紧宣布退朝。

事件流

在朝堂上很郁闷的IO大臣怒气冲冲地回到了家,下人送上的茶水也被他打翻在地。

幕僚已经了解今日朝堂发生之事,走上前来:“大人息怒,小人听说民间有个叫做Reactor的东西,用什么事件流和函数式编程中的高阶函数,就能解决这个回调地狱问题。”

事件流? IO大臣突然被点醒了,我怎么没想起这茬儿, 昨天仙人托梦不就是引导我用事件流吗?

他赶紧问道:“具体是怎么做的?”

“我们用图来表示,一个事件流是这样的, 在这个时间线上,还有Error事件和Complete事件,分别用来表示出错和完成,我就不画了。”

“了解,可是这又有什么用呢?” IO大臣问道。

“可以使用函数式编程对这个事件流做变换,例如map,把事件从‘圆圈’ 变成了‘三角’”

“还可以用filter对事件流做过滤”

“嗯, 看起来很清楚,我想到一个场景, 先调用函数1,产生了事件流,然后对事件流中的每个元素,又要调用函数B,又产生了新的事件流,该怎么办? ”  IO大臣问道。

“大人真是厉害,抽象思维能力极高! ” 幕僚适时地拍了一下马屁,“这时候可以用flatmap,把新的事件流给平铺了。”

“map, filter, flatmap 仅仅是最基本的操作,还有switch , take, merge,zip等很多运算符,你想要的功能都能满足!”

“不错,不错,” IO大臣兴奋地直搓手,他已经把握住了其中的关键思想,回调地狱可以被解决了。

比如原来的需求是先异步调用fun1,  根据fun1的结果调用fun2, 只能这么写:

fun1(param,new Callback(){    void onSuccess(...){             fun2(param,new Callback(){              void onSuccess(...){                ......            }            void onError(...){            }        });    }    void onError(...){    }});

现在假设fun1 返回的是数据流,fun2返回的也是数据流,用这种新的方式,可以写成这样:

fun1(param).flatMap( e -> func2(e)).subscribe(r -> showResult(r),       error -> handleError(error));

相当于把这一系列的回调给压平了!

IO大臣问道:“你刚才说的民间的那个软件叫什么来着? ”

“民间很多的,有RxJava, Reactor,要不要我把他们的负责人叫来聊聊?”

“慢着,光是这个Reactor, 用处不大,你把Spring大臣也请来,我们需要让Spring去使用Reactor,抛弃Servlet, 把所有的请求和处理都变成异步处理!”

新框架

三个月后,IO大臣喜气洋洋地向国王汇报:“陛下,臣已经解开了仙人所托的梦,那其实是让我Java帝国实现反应式编程(Reactive Programming)!”

“反应式编程? 这名字有点古怪!”

“对,这种方式是基于事件流和函数式编程的, 可以让我们用非阻塞的、异步的方式来处理请求,还能解决回调地狱的问题。”

IO大臣把Reactor给国王讲了一遍。

“那这个Reactor该如何使用? ”

“陛下还记得我们Java的高并发问题吧,就是由于没法有效地管理异步和回调地狱导致的, 现在好了,臣和Spring携手做了一个叫做Spring WebFlux的东西,献给陛下,它不用Servlet,可以实现非阻塞的IO,可以有效地应对高并发。 ” IO大臣展示了一幅图。

Servlet大臣一看,脸都绿了:我的位置在哪儿?

Tomcat大臣也觉得不爽,原来自己一家独大,现在被Netty给挤走了。

只有JDBC大臣还不慌不忙:“用异步非阻塞处理所有东西? 你省省吧,我这里访问数据库还是阻塞的呢!”

IO大臣心中暗叫不妙,怎么忘了JDBC这么重要的东西,既然想实现异步、非阻塞,那一定是端到端的,全链路的实现,某个点的阻塞调用都会导致整体出问题。

可他还是保持了镇静:“不用担心,民间的开源社区很快就会搞出来非阻塞的JDBC驱动的。”

国王看到这个新的Spring WebFlux简直是要革了好几个大员的命,也只好安抚一下Tomcat, Servlet:“这样吧,新事物总得有个渐进的采纳过程,我们让Spring MVC和Spring WebFlux 并存一段时间,让臣民们按照自己的实际情况来选择吧!”

后记:本文中托梦中的例子来源于:http://blog.leapoahead.com/2016/03/02/introduction-to-reactive-programming/  我做了改编。

转载于:https://www.cnblogs.com/bigben0123/p/10494246.html

Spring WebFlux 要革了谁的命?相关推荐

  1. 什么是Spring WebFlux?

    原创: 码农翻身刘欣 码农翻身 托梦 Java国王昨晚做了一个梦. 梦中有个白胡子老头儿,颇有仙风道骨, 告诉他说:"你们Java啊,实在是太弱了,连一个基本的功能都实现不了!" ...

  2. 爸爸又给Spring MVC生了个弟弟叫Spring WebFlux

    作者:李新杰 来自:编程新说 情景引入 很早之前,Java就火起来了,是因为它善于开发和处理网络方面的应用. Java有一个爱好,就是喜欢制定规范标准,但自己又不善于去实现. 反倒是一些服务提供商使用 ...

  3. Spring Webflux: Kotlin DSL [片断]

    原文链接:https://dzone.com/articles/spring-webflux-kotlin-dsl-snippets 作者:Biju Kunjummen 译者:Jackie Tang ...

  4. Spring WebFlux和Spring Cloud开发响应式微服务

    作者:Piotr Mińkowski 译者:大萝卜爱上小白菜 原文:https://dzone.com/articles/reactive-microservices-with-spring-webf ...

  5. Kotlin 协程 + Spring webflux 开发后端

    前言 后端响应式是未来,吞吐量会更大,而资源占用更少,其用到了类似Android系统的Loop(事件循环)机制,而协程可以减少线程等待的消耗,并且同步式的编程方式使代码可读性更高,两个仿佛天生就是一对 ...

  6. MyLiveSearch:它将会革掉Google的命?

    原文: http://www.gseeker.com/50226711/mylivesearchieaeegooglecie_97167.php 我们现在所使用的绝大部分的搜索引擎的工作原理都大同小异 ...

  7. Kotlin 和Spring WebFlux

    Kotlin 是一种来自JetBrains 的面向对象的语言,它支持函数式编程.它的主要优势之一是与Java 有非常高的互操作性.通过引入对Kotlin 的专门支持,Spring 在V5 中全面吸纳了 ...

  8. spring react_使用Spring WebFlux构建React性REST API –第1部分

    spring react 在本文中,我们将看到如何使用Spring WebFlux构建响应式REST API. 在进入React式API之前,让我们看看系统是如何发展的,传统REST实现遇到的问题以及 ...

  9. spring react_使用Spring WebFlux构建React性REST API –第3部分

    spring react 在上一篇文章的续篇中,我们将看到一个应用程序以公开React性REST API. 在此应用程序中,我们使用了 带有WebFlux的Spring Boot 具有响应式支持的Ca ...

  10. aws dynamodb_带有AWS DynamoDB的React式Spring Webflux

    aws dynamodb AWS已经发布了Java版本2的AWS开发工具包 ,该开发工具包现在支持针对不同AWS服务的API调用的非阻塞IO. 在本文中,我将探讨如何使用AWS开发工具包2.x的Dyn ...

最新文章

  1. Linux2.6--Linus电梯
  2. quantrader和matlab不匹配,【Matlab量化投资】支持向量机择时策略
  3. vue中如何进行Excel文件的下载
  4. 02_常用正则表达式
  5. 2018年江苏省计算机小高考,江苏2018年小高考成绩查询系统网站入口:江苏省教育考试院...
  6. java操作_JAVA操作文件大全(一)
  7. solr 3.5 配置及应用(二)
  8. python 程序运行计时 动态,在python中运行计时器几分钟
  9. [置顶] J2EE (八) 策略模式+装饰模式+反射(java)
  10. 文档开发工具调研总结
  11. TypeScript:运算符
  12. 【鲲鹏HCIA考试】随堂习题卷六
  13. WHQL之无需HLK结果就可获得微软驱动数字签名+Cannot specify [ClassInstall32] section解决
  14. 【luminate primordial】苏州之行
  15. python实现舒尔特方格
  16. win7系统ftp服务器密码修改,win7 ftp服务器密码
  17. c语言 强制退出程序,C#实现点击按钮退出应用程序实例
  18. 深度学习入门之神经网络的学习思维导图
  19. js解析json js获取json里面的某个节点的数据 js解析json数据
  20. PPI (手机屏幕的PPI 和计算方法)

热门文章

  1. smale学习之数学表达式(day2)
  2. 在SQL Server中建立主键外键的关系
  3. Matlab的数据类型及相互转换
  4. VMware资源集合,分享一波
  5. 每天10个Linux命令四
  6. 上传项目到GitLab
  7. html tooltip 换行,echarts在tooltip中换行操作
  8. function signature是什么
  9. fisco bcos Caliper部署 错误总结
  10. php session失效