V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
jeesk
V2EX  ›  Java

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

  •  
  •   jeesk · 2022-04-18 22:04:26 +08:00 · 17125 次点击
    这是一个创建于 985 天前的主题,其中的信息可能已经有所发展或是发生改变。
    说说我自己的看法, 无论是 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.

    如果有不同意见的小伙伴可以留言,我觉得这个可以作为一个面试题。
    第 1 条附言  ·  2022-04-19 21:46:42 +08:00
    关于我的帖子的一些说法错误

    1.nio 和 bio 的内存占用问题,理论上能用少量线程占用内存少,其实我测试过即使开到 200 甚至 2000 ,内存占用变化不大。 可能是我代码测试问题?
    2. 在使用 tomcat 的 nio 的时候使用 200 线程我是假设。 我们生产应用的线程有些直接用的 cpu 核心数,或者核心数*2.
    3. 关于阻塞问题我应该是理解错了。 nio 为什么能够使用 20 线程代替 bio 200 线程, 因为 nio 不会阻塞线程, 事件来了就处理。 而 bio 是会阻塞。

    关于回复里面有些错误说法:

    1. nio 性能压榨 bio , 其实是错的。我自己用 4 核 8g 的服务器测试过。webflux 并不能缩短应用处理时间,只有让时间更加平稳,而普通 bio 的处理时间波动相当大。
    2. bio 等待阻塞会占用 cpu 。 不会占用 cpu , 当然你要说自旋锁之类的占用 cpu , 那是因为在做 while 循环, 那不算。
    154 条回复    2024-08-15 18:48:05 +08:00
    1  2  
    koloonps
        1
    koloonps  
       2022-04-18 22:10:37 +08:00
    Netty 谁会开 200 个线程?一般都是 2*CPU
    jeesk
        2
    jeesk  
    OP
       2022-04-18 22:17:29 +08:00
    @koloonps 不谈 io. 今天就谈谈网上大量错误的回答和谬论。
    statumer
        3
    statumer  
       2022-04-18 22:18:36 +08:00   ❤️ 2
    1. 你用 NIO 的时候如果开了 100 个线程,说明要么你的程序是 CPU-bound ,要么是 HTTP 连接处理以外的 IO 全都在用同步网络库(如 JDBC )。后者属于错误用法了。模范用法见 techempower jooby-pgclient 。
    2. 建议搞清楚 tomcat 碰到超过 maxThreads 个阻塞 syscall 怎么处理的
    3 不解释了,建议写点 libevent 代码搞清楚什么是异步网络编程
    singerll
        4
    singerll  
       2022-04-18 22:20:36 +08:00 via Android   ❤️ 11
    JAVA 初学者都开始关注高并发,线程开销,io 开销了?讲道理你这初学者起点有点高。
    pursuer
        5
    pursuer  
       2022-04-18 22:21:42 +08:00
    1 '使用 BIO 上下文切换厉害' 可能是说高并发时多个线程同时运行时的抢占,很多时候其实请求逐个完成就可以,线程频繁切换影响性能。
    2 对于长链接应用,开很多线程是比较常见的,如游戏服务器,聊天服务器,开上万个也不是不可能,此时内存消耗就比较大了。
    3 select 是通过一个线程监听多个文件描述符状态变化的,因此除非高并发优化否则没必要开 10 个线程去 select
    ration
        6
    ration  
       2022-04-18 22:28:19 +08:00 via Android
    确实很多错误的回答,有些是过时,有些是本来就错误。谷歌,github 相对好点。再者,相对于技术来说,很多新闻啥啥的更不靠谱。所以严谨点,实践才是检验真理的唯一准则。
    jeesk
        7
    jeesk  
    OP
       2022-04-18 22:35:54 +08:00
    @pursuer 这里我可以说得不太清楚应该是说,1 个线程去监听, 然后 10 个线程去处理 selector 的事件。
    hidemyself
        8
    hidemyself  
       2022-04-18 22:38:28 +08:00
    那我问下了,NIO 和 BIO 各适用于什么场景呢?
    还是说所有可以使用 BIO 的场景,用 NIO 都会效果更好?
    james122333
        9
    james122333  
       2022-04-18 22:59:01 +08:00 via Android
    haha 当然不是
    但如果你机器非常好
    确实不一定得关注这个
    jeesk
        10
    jeesk  
    OP
       2022-04-18 23:08:04 +08:00
    @statumer tomcat 的 nio 我没有记错的话,tomcat nio 默认确实 worker 是 200 个线程。 所以我就问 bio 和 nio 都开 200 个线程, 那岂不是上下文竞争一样激烈? 我反驳得没有错吧?
    jeesk
        11
    jeesk  
    OP
       2022-04-18 23:09:16 +08:00
    @ration csdn 和知乎毒瘤不少。 还是得找谷歌,或者 sf 搜索看看老外写的文章。
    Vitta
        12
    Vitta  
       2022-04-18 23:09:38 +08:00
    我接触的几个 java 开发都给我一种 java 有本假秘笈,还非常流行的感觉
    jeesk
        13
    jeesk  
    OP
       2022-04-18 23:12:53 +08:00
    @Vitta 大佬也发我一份, 我也要看这本假秘籍。
    chihiro2014
        14
    chihiro2014  
       2022-04-18 23:13:42 +08:00
    现在还有个毒瘤,叫 simviso ,里面一个叫知秋的天天误导人。。自称国家机密人员,netflix 外包架构师。然后一群小白还挺相信
    jeesk
        15
    jeesk  
    OP
       2022-04-18 23:17:59 +08:00
    @chihiro2014 大佬你说的是 bilibili 里面的那个吧? webflux 的推广者, 我进群玩过两天, 和知秋大佬天生八字不合, 退群了。
    james122333
        16
    james122333  
       2022-04-18 23:18:13 +08:00 via Android
    @jeesk

    如果它真的这样搞那么你应该丢掉它 很多专案本来就很糟糕 甚至你改用其它语言
    Vitta
        17
    Vitta  
       2022-04-18 23:19:32 +08:00
    @jeesk #13 俺也没有啊,就是怀疑有假秘笈
    jeesk
        18
    jeesk  
    OP
       2022-04-18 23:20:43 +08:00
    @Vitta 能仔细说说那几个开发怎么发挥的吗? 好奇得不得了。
    jeesk
        19
    jeesk  
    OP
       2022-04-18 23:24:21 +08:00
    @chihiro2014 我最开始的时候也喜欢看大佬的视频, 发现都是做无用功。 最终放弃,还得自己看源码。
    jeesk
        20
    jeesk  
    OP
       2022-04-18 23:31:38 +08:00
    @james122333 哈哈, 我从来不讨论哪个语言性能好的问题。 领导让用啥就用啥。
    Vitta
        21
    Vitta  
       2022-04-18 23:33:14 +08:00
    @jeesk #18 我不一定对,人家也不一定错,没搞过 java ,也可能错的是我。几个栗子:
    1. 接口不处理业务逻辑
    2. 月经贴,不说 restful 了,接口路径,参数,返回字段随心所欲,有时候接口 A 返回的值要结合接口 B 编历处理
    3. 比如一个查询班级人员信息的列表接口,先拿一个接口获取所有 id, 再拿每个 id 去查列表要显示的信息


    不是一个 java 这么写了,好多个
    charlie21
        22
    charlie21  
       2022-04-18 23:34:58 +08:00
    假秘籍还行
    jeesk
        23
    jeesk  
    OP
       2022-04-18 23:46:17 +08:00
    chihiro2014
        24
    chihiro2014  
       2022-04-19 00:03:30 +08:00
    @jeesk 其实你错了,不是你八字不合,而是人家真的是啥也不会。。。在那边瞎吹牛逼,瞎立人设,这才是真相
    james122333
        25
    james122333  
       2022-04-19 00:04:41 +08:00 via Android
    @Vitta

    1 的话觉得还好 毕竟层层 return 是很麻烦的事情 一个接口也可能很多需求 纯编排基本逻辑并传递下去其实还可以 也很灵活 service 层可以拆的很细
    2 3 不说了
    jeesk
        26
    jeesk  
    OP
       2022-04-19 00:09:14 +08:00 via Android
    @chihiro2014 我记得我在知秋群贴了一段代码,问了一个问题, 然后群里就有死粉出来怼我了, 知秋也对我进行攻击, 后来就没有关注过了。 现在我很注重大 v 人品, 能力是其次,没有人品, 再牛也不相信。 徳不配位。
    chihiro2014
        27
    chihiro2014  
       2022-04-19 00:12:17 +08:00
    @jeesk 你又错了。。人家确实是真的没人品。建立的人设都是建立在朋友的情况下,当朋友就恩断义绝的时候,这人已经没了 hhh
    Vitta
        28
    Vitta  
       2022-04-19 00:12:30 +08:00
    @james122333 #25 其实 3 就是 1 的延伸。不处理业务逻辑的意思是我都不如直接用个云端数据库
    maximum2012
        29
    maximum2012  
       2022-04-19 00:20:10 +08:00
    @jeesk 就他还是大 v ,就一个江湖骗子而已。敢正经讨论问题直接攻击你
    Jooooooooo
        30
    Jooooooooo  
       2022-04-19 00:23:27 +08:00
    网上关于 volatile 的讨论也几乎都是错的.
    james122333
        31
    james122333  
       2022-04-19 00:23:46 +08:00 via Android
    @Vitta

    可以这样实现 但我想应该不会有人这样干
    levelworm
        32
    levelworm  
       2022-04-19 01:06:54 +08:00 via Android
    看来底层的东西的确是难搞啊
    james122333
        33
    james122333  
       2022-04-19 01:38:34 +08:00 via Android
    不知道什么纷争也不好讲了
    curoky
        34
    curoky  
       2022-04-19 01:50:28 +08:00 via Android
    优化个什么劲啊,堆机器不香吗
    chengyiqun
        35
    chengyiqun  
       2022-04-19 01:53:21 +08:00
    比错误的更讨厌的是, 首页一刷好几个一摸一样, 应该是爬虫互相爬取的, 有时候碰到问题了, 你搜到标题完全符合内容, 结果点开了发现里面什么都没说:(
    最后还是得到外网搜谷歌和栈溢出 :)
    chengyiqun
        36
    chengyiqun  
       2022-04-19 01:54:45 +08:00
    这些垃圾站能滚粗搜索引擎嘛, 污染了搜索引擎, 就算用插件屏蔽了, 我碰到最离谱的一次, 是屏蔽后, 搜索第一页一条记录都没有, 第二页就两三条记录还是不相干的 (
    medivh
        37
    medivh  
       2022-04-19 02:01:16 +08:00   ❤️ 3
    你应该把标题改改,喷 Golang 的异步 IO 那样引战效果更好,反正 V2EX 早就已经是技术饭圈了。

    如果你觉得自己不是引战的话,我觉得如果你要探讨 BlockingIO ,至少应该拿出数据来而不是 "我个人觉得差不了多少"。
    lifanxi
        38
    lifanxi  
       2022-04-19 02:24:35 +08:00 via Android
    wtdd
        39
    wtdd  
       2022-04-19 03:09:05 +08:00
    有没有可能:外网知识是对的,只不过全网错了^_^
    gtx990
        40
    gtx990  
       2022-04-19 07:39:45 +08:00 via Android
    楼上有直接反驳的,我看你也没理他。
    你可能没有搞懂一些概念。

    nio 就是给 select/epoll 包了一层
    如果你写过 C 语言的 server 的话你应该知道编程模型是:
    一个主线程 /eventloop/selector 在等待 io ,出现事件以后再执行 callback/起一个线程执行 callback 。
    如果你的下游是阻塞的,比如是 jdbc ,你要为 callback 起个线程,那确实符合你的描述。

    但是如果你的主要任务是当个网关,你的下游支持异步请求(比如基于 netty client 的 rpc 库 /支持异步的数据库),那么你可以用 completableFuture 的那套东西,不需要让工作线程阻塞在那监听下游。

    在这种情况下,200 个同时来的请求,不会产生 200 个同时 block 住,等待下游的线程。

    200 这么点,当然你用啥模型都没影响,想让单机并发破千、破万,肯定要死扣每个线程的几兆内存。
    jeesk
        41
    jeesk  
    OP
       2022-04-19 07:44:30 +08:00 via Android
    @medivh 看清标题再说, 我只是想讨论关于网上有很多错误的言论。
    jeesk
        42
    jeesk  
    OP
       2022-04-19 07:53:02 +08:00 via Android
    @wtdd 一切皆有可能
    jeesk
        43
    jeesk  
    OP
       2022-04-19 08:05:53 +08:00 via Android
    @gtx990 你说得没问题, 但是 netty 并不是全异步的,select 还是会阻塞, 真下的异步是 aio 。 既然 selct 都是阻塞的? 我看网上没也人亲自做过测试来证明一下相同线程下处理 seletor 事件,bio 上下文竞争比 nio 强烈, 我反驳的是这个观点。
    Jekins
        44
    Jekins  
       2022-04-19 09:15:48 +08:00
    我干了快两年 Java 。。还没遇到过要考虑用 netty 这些。。一直没想过 netty 会用在什么业务场景? lz 方便说下吗哈哈
    MoYi123
        45
    MoYi123  
       2022-04-19 09:23:13 +08:00
    2022 年的 mysql 真的超过 1000 万行就要分表吗? 不太用 mysql, 有没有人说一下.
    lap510200
        46
    lap510200  
       2022-04-19 09:23:19 +08:00
    正常,国内粪坑文章太多,只谈性能测试,脱离业务实践就是很鸡肋
    cheng6563
        47
    cheng6563  
       2022-04-19 09:31:10 +08:00
    @MoYi123 3 亿数据照样用
    misaka19000
        48
    misaka19000  
       2022-04-19 09:31:16 +08:00
    看书就行了,而且不要看中国人写的书
    jeesk
        49
    jeesk  
    OP
       2022-04-19 09:34:45 +08:00 via Android
    @Jekins 可以看看一些 rpc 源码里面通信大多用 netty
    jeesk
        50
    jeesk  
    OP
       2022-04-19 09:36:46 +08:00 via Android
    @MoYi123 一般公司用不了, 国内很多面试分库分表的 都是瞎搞。
    james122333
        51
    james122333  
       2022-04-19 09:38:01 +08:00
    @jeesk

    楼主还在纠结同样线程并且是大量线程
    jeesk
        52
    jeesk  
    OP
       2022-04-19 09:38:59 +08:00 via Android
    @lap510200 性能测试也是假的, 就拿 fastjson 来说 , 他们自己测试出来比 gson jackson 快。 但是我自己测试出来 fastjson 速度最慢 。
    Goooler
        53
    Goooler  
       2022-04-19 09:41:17 +08:00
    不如 okio 好用
    trivisa
        54
    trivisa  
       2022-04-19 09:41:23 +08:00
    这个不需要从业久也能发现吧哈哈哈,而且是各行各业,甚至生活知识都是这样
    只能说中文互联网内容确实还不够好,大家继续努力吧
    nothingistrue
        55
    nothingistrue  
       2022-04-19 09:51:32 +08:00
    你的标题是对的,但你下面说得谬论好些不是谬论。

    1. 抛开剂量来说影响,那是耍流氓,线程切换的消耗跟线程的数量,是指数对比,200 个线程你看不出来区别,但是一千一万呢,不要说物联网服务器,就是面向公众的普通 Web 服务,那都是一万起步的。

    2. 请参见一,在 tomcat 改成 NIO 之前,它要么只应用在不到百人的企业内部,要么躲在 IIS/Apache 后面,压根不会直接面向公众(早期确实有不负责任的人那 tomcat 当前台服务器的页游,那响应速度是相当感人的)。

    3. 这么貌似确实是谬论,我也没看懂。Netty 本质上只是对 Java nio 的易用性封装,并没有动 NIO 的原理。至于你的阻塞疑问,IO ,不管是本地 IO 还是网络 IO ,并不是总是在传输的,他经常是在等待输入源 /输出目的可用的等待过程,这期间它是不工作的,这个时候,如果是 BIO ,不管是否工作它都要占用线程,如果是 NIO ,不工作期间是不占用线程的。
    NXzCH8fP20468ML5
        56
    NXzCH8fP20468ML5  
       2022-04-19 09:52:19 +08:00   ❤️ 2
    本来 Java 就很搞笑啊,归根结底在于只提供了 NIO ,却没提供协程,异步运行时等基础设施,导致出现了 NIO 要开 200 个线程的荒谬的事情。
    正确的多路复用,比如 C#,Go ,Rust ,都是开了异步,就只提供 CPU 核心数量级的线程,一个 io 一个 task ,那些 task 就留着协程慢慢调度去。
    NXzCH8fP20468ML5
        57
    NXzCH8fP20468ML5  
       2022-04-19 09:55:30 +08:00
    @MoYi123 正确做法是亿级分表,但千万级时肯定就要考虑分表的事宜了。
    aguesuka
        58
    aguesuka  
       2022-04-19 09:58:18 +08:00
    nio 不初学者了, 我来说两个: 字符串拼接最佳实践和什么时候用 LinkedList
    nothingistrue
        59
    nothingistrue  
       2022-04-19 10:03:38 +08:00
    还有,NIO 200 个线程是应对五万并发连接的(一个 Linux 单机最高就能开这么多连接,没这个限制它能应对更多),实际上压根也用不到 200 个线程,物联网或者没有文件上传下载场景的接口服务器场景下,10 个线程就能轻松应对五万并发连接。请注意这里的并发连接是指可以毫秒级别同时响应的连接。

    后面你提到 RPC 大多用 NETTY ,那是因为 RPC 服务器是至少上千通常上万的并发量(没到这个并发量也没必要开 RPC )。
    aguesuka
        60
    aguesuka  
       2022-04-19 10:06:44 +08:00
    除非不用 JDBC, 否则 Java 就活在多线程的阴影里
    byte10
        61
    byte10  
       2022-04-19 10:07:19 +08:00   ❤️ 1
    @jeesk 少年,你多听前辈的。我来给你一一解答把,第一点:你用 BIO 和 NIO 都是 200 个线程 ,首先你条件是错了。。NIO 只要 4 个线程即可。另外要验证 BIO 上下文切换厉害,这个是需要在 IO 时间很短的情况下才会出现,且 200 个线程不算啥,你得开 1000 个线程才能看出有差距。

    所以你要验证线程上下文切换的损耗,我给你一个测试的方案。写一个 main 方法,一个用 4 个线程,一个用 200 个线程,处理的任务是:判断 100000007 是否为一个质数(一个线程计算一个数,总共相同计算 500 次),一个数 for 循环一亿次去判断,最终得到的是 4 个线程比 200 个线程快,原因就是线程切换会有开销,至于你看起来差不多,那是因为现在的 cpu 单核很快。你可以换成树莓派,或者手机 linux deploy ,或者几年前的双核 I3 去验证。你要多学习,多思考。不然以后会误导后辈的,我们公司都很多这样的小白,没有完整的验证方案,因为不懂这基础知识,所以没法设计验证的方案。

    第二个问题:一般 BIO - tomcat ,如果有 2000 个用户在线,那么就需要 2000 个线程,除非用伪 BIO 。

    第三个问题:你的思路很混乱,我暂时无法回答,也不知道从哪里回答你。

    对于 NIO 你先看我的视频,如果能看懂,你就算是毕业了,如果还没看懂,那么是我的讲的还不行。里面有大量的 test case 去验证 tomcat 线程数的数量该设置多少,https://www.bilibili.com/video/BV1FS4y1o7QB ,主页我还有一个视频讲多线程的,应该对你也有帮助。。

    @jeesk 关于 tomcat NIO 和 BIO 为何默认 200 个线程。这个从你目前的知识,无法解答。答案在视频里,如果你看懂了,自然明白。里面有大量的数据可以验证,tomcat 有 NIO 但是大多数人 还不会使用。tomcat NIO 的 支持 servlet 用异步编程的模式,只需要设置 tomcat 线程数等于 cpu 核心数 即可。里面有大量的例子给你证明的,希望你能明白。

    @hidemyself 你可以看看我的视频,应该能回到你的问题 https://www.bilibili.com/video/BV1FS4y1o7QB
    Edsie
        62
    Edsie  
       2022-04-19 10:09:14 +08:00
    没有任何时候比现在更容易从互联网上获取信息
    大爆炸似的信息增长,导致了两个结果:
    1. 你能在互联网上找的到非常优质的内容
    2. 从量上来看,垃圾信息也在恐怖的增长,至于好的信息和垃圾信息的比例就不得而知了

    所以这对人们提出了更高的要求,现状是:有能力的人总能找出他们需要的信息。
    lisongeee
        63
    lisongeee  
       2022-04-19 10:11:06 +08:00   ❤️ 2
    "我个人觉得差不了多少。 所以这个说法是错的。"

    不要凭感觉啊,拿 cpu 占用率和程序使用内存数据说话啊
    jeesk
        64
    jeesk  
    OP
       2022-04-19 10:19:14 +08:00 via Android
    @nothingistrue 你确定吗? tomcat8.5 才默认为 nio , 你这数据哪儿来的?
    byte10
        65
    byte10  
       2022-04-19 10:19:45 +08:00
    @Jekins 可以看看我的视频。B 站:小巫老师,视频:NIO 二 实战演练 ,里面就一个几个案例,讲到为何要用 NIO 。另外一个 视频:NIO 的绝对优势 这个视频非常的强,可以打开 NIO 的思路。里面有很多测试代码,可以帮组你理解 NIO 为何几个线程就可以吊打 BIO 几千个线程。

    @nothingistrue 正确,200 个线程难以看出差距,不过在低端 cpu 可以看出和 4 个线程的差距,高端 cpu 起码 2000 个线程和 10 个线程对比才能看出来,另外要测试的话 需要用 cpu 密集型任务去验证,很多小白会用 IO 任务去验证。。我头大。

    @hidemyself 你可以看看我的视频,B 站:小巫老师,NIO 二 实战演练,讲述了为何需要 NIO 的场景,里面有很多测试的代码,看完你应该就能明白,NIO 有绝对的性能优势。 等 java 的协程出来,BIO 就基本不会在用了。
    jeesk
        66
    jeesk  
    OP
       2022-04-19 10:20:40 +08:00 via Android
    @byte10 你是来推广视频的吧 哈哈
    chnhyg
        67
    chnhyg  
       2022-04-19 10:23:36 +08:00
    尽量接近信息源头,信息源头的错误率和失真率是最少的,二手、三手信息是别人嚼碎了再吐出来的,有一定的错误和失真。
    byte10
        68
    byte10  
       2022-04-19 10:27:05 +08:00
    @jeesk 哈哈,先看完,如果有问题可以留言或者 加绿色。我已经给你答案了,还有很多测试的代码,可以验证你的疑虑。为何 tomcat NIO 等于没用?因为下游的业务代码全是阻塞 IO 代码,所以你才会看到 tomcat NIO 依然需要默认 200 个线程。而 webflux 默认就是 cpu 核心数的线程,因为它是响应式编程。除了 webflux ,还有一个 vert.x 使用异步编程,也可以做到少量线程。当然你的业务如果是阻塞 IO 的操作,比如 mysql 读写等,还是需要创建的线程池去处理。

    作为一个后辈,我是需要你做出指引,给大家做出指引,科普知识非常的困难,我尽力而为。当然你说的推广算是附带的吧。
    Leviathann
        69
    Leviathann  
       2022-04-19 10:33:17 +08:00
    为什么用 nio 还要开那么多线程,nio 的目的不就是用少量线程管理大量 io

    而且为什么一直要说 tomcat 怎么怎么样,tomcat 是什么在单机高并发场景下很有代表性的东西吗?现在用 tomcat 的场景堆并发不都是堆机器,单机并发烂的很,不然还要 go 干嘛
    jeesk
        70
    jeesk  
    OP
       2022-04-19 10:45:21 +08:00 via Android
    @chnhyg 给你赞。 我就是这样学的。 看别人写的东西 会出现很大的问题 。
    zmal
        71
    zmal  
       2022-04-19 11:00:32 +08:00
    哈哈哈哈哈哈,op 再过两年回头看看自己的帖子(手动狗头。
    az467
        72
    az467  
       2022-04-19 11:00:40 +08:00
    没错,一切都是根据需求而言。

    如果我完全不在乎某些指标,比如 tps 、rt 、throughput ,只看内存占用或者其他什么的。
    那不论是 Blocking IO 还是 Non-blocking IO ,肯定都比不上 No IO 。
    我只要一个线程都不开,一行代码也没有,内存占用 0 ,上下文切换代价也是 0 ,不要说什么 M 级的内存消耗( https://en.wikipedia.org/wiki/Page_fault ),G 级别又能怎样。

    如果要解决 C10K/C10M 问题,那就不得不给 BIO 模型的服务软件配一个 IBM 小型机。
    nekoneko
        73
    nekoneko  
       2022-04-19 11:06:32 +08:00   ❤️ 1
    在少量连接的情况下 bio 的性能是优于 nio 的
    但是在大量连接的情况下, 比如说十万百万, 这种情况下 bio 就要建立十万百万的线程, 这个用 bio 处理基本离死不远了
    但 nio 就可以处理这种场景.
    ecric
        74
    ecric  
       2022-04-19 11:15:26 +08:00
    别他妈卷了
    zmal
        75
    zmal  
       2022-04-19 11:25:07 +08:00
    有没有一种可能,你的测试场景、测试手段都有问题?(狗头
    seagull7558
        76
    seagull7558  
       2022-04-19 11:32:12 +08:00
    知秋没深入接触过 不过看过一些翻译的课程,我觉得,emmmmm 哈可以吧 不晓得他是和其他人有什么冲突吗?
    xuanbg
        77
    xuanbg  
       2022-04-19 11:46:15 +08:00
    BIO 还是 NIO ,只要看阻塞的是什么就知道怎么选了啊,同时也就知道能开几个线程去处理了。
    yigecaiji
        78
    yigecaiji  
       2022-04-19 12:20:55 +08:00
    初学者的理解:
    bio 下,n 个 socket 连接需要一个线程来处理请求,同时每个 socket 需要 2 个线程来处理读写。
    nio 同步非阻塞下,n 个 socket 的请求、读、写操作可以由一个线程来完成,但没有这些操作的时候,线程还在运行,浪费 cpu
    nio 多路复用下,n 个 socket 的请求、读、写操作可以由一个线程来完成,如果没有这些操作,线程就会阻塞。
    我不知道 tomcat 的机制,不过相同 socket 的情况下,nio 开的线程应该是比 bio 要少的。
    jeesk
        79
    jeesk  
    OP
       2022-04-19 12:35:46 +08:00 via Android
    @yigecaiji 自己看源码
    jeesk
        80
    jeesk  
    OP
       2022-04-19 12:37:20 +08:00 via Android
    @seagull7558 我从来没说过他的水平,我也不清楚他是不是大神。 我更加看中 人品
    jeesk
        81
    jeesk  
    OP
       2022-04-19 12:37:56 +08:00 via Android
    @yigecaiji 你自己看了源码就知道网上很多都是错误的。
    jeesk
        82
    jeesk  
    OP
       2022-04-19 12:40:00 +08:00 via Android
    @ecric 谁在卷了? 我的标题一直在说 很多文章是错误的这个话题。
    relaxchen
        83
    relaxchen  
       2022-04-19 12:40:15 +08:00
    确实多,我就说一个
    mongodb 的教程里面,有多少链接不上就让你 bindip 0.0.0.0 的
    然后被人批量扫库
    jeesk
        84
    jeesk  
    OP
       2022-04-19 12:46:26 +08:00 via Android
    @relaxchen redis 也是吧。 😂
    salmon5
        85
    salmon5  
       2022-04-19 12:49:35 +08:00
    java 小白:undertow 性能好,岂不知 tomcat 更适用小白使用
    jeesk
        86
    jeesk  
    OP
       2022-04-19 12:50:54 +08:00 via Android
    @salmon5 管理局没压测过, 不要看网上评论 他们都是扯淡的。
    jeesk
        87
    jeesk  
    OP
       2022-04-19 12:51:47 +08:00 via Android
    @salmon5 @ 如果没有在服务器上面压测过的话, 千万不要相信某某性能高。
    salmon5
        88
    salmon5  
       2022-04-19 12:52:35 +08:00
    @jeesk #86
    是的,“undertow 的性能好”,网上都是瞎扯蛋
    salmon5
        89
    salmon5  
       2022-04-19 12:53:46 +08:00
    @salmon5 #85
    某些 java 小白:"undertow 性能好",岂不知 tomcat 更适用小白使用
    salmon5
        90
    salmon5  
       2022-04-19 12:54:35 +08:00
    tomcat 的线程模型,更适合粗糙、粗犷的环境
    gdgoldlion
        91
    gdgoldlion  
       2022-04-19 12:59:52 +08:00
    “中文互联网的主要问题不是信息太多,而是垃圾信息泛滥”
    外网技术圈不是说没有辣鸡,但是整体质量高太多了
    jeesk
        92
    jeesk  
    OP
       2022-04-19 13:02:16 +08:00 via Android
    @gdgoldlion 其实我现在也没明白 ,nio 怎么体现的非阻塞的? 所以我看看能不能给作者发一个邮件, 问问原理
    byte10
        93
    byte10  
       2022-04-19 13:18:44 +08:00
    @Leviathann tomcat 问题不大啊,你应该看看我的那个讲解 会给你展示 tomcat 如何处理高并发的场景,不是它不行,而是大部分人不会用。它 tomcat 也是支持 NIO ,使用 servlet 异步编程,依然可以少量的线程,处理高并发。b 战:小巫老师的 NIO 服务的优势-无视 IO 时间,tomat 单机跑 1w+/s 的 QPS 也问题不大。

    @zmal 是的,我已经给 OP 的测试方案了,希望他能研究学习下。
    @relaxchen mongodb 不是内网部署吗,相对安全把?被批量扫库是什么意思?
    @lisongeee 即便 OP 能拿出数据来,也可能是错的,因为测试的方案就不正确了。

    我那个视频有讲解怎么做正确的压力测试的,一般用 jmeter 测试没问题,但是测试 NIO 就需要换一个,可以使用 ab(ApacheBench)和 wrk 压测工具。如果知道 http 协议 那么就应该知道 连接数 是关键因素,但是太多人不清楚了。。。jmeter 适合测试 BIO 的服务,不适合测试 NIO 的服务,建议用 wrk 这个工具。
    liuhan907
        94
    liuhan907  
       2022-04-19 13:36:24 +08:00   ❤️ 1
    @jeesk
    你认为的几个谬论,实际上都是你自己的理解有些问题。
    1. 如果无论是 BIO 和 NIO 你都用 200 线程,确实线程之间的竞争都差不多。但是这里你的问题在于如果用 NIO ,我们使用的线程数量不会是 200 。通常 IO 线程数量选 CPU 核心数 * 2 ,或者再 +2 。比方说如果是四核心,那就是 10 线程左右。
    2. Java 的默认线程栈大小就是 1MB 这个其实没什么好多解释的。BIO 比 NIO 的内存消耗更大的原因其实就只是 BIO 需要更多线程。
    3.1. 这里其实还是和 1 一样,NIO 使用比 BIO 更少的线程所以内存消耗低,而不是线程池限制了消耗。当然 BIO 下你也没办法用线程池,因为每个连接都会独占一个线程。所以说线程池减少了内存消耗不准确。
    3.2. 这里的占用线程指的是操作系统对于线程分配的时间片,不过这里 BIO 和 NIO 一样都是内核等待所以确实是没差别。
    frankly123
        95
    frankly123  
       2022-04-19 13:37:55 +08:00
    @MoYi123 10 亿数据照样用
    macha
        96
    macha  
       2022-04-19 14:24:24 +08:00
    搞 windows 开发都没有文章和书看,只能信自己。现在看起来竟然也算是个优点了。
    hello158
        97
    hello158  
       2022-04-19 14:26:36 +08:00   ❤️ 3
    错误的知识多了去了。比如说:Java 关于类加载,有个词叫“双亲委派”,当我第一次听到这个词和他的概念的时候,就感觉很怪。字面上来看“双亲”是 父亲母亲的意思(或者你说 2 个父亲也行),那么这个“双亲”从层级上看是 2 层(实际上我可以写多个 classloader 继承,那样就不止 1 层了),且“双亲”给人的感觉是双方是平等的关系(就好比对于我们来说 爸爸妈妈是一个层级,爸爸和爷爷是 2 个层级,显然 BootstrapClassLoader 和 UserDefinedClassloader 不是一个层级,所以双亲的说法太怪了)。

    然而,人家的英文名词是啥?—— Parents Delegation Model 这他妈的怎么能翻译成“双亲委派”?!!!你翻译成“父级委派”不行么? 翻译成“向上委派”不行么? 或者你就不翻译,把这个当做一个特殊的词来说,或者你就简称 PDM 就行了。 然而这么多年,都是这么叫的,“双亲委派”,双你老 mu 啊。
    raynor2011
        98
    raynor2011  
       2022-04-19 14:55:11 +08:00   ❤️ 2
    你是在说你自己这个帖子吗?错漏百出
    xtinput
        99
    xtinput  
       2022-04-19 14:57:21 +08:00
    因为都是复制粘贴的,作者自己都没验证文章就出来了
    lmshl
        100
    lmshl  
       2022-04-19 15:00:36 +08:00
    楼主和楼内其他回帖人也犯了不少谬误

    我先说下我的实战经验,我有一个 NIO 生产环境服务,落到 JDBC 有 100 QPS ,CPU 消耗不超过 0.2 核心😏

    对大部分 CRUD 需要访问数据库,他人 API 的 IO 密集型应用来说,完全 NIO 模型对性能的提升都是碾压级别的,碾过 BIO 渣都不剩。
    另一点,JDBC 虽然是阻塞的,但不影响你开固定链接池异步访问,你的应用依然可以按照教科书上 n 核心的 CPU 开 n 个线程的池。

    如果你想了解更多 NIO 概念,那应该去看看《响应式设计模式》
    1  2  
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2479 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 04:12 · PVG 12:12 · LAX 20:12 · JFK 23:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.