从业时间越久,发现互联网很多知识都是错的, 对小白误导有多深?

2022-04-18 22:04:26 +08:00
 jeesk
说说我自己的看法, 无论是 csdn 还是知乎, 在我最开始从业 java 的时候,觉得他们说得没有毛病? 从业几年后,发现很多都是在鬼扯。 就拿 BIO 和 NIO 谁性能好, 知乎上面竞争激烈,下面我粘贴一个知乎的回答。

回答 1:

首先要明确一点:nio 的适用于 io 高并发场景线程开销包括:内存开销(创建一个线程需要为其分配和维护一个 tcb 线程控制块保存上下文,一个线程私有的栈)、线程上下文切换的时间开销(保存上下文,加载下一个线程的上下文),在高并发环境下多出来的这一点点开销积累起来是非常可观的。若使用 bio ,高并发必然引起激烈 contention ,导致大量的上下文切换,若采用一个 io 一个线程模型,一个线程 M 级的空间消耗,内存消耗不起。而 netty 采用 nio 加 selector 加线程池基本上解决了上述问题:一是线程池限制了内存消耗,二是采用 selector 使得只有处于活动状态的 io 才会去占用线程,不会使线程白白因为 io 而阻塞,提高了线程利用率。

说说他们的谬论:
1. 使用 BIO 上下文切换厉害, 如果是相同 4 核 cpu , 无论我是用 bio 还是 nio ,都用 200 个线程, 这个时候对 cpu 的竞争到底有多剧烈? 我个人觉得差不了多少。 所以这个说法是错的。

2. 若采用一个 io 一个线程模型,一个线程 M 级的空间消耗。 这个就更扯淡了。 即使是 tomcat 在 8.5 以前也是 BIO 200 个线程, 都没有用到 1w 个线程? 为什么非要扯开大量线程呢? 并且 tomcat 在 8.5 以后才默认 nio.

3. 一是线程池限制了内存消耗,二是采用 selector 使得只有处于活动状态的 io 才会去占用线程. 那我 tomcat 用 BIO 没有内存限制? 没有内存限制岂不是早就宕机了? 再说说 selector 的问题, 我 NIO 在 readSelector 开 10 个线程去调用 select, 不都是阻塞的吗? 怎么会说在活动状态才占用线程?

然后你会发现这些错误的回答有很多,下面还有大量的小白点赞,觉得说得很对。 但是一经脑子思考就发现, 这绝对是坑 B.

如果有不同意见的小伙伴可以留言,我觉得这个可以作为一个面试题。
17792 次点击
所在节点    Java
154 条回复
Narcissu5
2022-04-19 15:14:34 +08:00
异步不纯粹就纯粹不异步,java 这种提供一部分接口然后就没有了的方案缺失很鸡肋。尤其是 jdbc 没有异步接口是个绕不过去的问题。当然你可以开线程池,最后就发现大量线程还是 block 在数据库上
jeesk
2022-04-19 15:16:33 +08:00
@lmshl 大部分应用都是 io , 只有交易撮合, 广告竞价,算法之类的应用是 cpu 应用。
byte10
2022-04-19 18:41:34 +08:00
@Jekins 可以看看那个 B 战-小巫老师,视频:NIO 场景和实战,有很多场景和代码验证。还有一个 NIO 服务的绝对优势,看完你就知道小白的问题在哪里了。里面还有一个多线程的讲解,也有代码验证 《最大线程数计算公式》的例子。大多数人都不知道怎么去理解 NIO ,他们以为 用上 tomcat 8.x 后的就以为用上了 NIO 了,实际上还差一些。

@xxfye 正确,回答正确。tomcat NIO 要开 200 个线程,那是因为业务层“一般”一般一般依然使用阻塞模型,如果使用异步模型,那么只要少量的线程即可,但是需要使用者去主动设置。

关于网上说的:bio 上下文竞争比 nio 强烈 。因为 NIO 一般只需要设置等于 cpu 核心数即可,BIO 需要设置大量的线程,所以结果是:bio 上下文竞争比 nio 强烈。因果关系没搞明白吗?

如果你想测试多线程开销到底有多大的影响,我代码中有给出例子,你可以使用 TestMaxThreadNum.calculationCpuTime() 去验证,第一次设置 cpu 核心数量,第二次设置 2000 个线程,你就会发现 2000 大量的线程 跑起来没有线程数量少的快( cpu 密集型情况下)。所以 ”线程数量多“ 的上下文竞争 会比 ”线程数量少“ 的厉害,性能会有所下降。

