Tomcat的三种运行模式
Tomcat支持三种接收请求的处理方式: BIO
, NIO
, APR
BIO模式: 阻塞式I/O操作,表示Tomcat使用的是传统Java I/O操作(即:java.io包及其子包);Tomcat 7以下版本默认情况下是以BIO模式运行的,由于每个请求的都要创建一个线程来处理,因此 线程的开销较大,不能处理高兵的场景,在三种模式中性能也最低效;启动Tomcat看日志如下表示为BIO模式:
NIO模式: 是Java SE 1.4以后续版本提供的一种新的I/O操作方式(即:java.nio包及其子包);是一个基于 缓存区
、并提供非阻塞I/O操作的Java API,它拥有比传统的I/O操作(BIO)更好的并发运行性能;
APR模式: 简单理解就是,从操作系统级别解决异步IO问题,大幅度的提高服务器的处理合相应性能,也是Tomcat运行高并发应用的首选模式;
官方对三种运行模式的区别说明如下:
参数 | Java Blocking Connector (BIO模式) | Java Nio Blocking Connector(NIO模式) | APR/native Connector(APR模式) |
---|---|---|---|
classname | AjpProtocol | AjpNioProtocol | AjpAprProtocol |
Tomcat Version | 3.x onwards | 7.x onwards | 5.5.x onwards |
Support Polling | NO | YES | YES |
Polling Size | N/A | maxConnections | maxConnections |
Read Request Headers | Blocking | Sim Blocking | Blocking |
Read Request Body | Blocking | Sim Blocking | Blocking |
Write Response | Blocking | Sim Blocking | Blocking |
Wait for next Request | Blocking | Non Blocking | Non Blocking |
Max Connections | maxConnections | maxConnections | maxConnections |
特征
模式 | 默认运行版本 | 处理方式 |
---|---|---|
BIO运行模式 | Tomcat7或以下版本 | 一个线程处理一个请求;缺点:并发量高是,线程数较多,浪费资源 |
NIO运行模式 | Tomcat8版本 | 利用Java的异步IO处理,可通过少量的线程处理大量请求; |
APR运行模式 | Tomcat7 或 8 在win7或以上系统中默认使用 | 从操作系统层面解决IO阻塞问题; |
Tomcat启动时,可以通过 catalina.out
启动日志查看使用的是哪种运行模式:
Starting ProtocolHandler ["http-bio-8080"] ## BIO模式
Starting ProtocolHandler ["http-nio-8080"] ## NIO模式
Starting ProtocolHandler ["http-apr-8080"] ## APR模式
Tomcat BIO模式
自Tomcat 8.5 版本开始,Tomcat就移除了对BIO的支持; BIO即阻塞式I/O,是java提供的最基本的I/O方式。在网络通信(此处主要讨论TCP/IP协议)中,需要通过Socket在客户端与服务端建立双向链接以实现通信,主要步骤如下:
(1) 服务端监听某个端口是否有链接请求
(2) 客户端想服务端发出链接请求
(3) 服务端想客户端返回Accept(接受)消息,此时链接成功
(4) 客户端和服务端通过send()、write()等方法与对方通信
(5) 关闭链接
Tomcat 7以下版本默认情况下是以BIO模式运行的,由于每个请求的都要创建一个线程来处理,因此 线程的开销较大,不能处理高并发的场景,在三种模式中性能也最低效;启动Tomcat看日志如下表示为BIO模式:
Tomcat NIO模式
重要提示:使用这些功能需要使用APR或NIO HTTP连接器。传统的java.io HTTP连接器和AJP连接器不支持它们
传统的BIO方式是基于流进行读写的,而且是阻塞的,整体性能比较差; 为了提供I/O性能,JDK自1.4版本引入了NIO模式,它弥补了原来BIO方式的不足,在标准的java代码中提供了 高速、面向块的I/O。 通过定义包含数据的类以及以块的形式处理数据,NIO可以在不编写本地代码的情况下利用底层优化,这是BIO所无法做到的;
NIO模式 是Java SE 1.4及后续版本提供的一种新的I/O操作方式(即java.nio包及其子包)。是一个基于缓冲区、并能提供非阻塞I/O操作的Java API,它拥有比传统I/O操作(bio)更好的并发运行性能。要让Tomcat以nio模式来运行比较简单,只需要在Tomcat安装目录/conf/server.xml文件中将如下配置:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
修改成:
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000"
redirectPort="8443" />
注意: Tomcat8以上版本,默认使用的就是NIO模式;不需要额外修改
提示: 更改模式时,如果只修改上述文件内容,则只有 ["http-nio-8180"]
被修改为NIO模式,若想上图中2处都修改为 NIO模式
则还需要修改如下内容:
<Connector port="8109" protocol="AJP/1.3" redirectPort="8443" />
改为:
<Connector port="8109" protocol="org.apache.coyote.http11.Http11NioProtocol" redirectPort="8443" />
以下属性是特定于NIO连接器 NIO连接器官方详细说明
Tomcat NIO2模式
NIO2是JDK7新增的文件及网络I/O特性,它继承自NIO 同时添加了众多特性及功能改进,其中最重要的即是对异步I/O(AIO)的支持;
1 . 通道 在AIO中,通道必须实现接口
java.nio.chanels.AsynchronousChannel(继承自java.nio.channels.Channel)
JDK7提供了3个通道实现类:java.nio.channels.AsynchronousFileChannel用于文件I/O
,java.nio.channels.AsynchronousServerSocketChannel
和java.nio.channels.AsynchronousSocketChannel用于网络I/O
2 . 缓冲区 AIO仍通过操作缓冲区完成数据的读写操作,这里不再阐述。
3 . Future 和 CompletionHandler AIO操作存在两种操作方式: Future 和 CompletionHandler ; 我们可以使用其中任何一种来完成I/O操作 首先, AIO使用了java并发包的API,无论接收Socket请求还是读写操作,均可以返回一个java.util.concurrent.Future对象来表示I/O处于等待状态; 通过Future的方法,我们可以检测操作是否完成(isDone)、等待完成并取得操作结果(get)等。 当接收请求(accept)结束时,Future.get返回值为AsynchronousSocketChannel; 读写操作时(read/write),Future.get返回值为读写操作结果。
4 . 异步通道组 AIO新引入了异步通道组(Asynchronous Channel Group)的概念,每个异步通道均属于一个指定的异步通道组,同一个通道组内的通道共享一个线程池; 线程池内的线程接收指令来执行I/O事件并将结果分发到CompletionHandler。 异步通道组包括线程池以及所有通道工作线程共享的资源。通道生命周期受所属通道组影响,当通道组关闭后,通道也随之关闭;
Tomcat APR模式
APR模式:简单来说,就是从操作系统级别解决异步IP问题,大幅度的提高服务器的处理和响应性能,也是Tomcat运行高并发应用的首选模式;
启动这种模式需要安装一些依赖库,下面进行详细说明:
基于Apache Portable Runtime(APR)的Tomcat本地库
安装要求:
APR 1.2+开发头文件(libapr1-dev包)
OpenSSL 0.9.7+开发头文件(libssl-dev包)
来自Java兼容JDK 1.4+的JNI头文件
GNU开发环境(gcc,make)
apr的安装
下载apr包地址(http://apache.fayea.com/apr/)
## 下载解压
wget http://apache.fayea.com/apr/apr-1.6.3.tar.gz
wget http://apache.fayea.com/apr/apr-util-1.6.1.tar.gz
tar fxz apr-1.6.3.tar.gz
tar fxz apr-util-1.6.1.tar.gz
## 安装
cd apr-1.6.3/
./configure --prefix=/usr/local/apr
make && make install
cd apr-util-1.6.1/
./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr
make && make install
安装tomcat-native
cd /usr/local/tomcat/bin tar -zxvf tomcat-native.tar.gz
cd tomcat-native-1.1.22-src/jni/native
./configure --with-apr=/usr/local/apr
make && make install
设置apr环境变量
# vim /etc/profile
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/apr/lib
# 执行 source /etc/profile 立即生效
修改Tomcat配置文件
修改http协议
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
修改成:
<Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol"
connectionTimeout="20000"
redirectPort="8443" />
修改AJP协议
<Connector port="8109" protocol="AJP/1.3" redirectPort="8443" />
改为:
<Connector port="8109" protocol="org.apache.coyote.http11.Http11AprProtocol" redirectPort="8443" />
总结
对于每种协议,Tomcat都提供了对应的I/O方式的实现,而且Tomcat官方还提供了在每种协议下每种I/O实现方案的差异; HTTP协议下的处理方式如下表:
NIO | NIO2 | APR | |
---|---|---|---|
引用版本 | ≥6.0 | ≥8.0 | ≥5.5 |
轮询支持 | 是 | 是 | 是 |
轮询队列大小 | maxConnections | maxConnections | maxConnections |
读请求头 | 非阻塞 | 非阻塞 | 非阻塞 |
读请求体 | 阻塞 | 阻塞 | 阻塞 |
写响应 | 阻塞 | 阻塞 | 阻塞 |
等待新请求 | 非阻塞 | 非阻塞 | 非阻塞 |
SSL支持 | Java SSL/Open SSL | Java SSL/Open SSL | Open SSL |
SSL握手 | 非阻塞 | 非阻塞 | 阻塞 |
最大链接数 | maxConnections | maxConnections | maxConnections |