tomcat 版本:8.0.15, connector和executor区别。
网上很多混淆了,异步servlet和非阻塞connector,一个是Executor,一个是connector,两者的工作阶段不同。
connector:
这个是指,外部IP连接到服务器,好比抢票软件在抢12306的火车票,因此一坨一坨的连接到12306。因此,会有很多connection(连接),建立、维护、管理这些连接,这就是connector要做的事情。显然这是web服务器性能的重要指标。即,可支持的每秒最大连接数。
connector,可以采用,blocking I/O,nio,ajp,apr
Servlet:
一个Servelet,就是一个线程一次的执行过程。比如响应doGet(),这个是在一个独立的线程中完成的。
当connector建立连接后,服务器会分配一个线程(可能是从线程池)去服务这个连接,即执行doGet等方法,执行完,回收线程。显然这一步是一个同步的过程,tomcat对应的是Executor
- 显然,具体实现由多种方式:connector和Servlet可以共用一个线程,这种web服务方案,即为 每连接一个线程 Connection per thread。每次来个请求,服务器便创建一个线程(或者线程池中选择线程)由于线程不可能无限制增加,当线程比较多时,服务负载会很大。
这种方式的优点是,简单,适合CPU型
- Request per thread 每请求一个线程,即等到具体服务请求时,才独立分配线程方式。而这个线程通常是在线程池中分配,如果没有空闲的执行线程,那么请求会被挂起,当请求挂起的数目(即排队数)超过预设最大请求数(tomcat中maxConnections值),服务会拒绝服务器(Service Unavailable)。apache,tomcat等主流实现方案都采用这种方式。
说明:网上很多人都以为,第二种方式,实现了高并发、高吞吐。其实,是因为第二种模型是适合常见的web服务特点,即大量的短连接(IO密集型,服务处理时间很短,大约50ms以内,但连接数很多),处理完即关闭连接,当服务是批处理类的大作业服务(CPU密集型,服务处理时间很长,常需要1秒以上,但连接数少),第二种方式不如第一种,每连接就分配一个线程运行。
此时,Connector和Servlet(Executor)也可以不共用一个线程,一个维护连接,Executor用独立的线程来服务,
tomcat采用的就是这种方式。而维护连接connector部分,常见的可以采用阻塞和非阻塞方式。实际上,tomcat8提供4种protocol:
org.apache.coyote.http11.Http11Protocol - blocking Java connectororg.apache.coyote.http11.Http11NioProtocol
- non blocking Java connectororg.apache.coyote.http11.Http11Nio2Protocol
- non blocking Java connectororg.apache.coyote.http11.Http11AprProtocol
- the APR/native connector.
tomcat8.0.15原文文档如下:
Each incoming request requires a thread for the duration of that request. If more simultaneous requests are received than can be handled by the currently available request processing threads, additional threads will be created up to the configured maximum (the value of the maxThreads
attribute). If still more simultaneous requests are received, they are stacked up inside the server socket created by the Connector, up to the configured maximum (the value of the acceptCount
attribute). Any further simultaneous requests will receive "connection refused" errors, until resources are available to process them.
可以看出,tomcat使用了线程池,线程最多增加到maxThreads ,如果还有请求进来,那么这些请求就会wait在connector上,如果connector上wait的请求超出了acceptCount ,那么服务器就返回 "connection refused"拒绝连接错误。
所以,此时,Servlet的线程数,最大maxThreads ,但连接数则最大为acceptCount
_________________________________________________________________________________
CONNECTOR之间的比较
Java Blocking Connector BIO | Java Nio Blocking Connector NIO | Java Nio2 Blocking Connector NIO2 | APR/native Connector APR | |
---|---|---|---|---|
Classname | Http11Protocol | Http11NioProtocol | Http11Nio2Protocol | Http11AprProtocol |
Tomcat Version | 3.x onwards | 6.x onwards | 8.x onwards | 5.5.x onwards |
Support Polling | NO | YES | YES | YES |
Polling Size | N/A | maxConnections | maxConnections | maxConnections |
Read HTTP Request | Blocking | Non Blocking | Non Blocking | Blocking |
Read HTTP Body | Blocking | Sim Blocking | Blocking | Blocking |
Write HTTP Response | Blocking | Sim Blocking | Blocking | Blocking |
Wait for next Request | Blocking | Non Blocking | Non Blocking | Non Blocking |
SSL Support | Java SSL | Java SSL | Java SSL | OpenSSL |
SSL Handshake | Blocking | Non blocking | Non blocking | Blocking |
Max Connections | maxConnections | maxConnections | maxConnections | maxConnections |
Connecotr和Executor的关系,其实可以类比nginx的主进程和工作进程