另外 BIO 上下文竞争是否会比 NIO 厉害,这里要区分情况,如果 BIO 线程中经常出现 IO 等待,那么不会有特别多的线程竞争。只有在 IO 时间短,且存在大量的线程的情况下,才会出现这样的情况。要减少这种情况,就需要在业务 IO 时间短的时候,使用少量线程,这不好设置和判断。而 NIO 则可以无视 IO 时间,我在视频中有讲过。

能救一个算一个。
sampeng
2022-04-19 18:52:13 +08:00
我觉得有个逻辑很多人是不知道的。。都是盲目开线程数。也不管是不是 nio 还是 bio 模型。
另外,其实在正常情况,只要你的接口足够快,哪怕 2 个线程都够用。
lmshl
2022-04-19 19:40:04 +08:00
大多数人都是先把线程池用💩了,再学美团动态线程池💩上雕花,并不知道一开始就把事情做对,反而去质疑教科书是不是写错了。
statumer
2022-04-19 20:02:29 +08:00
再说个有意思的事,OP 提到的这个回答我找了下原地址

为什么 nio 效率会比 bio 高? - 锭阳的回答 - 知乎
https://www.zhihu.com/question/59356897/answer/165104063

也就 15 个人点赞,排名也很靠后。并没有很多小白点赞嘛。

[Imgur]( https://imgur.com/sGShzm3)
rahuahua
2022-04-19 20:32:07 +08:00
1. 使用 BIO 上下文切换厉害, 如果是相同 4 核 cpu , 无论我是用 bio 还是 nio ,都用 200 个线程, 这个时候对 cpu 的竞争到底有多剧烈? 我个人觉得差不了多少。 所以这个说法是错的。

都用 200 个线程......
jeesk
2022-04-19 21:15:54 +08:00
@statumer 这个回答是第一名。 不知道为什么。
jeesk
2022-04-19 21:26:11 +08:00
@lmshl 压榨? 有测试代码吗? 还是你随口说的? 我测试过 webflux 和 servlet 差距并不大。 可以看看我回复里面的压测文章, 发在简书里面的。
jeesk
2022-04-19 21:26:24 +08:00
@sampeng 你说的是对的。
jeesk
2022-04-19 21:27:30 +08:00
@rahuahua 我是说假如。 并不是真的。 我们生产有些应用线程直接使用的核数。 因为是 cpu 密集应用。
jeesk
2022-04-19 21:40:10 +08:00
@sampeng 你说的不就是 redis 吗 😆
maximum2012
2022-04-19 21:51:31 +08:00
@seagull7558 他不是翻译的核心力量,他基本上就是打杂的
jeesk
2022-04-19 21:54:58 +08:00
tomcat 的 nio 并不是全部是非阻塞的,分为 4 部分, 读请求头,读 request body ,写响应头和 body , 等待下一个连接,只有读 request body 和写请求头 body 体都是阻塞的。
lmshl
2022-04-19 21:57:56 +08:00
@jeesk 有做过社区分享,数据是 Prometheus 实时采集的 3 Pod CPU 合计,TPS 也是来自 Ingress 和 服务内暴露的。
我的应用是全异步,包括 HTTP 和 RPC 调用,数据库访问走 hikaricp JDBC 链接池,但技术栈是 Scala 这边的,Akka Stream 混合 ZIO 纤程调度,线程池仅有 N 个 fiber scheduler + 2N 个 Blocking 。
lmshl
2022-04-19 22:01:59 +08:00
Scala 生态里的 HTTP Body 读写都是纯异步的😏
chihiro2014
2022-04-19 22:57:39 +08:00
@jeesk webflux 只是更抗压而已,个人感觉它的背压机制,只是一种限流优化而已。国外 Josh Long 也说过,其实 Webflux 只是一种对多线程的更好封装=。=
zeni123
2022-04-20 06:08:07 +08:00
都用 200 个线程池 。。。
zeni123
2022-04-20 06:09:03 +08:00
就好像在问一公斤铁 一公斤棉那个重
defage
2022-04-20 08:44:48 +08:00
lz 不觉得在说“也差不多”,“差不大”的词的时候非常不严谨么。如果你拿普通 crud ,只是做完能跑起来,用这些没问题的。
本来就在论严谨的问题,放在当下内存动不动就是 32G 的时代,当然可以说都差不多了咯。

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

https://ex.noerr.eu.org/t/847761

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

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

© 2021 V2EX