我来说说异步框架的最大缺点

2021-04-20 16:04:09 +08:00
 balabalaguguji

异步大家都在夸,都在说他的好处,但是似乎没人说过他的最大缺点,我来说说吧,避免踩坑。

异步因为是只有一个线程,如果有一个地方阻塞了,那整个网站全部都卡住了(多进程的另说),所以你得时刻记得,如果会阻塞的方法,就得用异步的库。另外还得确保别写出死循环的逻辑,不然也是卡住整个站。

异步现在支持最好的应该是 nodejs 吧,各种异步库都有,但是 python 的支持就少很多了,如果用 gevent,猴子补丁不能帮你把所有的接口都补成异步的,所以你得清楚什么方法是可以用的,例如 commands 这个就不能用,没打补丁,可以改用 subprocess 。

写异步的代码时得时刻提醒自己以上问题,但是如果用多线程模型,就不用担心这些,如果你的网站不是特别大的访问量,可以使用多线程模型,够简单;如果是需要高并发,有大量用户,可以用异步框架并始终记住不要用阻塞方法。

如果说得不对的地方,请大家指点。

15787 次点击
所在节点    编程
153 条回复
MaxJin
2021-04-21 10:35:23 +08:00
。。。js 是单线程,node 是多线程
SystemLight
2021-04-21 10:42:16 +08:00
协程只是异步的其中一种实现,多线程同样可以实现异步,而且多线程配合协程实现的异步方式性能非常高,不但解决了 CPU 密集同时还让 IO 密集型尽力节省出 CPU 上下文切换带来的损耗,这一点我感觉.NET5 的 web 框架是做的最好的。
lllllliu
2021-04-21 10:47:08 +08:00
A 等 B,B 又是个事件监听,不知道什么时候发生,也不能返回,也不能让 A 抢掉这个监听。
这玩意在 Node 里写起来贼难受哦。只能强行加 flag+setInterval 1ms.
lllllliu
2021-04-21 10:51:52 +08:00
Node 就是没有一个能 hold 住的方法。很难受。不像 go 可以 wait
guyeu
2021-04-21 10:52:26 +08:00
你说的这算什么缺点啊。。。哪怕是纯多线程,你写出了一个死循环或者死锁,就能保证它只阻塞一个线程不影响其他线程?
还有,异步和多线程并不存在任何冲突,思维不要被单一语言限制,从原理上讲这俩就不是一个维度的东西。

目前的操作系统只提供了多线程和多进程的调度支持,如果要实现异步,要么是如你所言线程池(单线程也是一种线程池)+回调的方式,要么是 go 这种自行实现了一套协程的调度模型,但这两种最终的落脚点都在操作系统的线程上,因此就目前而言,各种异步编程的实现方式都是对多线程去阻塞的优化,目标还是完美利用多核算力。

一般而言,公认异步的缺点主要有以下两种:
1. 对同步代码的破坏性改动,绝大多数异步 API 都具有传染性,类似各种语言的 async 关键字,各种异步库的 Future/Promise/Mono,都不可避免通过函数签名的方式传染调用方( go 这方面就好很多);
2. 复杂调度和竞争导致的延时,同步可以不用做其他事专心等阻塞逻辑的结果就好,异步就得等线程 /协程调度的结果,让你这个回调执行才能轮到执行,当并发量大的时候长尾效应还是很严重的。
xiubin
2021-04-21 10:53:41 +08:00
@balabalaguguji #101 那这个问题的本质就不是异步了呀,单线程模型你不用异步,有耗时的任务照样会卡住的啊,有死循环不是照样会卡死吗?
kksco
2021-04-21 11:05:40 +08:00
go 吹来了,go 最大的特点就是所有的代码都是同步的逻辑去写的,非常自然,不用考虑什么 async await 这种关键字,写过 js py go rust,go 这块是做的最好的。异步最大的缺点就是反智。。但是现在也成为了主流,基本都还是要懂要会用。。
lonelymarried
2021-04-21 11:08:56 +08:00
我已经习惯异步了,不是异步的我会纳闷怎么写
elintwenty
2021-04-21 11:15:26 +08:00
主题应该加上限定的语言或框架,Java 可以做到多线程异步非阻塞
异步和多线程没有关系,阻塞和异步也没有关系
阻塞导致当前线程卡死不是异步的问题
而且多线程不见得比异步代码好写,只能说明还没遇到多线程的问题而已
leexy
2021-04-21 11:30:07 +08:00
PHP 是最好的编程语言
hejingyuan199
2021-04-21 11:42:07 +08:00
@balabalaguguji 感谢回复。明白了。
对于多线程我只用过 java 和 c++。
nodejs 我虽然在用,但我知道他是单线程同时 IO 非阻塞,那是因为它利用了多条 IO 线程,但这些线程不属于 js 线程而已。
balabalaguguji
2021-04-21 11:46:44 +08:00
@LessonOne #119 那请教下正确的是怎样
balabalaguguji
2021-04-21 11:47:50 +08:00
@czzhengkw #120 都是程序员,不用那么高情商,直接怼
balabalaguguji
2021-04-21 11:52:30 +08:00
@MaxJin #121 又去了解了下,应该说是 nodejs 的代码执行是单线程的,IO 是多线程的
balabalaguguji
2021-04-21 11:53:36 +08:00
@SystemLight #122 感谢科普,之前一直以为.NET 很落后
mmqc
2021-04-21 11:54:29 +08:00
C# 中采用 TAP 的模式去写代码,在可能会出现耗时的地方,直接通过 Task 的调度来手动调度一个额外的线程,来承载具体的业务。而调用 Task 的线程,还是可以继续处理其他问题啊。node 之类的应该也会有类似的机制吧?
所以我没太看明白,为什么一个卡死,会造成全站崩……
1more
2021-04-21 12:23:07 +08:00
Rust 的 async/.await 用着非常舒服,写代码用同步风格就可以
iyaozhen
2021-04-21 13:05:50 +08:00
其实这主要是同步语言、比如 Python 这种后来加了异步的,就很烦。就像 java 一样要考虑这个是不是线程安全啥的。

node 、go 这种天生异步的好很多
ipwx
2021-04-21 14:00:44 +08:00
@balabalaguguji 101L

“@xiubin #79 不用异步那就是多线程模型,每个用户进来都是一个独立的线程,卡死也是卡死他自己的,其他人不受影响,而异步是所有人都受影响,这个估计很多新人是不知道的。死循环只是一个卡死的举例”
----

如果只是这个模型的话确实,多线程好写。但是逻辑复杂一点,经常是各种线程互相协作的时候,你会发现多线程模型、线程池,写起来都经常死锁 bug 。。。 这时候异步、await 、甚至 actor 反而更好写了。
yazinnnn
2021-04-21 15:40:05 +08:00
看了本楼讨论,感觉 vertx 的异步还挺好用的....
嗯,本来 vertx 也算是 nodejs 的一种 java 实现

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

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

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

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

© 2021 V2EX