在这里我先简单的说下bio和nio的区别apache
这里我以电话客服的状况来解释tomcat
bio服务器
一个客户对应一个客服,网络
假如客户比较麻烦,中途不挂电话,或者去作其余事情了,而客服资源会被一直占用socket
致使的后果是系统处理能力大大下降性能
Nio网络传输协议
中间加入了一个协调员,假如遇到比较麻烦的用户,请求能够先到协调员这里,当用户准备好之后,在转接给客服。spa
那这两种方式有啥区别呢?.net
理论上来讲,若是是彻底没有网络延迟,阻塞的状况下,其实这二者的性能差很少。线程
可是实际状况下,服务器根本没法肯定客户端的网络状况,因此,通常不使用bio
Tomcat处理请求核心流程图
Acceptor (Acceptor的做用是控制与tomcat创建链接的数量,但Acceptor只负责创建链接)
接收socket线程,这里虽然是基于NIO的connector,可是在接收socket方面仍是传统的serverSocket.accept()方式,得到SocketChannel对象,而后封装在一个tomcat的实现类org.apache.tomcat.util.net.NioChannel对象中。而后将NioChannel对象封装在一个PollerEvent对象中,并将PollerEvent对象压入一个队列中里。这是典型的生产者-消费者模式,Acceptor与Poller线程之间经过queue通讯,Acceptor是生产者,Poller是消费者。
Poller (socket内容的读写)
Poller线程中维护了一个Selector对象,NIO就是基于Selector来完成逻辑的。
Poller是NIO实现的主要线程。首先做为消费者,从队列中取出PollerEvent对象,而后将此对象中的channel以OP_READ事件注册到Selector中,而后Selector执行select操做,遍历出能够读数据的socket,并从Worker线程池中拿到可用的Worker线程,而后将socket传递给Worker。这个过程是典型的NIO实现。
Worker (执行相关业务逻辑)
Worker线程拿到Poller传过来的socket后,将socket封装在SocketProcessor对象中。而后从Http11ConnectionHandler中取出Http11NioProcessor对象,从Http11NioProcessor中调用CoyoteAdapter的逻辑,跟BIO实现同样。在Worker线程中,会完成从socket中读取http request,解析成HttpServletRequest对象,分派到相应的servlet并完成逻辑,而后将response经过socket发回client。
核心参数说明
参数名称 |
可选值 |
参数解释 |
protocol |
HTTP/1.1 org.apache.coyote.http11.Http11NioProtocol |
网络传输协议 bio Nio |
maxThreads |
|
工做线程的最大线程数 |
minSpareThreads |
|
工做线程的最小线程 |
connectionTimeout |
|
链接超时(当请求数量超过了 maxConnections,系统会继续接收链接但不会超过acceptCount的值 ) |
acceptCount |
|
等待队列的长度 |
acceptorThreadCount |
|
Acceptor线程数量 |
maxConnections |
|
最大链接数 |
pollerThreadCount |
|
Poller线程数量(nio独有) |