响应式编程确实有点看不懂

213 天前
 yuhongtai114514
因为 spring cloud gateway 里用了 project reactor 所以就去研究了一番,但是越看越模糊,只知道它的一些用法,比如在数据流上设定操作符(如 flatMap),然后当调用 subscribe 时,这一系列操作符就会被执行。但这个和普通的回调有什么区别呢,为啥说它是异步非阻塞的?

再比如在 spring cloud gateway 里,filter 返回的都是 Mono,当 reactory-netty 收到网络请求时,调用 subscribe ,触发 filter 返回的 Mono 中设定的一系列操作。但是实验了一下,发现 filter 之间也是串行阻塞的:
[在一个 filter 返回的 Mono 的 flatMap 中写下 Thread.sleep(2000L),发现在该 filter 后面的所有 filter 也被阻塞了。但是 gpt 告诉我 filter 之间可以是并行的,因为用了 project reactor ]

想问问这是为啥,感觉始终没有正确理解响应式编程,想问问 v 友们~
7243 次点击
所在节点    Java
44 条回复
BBCCBB
213 天前
可以先理解下 js 里最开始的 callback hell, 然后再看看 Promise 的出现解决了 js 的什么问题. Promise 可以理解成一个最简单的响应式..

一定程度上解决了 callback hell, 然后加了一些方便开发的 operator 方法.

不建议看这个东西.. 协程才是正路.
b1t
213 天前
我看 Spring Cloud Gateway 的时候跟你的感觉是一模一样的,然后我就放弃了
b1t
213 天前
op 如果找到响应式编程的学习方法,记得 @一下我(逃
statumer
213 天前
Project Reactor 这些东西就是 monad 在 Java 里的实现。需要这个东西的根本原因是 Java 没有协程,非得用纯函数这种不自然的形式构造状态机。
现在没什么学的必要了,如果进展理想的话协程在 Java 世界中会迅速普及。
btw ,回复一下主楼里的问题,你转述的 gpt 的说法是完全错误的,可以自己找本书看或者看 Project Reactor 的 reference ,第三章很好地阐释了基本思想。
weijancc
213 天前
在 Spring Cloud Gateway 上开发的代码看着真恶心
SilenceLL
213 天前
原来大家都看着难受,说明是真的难受
iOCZ
213 天前
不要过分依赖 GPT ,它撒起谎来还有板有眼的
chendy
213 天前
可以在业务不复杂,对性能又有一些要求的场景使用
不能用同步语法写异步就是坐大牢
iovekkk
213 天前
按我的理解,响应式编程的意义就是可以把某一个代码块或者函数当做参数,而这一段代码块或者函数的逻辑,可以放到任何地方去实现
mgcnrx11
213 天前
因为 op 把“响应式 Reactive” 和 “异步非阻塞” 的概念 混淆为 它两个是一个意思了

Project Reactor 的响应式里面,当 subscribe 时,一系列的操作会一个接着一个去执行。但这些操作都是我们自己写的代码,还是需要确保这里自己写的代码是“非阻塞”的才行。否则,就会像你举例的一样,sleep(2000L)后发现阻塞了。
还有的是,除非显式的调用 publishOn / subscribeOn 等方法呢,否则都是在调用 subscribe 的当前线程上执行的。也就会造成该线程被 sleep 阻塞起来的感觉

> 但是 gpt 告诉我 filter 之间可以是并行的

这是错误的
afeiche
213 天前
spring 那一套和阻塞线程参合在一起,不太好理解,你可以看看 vert.x ,参考 nodejs 搞的,理解起来会容易一点,我没看你过 project reactor ,估计和 vert.x 差不多,底层应该都是 netty 。
ccde8259
213 天前
想搞响应式编程的话,以生产者-消费者模型为基础,得先入门一下函数式编程,再开始理解值容器也就是 Monad……太难了还是别学了
des
213 天前
我还以为只有我一个人是这样呢,看的难受
msaionyc
213 天前
理解起来确实费劲,从声明,订阅( subscribe ),请求,执行,正向->逆向->正向->逆向,最后又到正向执行,太绕了。
而且也不好 debug
Helsing
213 天前
RxJava 和 Reactor 的思想是类似的,推荐一篇写的很好的关于 RxJava 的文章,希望对你有帮助:

https://juejin.cn/post/6844903670203547656
srx1982
213 天前
简单的需求还行,如果需求复杂,还要在不同阶段读取多种数据源,那就麻烦了
mikasa1024
213 天前
之前基于 srping gateway 开发了一个网关管理系统,感受就是业务很难写,到最后只是连着数据库做了个简单的增删查改,然后和网关路由同步起来

下次有这种需求,我会选择使用 openresty 或者 apisix ,选择 openresty 用 lua 开发的体验应该也比 gateway 的这个响应式强
Leviathann
213 天前
Brian Goetz: "I think Project Loom is going to kill Reactive Programming"
GiantHard
213 天前
> 比如在数据流上设定操作符(如 flatMap),然后当调用 subscribe 时,这一系列操作符就会被执行。但这个和普通的回调有什么区别呢

没有区别,这些操作符就是在帮助你设置回调函数

> 为啥说它是异步非阻塞的

因为 Operator 的执行线程可以由 Scheduler 决定,所以说 Rx (ReactiveX, 响应式编程 API) 可以实现异步非阻塞

https://projectreactor.io/docs/core/release/api/reactor/core/scheduler/Scheduler.html

> 一个 filter 返回的 Mono 的 flatMap 中写下 Thread.sleep(2000L),发现在该 filter 后面的所有 filter 也被阻塞了

Thread.sleep 是「阻塞的 api 」,你可以试试使用 Rx 的 delay https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html#delay-java.time.Duration-

除了 Thread.sleep 之外,Java 世界中有很多库的 API 都是阻塞的,要在 Rx 世界中流畅使用,得自己找对应的 Rx 实现
yazinnnn0
213 天前
https://www.reactivemanifesto.org/zh-CN

响应式和异步非阻塞没啥关系

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/979656

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX