Tomcat中BIO和NIO的区别(Tomcat)

BIO

Tomcat中BIO的模型和理论很简单,例图如下

1.Acceptor线程死循环阻塞接收客户端的打过来的socket请求

2.接收到请求之后打包成一个SocketProcessor(Runnable),扔到线程池中读取/写入数据

参数配置

1.Acceptor默认线程是1,可以设置参数自己去改

2.Executor的线程池,一个Connector对应一个线程池,一个线程池可以被多个Connector公用,最小线程数是10,最大线程数是200

BIO总结

**1.**如果请求量很大,那么可以适当提高Acceptor线程池的线程数量

2.如果是那种处理起来效率不高的请求,那么可以适当提高Executor中的线程数

3.线程池中的线程还是要根据线上实际情况设置的,并不是越多越好,自己去压测看一下,找一个适当的值

NIO

Tomcat7中的NIO其实只有在读取请求头和请求行下才是非阻塞的,Servlet读取请求体的时候依旧还是阻塞的。执行流程如下

1.Acceptor接收客户端连接,接收到之后将socketChannel推到一个Poller(本质上也是一个Runnable)的events队列中,客户端和服务端的交互就此结束

2.推入到events队列中的是一个注册事件(要将其绑定到对应Poller中的Selector中)

3.对应Poller中的线程会去循环查询Selector中是否有事件发生,在查询之前会现将Events中的注册事件执行了,所以在执行events队列中的事件时,就相当于将socketChannel注册到Selector中。

4.socketChannel中的读写事件被Poller轮询到,就会socketChannel和读写事件打包成一个SocketProcessor,然后扔到Executor中执行读写逻辑

5.当SocketProcessor中的线程运行时,就会从socketChannel中读取/写入数据时(非阻塞),如果发现请求行和请求头已经读写并且解析完了,那么就会将剩下的交给Servlet处理,Servlet中可能会读写数据,或者发起响应,Servlet的这两个操作都是阻塞的。如果SocketProcessor线程读取到了数据,但是发现请求行和请求头的数据还没有读完,那么本次请求直接结束,要处理的话只能等下一次就绪事件

6.tomcat7中读取请求体的时候其实依旧是阻塞的,因为tomcat7本身并没有非阻塞这个概念,servlet读取请求体时底层依旧是用inputStream.read()方法读取,并且是阻塞的

7.Servlet读取请求体inputStream.read()方法底层调用的是InternalNioInputBuffer.SocketInputBuffer.doRead(),在这个方法中会调用fill(param1,param2)方法从操作系统读取数据

8.阻塞读取数据流的时候,还是得利用Selector,因为刚开始的时候socketChannel会被设置成非阻塞,然后socketChannel会被注册到一个Selector(称为主Selector),然后你如果再想把他改成阻塞,是会报错的(NIO中的限制),tomcat中为了实现这个阻塞,又构造了一个辅助Selector,将socketChannel重新注册到辅助Selector上,并设置成阻塞(在此之前已经取消了对主Selector的绑定)

9.首先先InputStream.read(),然后加锁(为了实现阻塞),辅助Selector也有与之对应的Poller线程,也会去轮询辅助Selector上发生的就绪事件。一旦轮询到对应的事件,就会解锁,解阻塞

10.从socketChannel中读取数据,结束

NIO总结

Tomcat7中的NIO其实相对于BIO并没有太多的性能提升,只是可以接收更多的客户端请求(NIO直接推到Events队列中就直接返回了),真正的在处理请求的时候并没有体现出太大的优势,如果是那种不用处理请求数据,并且不用响应什么数据的那种请求,那么NIO会有非常好的吞吐量

相关推荐
ღ᭄陽先生꧔ꦿ᭄14 分钟前
Java异常架构与异常关键字
java·开发语言·架构
繁依Fanyi21 分钟前
【问题随记】在使用 AuthenticationManager 的时候,出现循环依赖问题 —— `java.lang.StackOverflowError`
java·大数据·开发语言
代码代码快快显灵28 分钟前
TomCat乱码问题
服务器·ajax·tomcat
年轻的高血压患者30 分钟前
Java servlet《网吧机房管理系统浅析》
java·mysql·servlet·eclipse·idea
远望樱花兔1 小时前
【d46】【Java】【力扣】876.链表的中间结点
java·leetcode
严文文-Chris1 小时前
【设计模式-备忘录】
java·设计模式
码上一元1 小时前
【百日算法计划】:每日一题,见证成长(019)
java·数据结构·算法
shiming88791 小时前
在IntelliJ IDEA中创建一个HTML项目
java·html·intellij-idea
xcLeigh1 小时前
html实现好看的多种风格手风琴折叠菜单效果合集(附源码)
android·java·html
一丝晨光1 小时前
语言的循环语句
java·c++·python·c#·c·fortran·algol