• -W.LI-
    2019-06-18
    老师好!那个两次read能理解为,连接被保留着,数据没就绪处理的线程资源先释放了。收到异步数据就绪通知后,根据原有的连接重建处理线程,继续处理。阻塞期间线程可复用

    作者回复: 对的

    
     6
  • yungoo
    2019-06-13
    我所看的tomcat 8.5的代码跟专栏所讲已经有些不一致了。已经没有Nio2Acceptor了,accept获取连接用的是Future aceept()。

    作者回复: 我使用的是最新版的代码:
    https://github.com/apache/tomcat/blob/master/java/org/apache/tomcat/util/net/Nio2Endpoint.java#L382

     1
     4
  • 佑儿
    2019-06-25
    Http11Processor 是通过 2 次 read 调用来完成数据读取操作的。
    这一点看了好几遍始终没明白,
    作者回复: Nio2SocketWrapper的read方法,这个方法会被调用两次,不是串行调两次,而是Poller会先后创建两个SocketProcessor任务类,在两个线程中执行,执行过程中每次Http11Processor都会调Nio2SocketWrapper的read方法。

    public int read(boolean block, ByteBuffer to){

    //第二次调用时直接通过这个方法取数据
    int nRead = populateReadBuffer(to);

    ...

    //第一次时数据没取到,会调用下面这个方法去真正执行I/O操作并注册回调函数:
    nRead = fillReadBuffer(block);

    ...
    }
    以上是针对802.11的回答,可是我没有在Nio2EndPoint中找到对应poller内部类啊
     
    展开

    作者回复: 可能是代码版本不对,我看的是9.0.20最新版

     1
     3
  • -W.LI-
    2019-06-18
    老师好!Windows 的 IOCP 和 Linux 内核 2.6 的 AIO 都提供了异步 I/O 的支持,Java 的 NIO.2 API 就是对操作系统异步 I/O API 的封装。
    这句话怎么理解啊?我看别的老师说Linux不支持异步IO,评论里也有同学说Linux下的AIO其实只是NIO之类的。老师能具体讲讲么谢谢。

    作者回复: 刚我查了下JDK的源码,确实Java的NIO.2是通过epoll来模拟实现的,源码在这里:
    http://hg.openjdk.java.net/jdk9/dev/jdk/file/71716def08ac/src/java.base/linux/classes/sun/nio/ch/EPollPort.java

    Linux内核2.6确实提供了内核级的AIO支持,只是还不完善,详情可以看这里:http://lse.sourceforge.net/io/aio.html

    估计是这个原因JDK没有使用这种方案。抱歉弄错了,还是不能人云亦云,一定要自己看了源码才行...



     1
     3
  • 802.11
    2019-06-15
    Http11Processor的2次read是在哪个类中呢,没有找到。。。。

    作者回复: Nio2SocketWrapper的read方法,这个方法会被调用两次,不是串行调两次,而是Poller会先后创建两个SocketProcessor任务类,在两个线程中执行,执行过程中每次Http11Processor都会调Nio2SocketWrapper的read方法。

    public int read(boolean block, ByteBuffer to){

    //第二次调用时直接通过这个方法取数据
    int nRead = populateReadBuffer(to);

    ...

    //第一次时数据没取到,会调用下面这个方法去真正执行I/O操作并注册回调函数:
    nRead = fillReadBuffer(block);

    ...
    }

    
     3
  • 西兹兹
    2019-06-15
    李老师好,请问nio1,tomcat里nio为什么不参考netty,通过使用堆外内存来避免零拷贝问题?

    作者回复: 主要还是堆外内存管理起来没有JVM堆那么方便,为了稳定性的考虑吧,另外APR就是堆外内存的方案,也就是已经提供了这个选项。

    
     3
  • Monday
    2019-06-17
    走到io就渐渐要掉队,虽然看了很多遍
    
     2
  • 西兹兹
    2019-06-15
    李老师好,这节精彩,特别是两次read讲的用心。
    1 nio2图里确实有个poller字样
    2 思考题回答,个人认为第二次read用的是work线程池, 因为内核已经准备好完整开箱可用的数据, 直接使用即可, 无须过多的线程上下文切换。
    
     2
  • W.T
    2019-06-13
    李老师实力派!👍
    
     2
  • WL
    2019-06-13
    老师关于IO模型内存我有两个问题:
    1. 配内存的时候,是不是因为堆内存会受到GC的影响导致地址变化,所以不能直接使用不能使用堆内存, 如果使用堆内存的话也需要先指向一个固定的堆外内存,所以使用堆外内存就可以避免GC对内存地址的影响。
    2. 是不是IO在读数据的时候经过两次数据拷贝,从网卡到内核态,从内核态到用户态,这两次数据拷贝有什么方法可以减少1次吗?

    作者回复: 好问题,下一篇就会解释这个问题。

    
     2
  • 802.11
    2019-06-21
    怎么模拟呢。现在springboot内置的Tomcat使用的都是nio 。设定NIO2呢

    作者回复: 详细介绍
    https://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-web-servers.html

     1
     1
  • 世纪猛男
    2019-06-16
    "同时为了提高处理速度,会提供一个线程池给内核使用,样不会耽误内核线程的工作"

    请问老师,这里不太明白,用户线程不能操作内核空间, 那这个线程池 如何能替代 内核线程的工作
    
     1
  • helloWorld
    2019-06-15
    老师以后在文章中的例子可以给出完整的代码吗?

    作者回复: 我尽量贴全,有时候代码太多不好贴,最好课后去看看源码

    
     1
  • 发条橙子 。
    2019-06-14
    老师 , 这两张讲的I/O有点难啃 ,主要还是底子太薄 。 反复看了几遍有几个疑问点希望老师指点一下 😄

    1. read请求是怎么发出来的 是通过调用select方法发出来的么 ?

    2. 异步我看发了一个read 就返回了,那实际是应该是指异步非阻塞 , 那么存在异步阻塞的模型么?

    3. 老师说从tcp/ip那层解数据包。我理解的过程是 当客户端发一个uri请求,当通过一系列的路由后最终到我们的服务器,再从七层网络模型的最底层开始一路向上到最顶层的应用层。 当应用层(Tomcat容器)接收到请求(连接器endpoint监听端口)后向操作系统发送一个read请求 ,然后等待操作系统内核回调应用程序(Tomcat容器)的回调接口 。那么按照我这种脑补的过程,实际上当服务端tomcat接收到客户端的I/O请求时,向操作系统发送read请求要求操作系统将客户端发送的数据(前台的入参信息)从内核拷贝到用户空间。因为tcp/ip层在应用层下面,那么从网卡解析数据到内核这个过程是不是在tomcat获取到请求之前的的时候就已经处理好了,而不是在tomcat发送read请求时再去从网卡解析数据..?
    展开

    作者回复: 1,select只是查询,真正发出read调用的还是read方法
    2,好像没有异步阻塞这个说法
    3,同步阻塞模型,read调用发起时,数据可能还没到网卡。如果io多路复用,read调用时,数据已经到了内核空间,因为之前select已经查到数据到了,应用才调read

    
     1
  • nimil
    2019-06-13
    问下老师,这个Tomcat这个IO模型是将数据拷贝了两次么,还是有做特殊优化

    作者回复: 数据没有拷贝两次,第一次read调用是读不到数据的,因为这个时候数据还没应用层的Buffer,只是注册一个回调函数,当内核将数据拷贝到了应用层Buffer,调用回调函数,在回调函数里,HttpProccessor再发起一次read,read方法首先会检查数据是不是已经到了Buffer,如果是,直接读取Buffer返回,这一次并没有真正向内核发起read调用。

    
     1
  • 李磊
    2020-01-17
    老师,您好,java NIO与tomcat 的NioEndpoint有什么区别,为啥不直接用java的NIO呢。
    
    
  • 帽子丨影
    2019-09-19
    老师好,文中说到 Http11Processor在处理请求时,会调用Nio2SocketWrapper的Read()。这个逻辑不知道在源码的什么位置,一直没找到
    
    
  • 不二
    2019-09-14
    老师,请教一下,在assc.accept(this, new AcceptHandler)方法注册的回调函数,在连接建立和数据到来内核是调用同一个回调函数处理的吗?

    
    
  • What for
    2019-08-24
    老师您好,有几个问题想请教下:
    1. 对于异步 IO 的理解,文中的 IO 过程其实注册的两个回调函数,一次用于建立连接一次用于读取数据,那么是不是 accept 和 read 是两个 IO 过程?两个回调函数都跑在 ChannelGroup 注册的线程池里?相当于 accept 和之后的两个回调函数一共用了 3 个线程?
    2. 异步 IO 中如果 read 函数的给定的 buffer 放不下一次连接传来的数据怎么办?
    3. 回调函数实现类的第二个类型参数本应是 attachment,但由于 NIO2Acceptor 本身就是回调函数它不需要显示指定 attachment 的类型参数,所以它的第二个类型参数为 Void?
    4. 关于思考题,如果我上面的理解没错的话,我觉得是不同的线程池,一个用于执行回调函数,另一个属于 Tomcat 用来执行 Handler 业务逻辑,不知道对不对...
    展开
    
    
  • 刘晓林
    2019-08-21
    老师,NIO2中,由于TCP是一个流,那内核把多少字节拷贝到buff中才触发回调函数呢?比如一次http请求,有没有可能触发回调函数时,还没有把一个完整的http请求包接受完整呀?

    作者回复: 对的,可能需要多次回调才能接收一个完整的请求

    
    
我们在线,来聊聊吧