V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
546L5LiK6ZOt
V2EX  ›  问与答

异步编程中,为什么一些类库不提供限制队列长度的方式

  •  1
     
  •   546L5LiK6ZOt · 2023-05-10 23:20:23 +08:00 · 908 次点击
    这是一个创建于 557 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在 java 中,利用 nio 来发起网络请求,基本步骤是:

    1. 业务线程把请求写到一个内存队列,然后往相关的 channel 注册一个写事件
    2. select 方法是单独运行在另一个线程,当 channel 可写时,就会从内存队列中获取要发送的数据,然后写进 channel

    java11 的 httpclient ,以及 apache 的 httpclient ,都提供异步请求的方式,底层也是利用 nio 。但是没有提供限制内存队列的方式。也就是说,如果网络抖动,短时间等不到“可写”事件的发生,加上频繁发起网络请求,那么内存队列有可能会占用很大内存。本质上这是生产者和消费者模型,两个线程交互必须要考虑内存队列大小的,不然生产速度远大于消费速度就 GG 了。stackoverflow 上有个回答是利用 semaphor. 但是 semaphor 是在请求结束了才 release ,性能最好的方式应该是请求数据写进 channel 就 release 。

    相反,netty 可以限制内存队列,并且还能配置拒绝策略(不愧是号称 java 最好的网络 io 库)。不理解 java 和 apache 官方的类库为啥不考虑这一点。

    再扩展一下,像 go 这种支持协程的语言,并发发起网络请求都是起一个协程,底层肯定也是有一个内存队列缓存请求数据的,貌似也没有限制队列长度的方式(我对 go 不熟悉,不知道理解对不对)。

    难道 channel 大概率是可写的,内存队列堆积的可能性非常小,不需要考虑?

    4 条回复    2023-05-12 04:16:48 +08:00
    hankai17
        1
    hankai17  
       2023-05-10 23:44:03 +08:00
    没看过 netty httpclient apache 的源码 看过几个网络库源码
    猜一下
    1. 队列长度应该有限制 即使没有 也会受其它比如并发 打开的文件个数限制
    2. 除此外 队列应该也有超时"淘汰"机制
    byte10
        2
    byte10  
       2023-05-11 10:04:43 +08:00
    没有看到 Netty 的源码,倒是自己使用 netty 写过一下 http 服务端和 http 客户端

    NIO 发起网络,一般就是一个请求一个链接 channel 吧,它提供了简单的通讯框架。一般是上一层来维护连接池,比如基于 netty 的 http 客户端,有可能可以设置 http 连接池。如果没有设置的话,那么就是默认一次请求一个连接 channel 。但如果共享链接池的话,就会从任务队列拿数据进行发送,这个队列应该是 http 客户端来维护。同理其他的协议也是类似,比如 redis 协议等。

    另外 NIO 本来存在背压的问题,还是要从业务层来规避下,限流下。
    ql562482472
        3
    ql562482472  
       2023-05-11 10:26:09 +08:00
    tcp 缓冲区怎么是无限的?
    documentzhangx66
        4
    documentzhangx66  
       2023-05-12 04:16:48 +08:00
    如果用 C++的思维去理解,就很容易解释了。

    这是因为,对于高性能组件来说,限制长度这个功能,对性能的冲击非常大,因为它需要检测与同步,在多线程甚至多 CPU 情况下,这种代价会加剧变大。很多网络组件,为了高性能,甚至改用不精准的定长 ringbuffer 的满载时首尾位置判断,来代替更精准的实时长度。

    你可以简单找个大内存服务器,不做 free 或 delete ,来比较一下 queue 或 list 入队时,有无长度检测或容量检测,对性能的影响。特别是多 CPU 多线程的情况。

    如果计算机性能,能够得到大幅度提高,那么实时获取长度,对程序员的体验来说,当然更好。但那个时候,对性能又会有更高的要求。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5506 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 01:29 · PVG 09:29 · LAX 17:29 · JFK 20:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.