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

查看 64|回复 1
作者:546L5LiK6ZOt   
在 java 中,利用 nio 来发起网络请求,基本步骤是:
[ol]
  • 业务线程把请求写到一个内存队列,然后往相关的 channel 注册一个写事件
  • select 方法是单独运行在另一个线程,当 channel 可写时,就会从内存队列中获取要发送的数据,然后写进 channel
    [/ol]
    java11 的 httpclient ,以及 apache 的 httpclient ,都提供异步请求的方式,底层也是利用 nio 。但是没有提供限制内存队列的方式。也就是说,如果网络抖动,短时间等不到“可写”事件的发生,加上频繁发起网络请求,那么内存队列有可能会占用很大内存。本质上这是生产者和消费者模型,两个线程交互必须要考虑内存队列大小的,不然生产速度远大于消费速度就 GG 了。stackoverflow 上有个回答是利用 semaphor. 但是 semaphor 是在请求结束了才 release ,性能最好的方式应该是请求数据写进 channel 就 release 。
    相反,netty 可以限制内存队列,并且还能配置拒绝策略(不愧是号称 java 最好的网络 io 库)。不理解 java 和 apache 官方的类库为啥不考虑这一点。
    再扩展一下,像 go 这种支持协程的语言,并发发起网络请求都是起一个协程,底层肯定也是有一个内存队列缓存请求数据的,貌似也没有限制队列长度的方式(我对 go 不熟悉,不知道理解对不对)。
    难道 channel 大概率是可写的,内存队列堆积的可能性非常小,不需要考虑?

    队列, 内存, channel, 请求

  • hankai17   
    没看过 netty httpclient apache 的源码 看过几个网络库源码
    猜一下
    1. 队列长度应该有限制 即使没有 也会受其它比如并发 打开的文件个数限制
    2. 除此外 队列应该也有超时"淘汰"机制
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部