作者回复: 对的
作者回复: 我使用的是最新版的代码:
https://github.com/apache/tomcat/blob/master/java/org/apache/tomcat/util/net/Nio2Endpoint.java#L382
作者回复: 可能是代码版本不对,我看的是9.0.20最新版
作者回复: 刚我查了下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没有使用这种方案。抱歉弄错了,还是不能人云亦云,一定要自己看了源码才行...
作者回复: Nio2SocketWrapper的read方法,这个方法会被调用两次,不是串行调两次,而是Poller会先后创建两个SocketProcessor任务类,在两个线程中执行,执行过程中每次Http11Processor都会调Nio2SocketWrapper的read方法。
public int read(boolean block, ByteBuffer to){
//第二次调用时直接通过这个方法取数据
int nRead = populateReadBuffer(to);
...
//第一次时数据没取到,会调用下面这个方法去真正执行I/O操作并注册回调函数:
nRead = fillReadBuffer(block);
...
}
作者回复: 主要还是堆外内存管理起来没有JVM堆那么方便,为了稳定性的考虑吧,另外APR就是堆外内存的方案,也就是已经提供了这个选项。
作者回复: 好问题,下一篇就会解释这个问题。
作者回复: 详细介绍
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-web-servers.html
作者回复: 我尽量贴全,有时候代码太多不好贴,最好课后去看看源码
作者回复: 1,select只是查询,真正发出read调用的还是read方法
2,好像没有异步阻塞这个说法
3,同步阻塞模型,read调用发起时,数据可能还没到网卡。如果io多路复用,read调用时,数据已经到了内核空间,因为之前select已经查到数据到了,应用才调read
作者回复: 数据没有拷贝两次,第一次read调用是读不到数据的,因为这个时候数据还没应用层的Buffer,只是注册一个回调函数,当内核将数据拷贝到了应用层Buffer,调用回调函数,在回调函数里,HttpProccessor再发起一次read,read方法首先会检查数据是不是已经到了Buffer,如果是,直接读取Buffer返回,这一次并没有真正向内核发起read调用。
作者回复: 对的,可能需要多次回调才能接收一个完整的请求