Tomcat 8(十)HTTP/AJP Connector、Bio/Nio/Apr性能对比
2017-02-13 16:54
393 查看
Tomcat 8(七)解读Bootstrap介绍过,Connector初始化/启动的时候,将初始化/启动内部的ProtocolHandler。其实ProtocolHandler只是个接口
ProtocolHandler的UML图(以下这些类在org.apache.coyote包下)
创建Connector对象时,Connector的构造函数内会根据server.xml的Connector标签的配置创建ProtocolHandler(默为Http11NioProtocol)
[java] view
plain copy
public Connector(String protocol) {
setProtocol(protocol);
// Instantiate protocol handler
ProtocolHandler p = null;
try {
Class<?> clazz = Class.forName(protocolHandlerClassName);
p = (ProtocolHandler) clazz.newInstance();
} catch (Exception e) {
log.error(sm.getString(
"coyoteConnector.protocolHandlerInstantiationFailed"), e);
} finally {
this.protocolHandler = p;
}
if (!Globals.STRICT_SERVLET_COMPLIANCE) {
URIEncoding = "UTF-8";
URIEncodingLower = URIEncoding.toLowerCase(Locale.ENGLISH);
}
}
setProtocol(protocol)方法内容:
[java] view
plain copy
public void setProtocol(String protocol) {
//protocol对应server.xml的Connector标签的protocol属性
if (AprLifecycleListener.isAprAvailable()) {
if ("HTTP/1.1".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.http11.Http11AprProtocol");
} else if ("AJP/1.3".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.ajp.AjpAprProtocol");
} else if (protocol != null) {
setProtocolHandlerClassName(protocol);
} else {
setProtocolHandler
1b406
ClassName
("org.apache.coyote.http11.Http11AprProtocol");
}
} else {
if ("HTTP/1.1".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.http11.Http11NioProtocol");
} else if ("AJP/1.3".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.ajp.AjpNioProtocol");
} else if (protocol != null) {
setProtocolHandlerClassName(protocol);
}
}
}
如果server.xml配置了AprLifecycleListener
[html] view
plain copy
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
AprLifecycleListener.isAprAvailable()为true
Connector支持两种协议:HTTP/1.1和AJP/1.3
HTTP比较熟悉,在此不做说明了。AJP主要用于Tomcat的负载均衡,即Web Server(如Apache) 可以通过AJP协议向Tomcat发请求
AJP(Apache JServ Protocol)是一种定向包协议, 用于将传入Web Server(如Apache)的request传递到处理具体业务的Application Server(如Tomcat)
AJP的优点:
1. AJP使用二进制格式来传输可读性文本,Web Server通过TCP连接Application Server,较HTTP性能更高
2. 为了减少生成socket的开销,Web Server和Application Server之间尝试保持持久性的TCP连接,对多个request/response循环重用一个连接
3. 一旦连接分配给一个特定的request,在该request完成之前不会再分配给其他request。因此,request在一个连接上是独占的,这使连接两端的编码变得简洁
4. 在连接上发送的基本请求信息是高度压缩的
AJP的缺点:
1. 某一时刻的连接数可能较多
2. HTTP Connector可以在Server.xml设置有效时间(connectionTimeout),而AJP Connector是永久有效
AJP协议的设计:http://httpd.apache.org/docs/2.2/mod/mod_proxy_ajp.html
下面来测试下HTTP和AJP的性能
测试环境:win8.1 64位(4核、4G内存) + Tomcat8.0.3
64位 + jdk1.7.0_51 64位
压力测试工具:Apache ab
监控工具:Process Explorer、任务管理器
测试方法:在Tomcat\webapps\examples下创建index.jsp
[html] view
plain copy
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page import="java.text.SimpleDateFormat"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Test</title>
</head>
<body>
Server Info:
<%
String dtm = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date());
System.out.println("["+request.getLocalAddr()+":"+ request.getLocalPort()+"]" + dtm);
out.println("<br>["+request.getLocalAddr()+":" +request.getLocalPort()+"]" + dtm+"<br>");
%>
Session Info:
<%
session.setAttribute("name","dennisit");
System.out.println("[Session Info] Session ID:"+session.getId());
out.println("<br>[Session Info] Session ID:" + session.getId()+"<br>");
%>
</body>
</html>
index.jsp的内容比较简单,就是获取Server信息和Session信息。Tomcat 8默认配置下,配置了AprLifecycleListener,监听8080端口的Connector使用HTTP/1.1协议;监听8009端口的Connector使用AJP/1.3协议,这两个端口默认使用apr模式。使用ab向HTTP Connector/AJP Connector发送10000个请求(并发量设为1000)
测试HTTP Connector的命令:ab -n 10000 -c 1000 localhost:8080/examples/index.jsp
测试AJP Connector的命令:ab -n 10000 -c 1000 localhost:8009/examples/index.jsp
以下数据是三次测试的平均值(注:每次只测一个Connector,每次测试都会重启Tomcat)
名词解释:
时间-处理完所有请求所用的时间(单位:s)
CPU-Java.exe进程的CPU占用峰值
内存-java.exe进程的内存占用峰值(单位:MB)
流量-处理请求期间的宽带占用(单位:kb/s)
测试结果:
通过上表可以看出,AJP处理请求稍快一点,但使用AJP时,CPU和内存占用更少,宽带占用几乎为0(由于使用AJP时,发送的基本请求信息是高度压缩。当然,也跟这个请求简单有关系)
所以,AJP Connector的性能更优
每个ProtocolHandler内部都有一个Endpoint,ProtocolHandler初始化/启动的时候,将初始化/启动其内部的Endpoint
Tomcat有三种Endpoint:JIoEndpoint、NioEndpoint、AprEndpoint
ProtocolHandler与Endpoint的对应关系
Http11Protocol/AjpProtocol使用JIoEndpoint
Http11NioProtocol/AjpNioProtocol使用NioEndpoint
Http11AprProtocol/AjpAprProtocol使用AprEndpoint
Server.xml的Connector标签配置的部分属性(如port),在Endpoint中才真正被使用。因此只有Endpoint启动了,Tomcat才开始监听指定端口
学习这三种Endpoint之前,需要了解下java io和java nio,可参考这两篇文章:
http://www.cnblogs.com/flyoung2008/p/3251826.html
http://tutorials.jenkov.com/java-nio/index.html
JIoEndpoint:使用java io(也称为bio)技术,即一个请求对应一个线程。缺点:并发量高时,线程数较多,占资源
NioEndpoint:使用java nio技术,可以通过少量的线程处理大量的请求
AprEndpoint:Apr即Apache Portable Runtime,从操作系统层面解决io阻塞问题。使用Apr时将用到Tomcat\bin\tcnative-1.dll (使用Apr时,应用了jni技术)。
Tomcat 8默认配置下,HTTP Connector和AJP Connector均使用Apr。测试AprEndpoint,使用Tomcat 8的默认配置即可。测试JIoEndpoint、NioEndpoint需要将server.xml中的AprLifecycleListener注释掉
[html] view
plain copy
<!--
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
-->
并修改Connector标签的protocol属性
测试JIoEndpoint的配置:
[html] view
plain copy
<Connector port="8080" protocol="org.apache.coyote.http11.Http11Protocol "
connectionTimeout="20000"
redirectPort="8443" />
测试NioEndpoint的配置:
[html] view
plain copy
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol "
connectionTimeout="20000"
redirectPort="8443" />
三种Endpoint的测试采用HTTP Connector
测试结果:
通过上表可以看出,Apr处理请求最快,Bio最慢;Apr宽带占用最高,Bio最低;但Apr的内存占用最高,而Nio的内存占用最低
所以综合来看,Nio适用于一般需求;Apr适用于高并发需求
ProtocolHandler的UML图(以下这些类在org.apache.coyote包下)
创建Connector对象时,Connector的构造函数内会根据server.xml的Connector标签的配置创建ProtocolHandler(默为Http11NioProtocol)
[java] view
plain copy
public Connector(String protocol) {
setProtocol(protocol);
// Instantiate protocol handler
ProtocolHandler p = null;
try {
Class<?> clazz = Class.forName(protocolHandlerClassName);
p = (ProtocolHandler) clazz.newInstance();
} catch (Exception e) {
log.error(sm.getString(
"coyoteConnector.protocolHandlerInstantiationFailed"), e);
} finally {
this.protocolHandler = p;
}
if (!Globals.STRICT_SERVLET_COMPLIANCE) {
URIEncoding = "UTF-8";
URIEncodingLower = URIEncoding.toLowerCase(Locale.ENGLISH);
}
}
setProtocol(protocol)方法内容:
[java] view
plain copy
public void setProtocol(String protocol) {
//protocol对应server.xml的Connector标签的protocol属性
if (AprLifecycleListener.isAprAvailable()) {
if ("HTTP/1.1".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.http11.Http11AprProtocol");
} else if ("AJP/1.3".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.ajp.AjpAprProtocol");
} else if (protocol != null) {
setProtocolHandlerClassName(protocol);
} else {
setProtocolHandler
1b406
ClassName
("org.apache.coyote.http11.Http11AprProtocol");
}
} else {
if ("HTTP/1.1".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.http11.Http11NioProtocol");
} else if ("AJP/1.3".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.ajp.AjpNioProtocol");
} else if (protocol != null) {
setProtocolHandlerClassName(protocol);
}
}
}
如果server.xml配置了AprLifecycleListener
[html] view
plain copy
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
AprLifecycleListener.isAprAvailable()为true
Connector支持两种协议:HTTP/1.1和AJP/1.3
HTTP比较熟悉,在此不做说明了。AJP主要用于Tomcat的负载均衡,即Web Server(如Apache) 可以通过AJP协议向Tomcat发请求
AJP(Apache JServ Protocol)是一种定向包协议, 用于将传入Web Server(如Apache)的request传递到处理具体业务的Application Server(如Tomcat)
AJP的优点:
1. AJP使用二进制格式来传输可读性文本,Web Server通过TCP连接Application Server,较HTTP性能更高
2. 为了减少生成socket的开销,Web Server和Application Server之间尝试保持持久性的TCP连接,对多个request/response循环重用一个连接
3. 一旦连接分配给一个特定的request,在该request完成之前不会再分配给其他request。因此,request在一个连接上是独占的,这使连接两端的编码变得简洁
4. 在连接上发送的基本请求信息是高度压缩的
AJP的缺点:
1. 某一时刻的连接数可能较多
2. HTTP Connector可以在Server.xml设置有效时间(connectionTimeout),而AJP Connector是永久有效
AJP协议的设计:http://httpd.apache.org/docs/2.2/mod/mod_proxy_ajp.html
下面来测试下HTTP和AJP的性能
测试环境:win8.1 64位(4核、4G内存) + Tomcat8.0.3
64位 + jdk1.7.0_51 64位
压力测试工具:Apache ab
监控工具:Process Explorer、任务管理器
测试方法:在Tomcat\webapps\examples下创建index.jsp
[html] view
plain copy
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page import="java.text.SimpleDateFormat"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Test</title>
</head>
<body>
Server Info:
<%
String dtm = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date());
System.out.println("["+request.getLocalAddr()+":"+ request.getLocalPort()+"]" + dtm);
out.println("<br>["+request.getLocalAddr()+":" +request.getLocalPort()+"]" + dtm+"<br>");
%>
Session Info:
<%
session.setAttribute("name","dennisit");
System.out.println("[Session Info] Session ID:"+session.getId());
out.println("<br>[Session Info] Session ID:" + session.getId()+"<br>");
%>
</body>
</html>
index.jsp的内容比较简单,就是获取Server信息和Session信息。Tomcat 8默认配置下,配置了AprLifecycleListener,监听8080端口的Connector使用HTTP/1.1协议;监听8009端口的Connector使用AJP/1.3协议,这两个端口默认使用apr模式。使用ab向HTTP Connector/AJP Connector发送10000个请求(并发量设为1000)
测试HTTP Connector的命令:ab -n 10000 -c 1000 localhost:8080/examples/index.jsp
测试AJP Connector的命令:ab -n 10000 -c 1000 localhost:8009/examples/index.jsp
以下数据是三次测试的平均值(注:每次只测一个Connector,每次测试都会重启Tomcat)
名词解释:
时间-处理完所有请求所用的时间(单位:s)
CPU-Java.exe进程的CPU占用峰值
内存-java.exe进程的内存占用峰值(单位:MB)
流量-处理请求期间的宽带占用(单位:kb/s)
测试结果:
通过上表可以看出,AJP处理请求稍快一点,但使用AJP时,CPU和内存占用更少,宽带占用几乎为0(由于使用AJP时,发送的基本请求信息是高度压缩。当然,也跟这个请求简单有关系)
所以,AJP Connector的性能更优
每个ProtocolHandler内部都有一个Endpoint,ProtocolHandler初始化/启动的时候,将初始化/启动其内部的Endpoint
Tomcat有三种Endpoint:JIoEndpoint、NioEndpoint、AprEndpoint
ProtocolHandler与Endpoint的对应关系
Http11Protocol/AjpProtocol使用JIoEndpoint
Http11NioProtocol/AjpNioProtocol使用NioEndpoint
Http11AprProtocol/AjpAprProtocol使用AprEndpoint
Server.xml的Connector标签配置的部分属性(如port),在Endpoint中才真正被使用。因此只有Endpoint启动了,Tomcat才开始监听指定端口
学习这三种Endpoint之前,需要了解下java io和java nio,可参考这两篇文章:
http://www.cnblogs.com/flyoung2008/p/3251826.html
http://tutorials.jenkov.com/java-nio/index.html
JIoEndpoint:使用java io(也称为bio)技术,即一个请求对应一个线程。缺点:并发量高时,线程数较多,占资源
NioEndpoint:使用java nio技术,可以通过少量的线程处理大量的请求
AprEndpoint:Apr即Apache Portable Runtime,从操作系统层面解决io阻塞问题。使用Apr时将用到Tomcat\bin\tcnative-1.dll (使用Apr时,应用了jni技术)。
Tomcat 8默认配置下,HTTP Connector和AJP Connector均使用Apr。测试AprEndpoint,使用Tomcat 8的默认配置即可。测试JIoEndpoint、NioEndpoint需要将server.xml中的AprLifecycleListener注释掉
[html] view
plain copy
<!--
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
-->
并修改Connector标签的protocol属性
测试JIoEndpoint的配置:
[html] view
plain copy
<Connector port="8080" protocol="org.apache.coyote.http11.Http11Protocol "
connectionTimeout="20000"
redirectPort="8443" />
测试NioEndpoint的配置:
[html] view
plain copy
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol "
connectionTimeout="20000"
redirectPort="8443" />
三种Endpoint的测试采用HTTP Connector
测试结果:
通过上表可以看出,Apr处理请求最快,Bio最慢;Apr宽带占用最高,Bio最低;但Apr的内存占用最高,而Nio的内存占用最低
所以综合来看,Nio适用于一般需求;Apr适用于高并发需求
相关文章推荐
- Tomcat 8(十)HTTP/AJP Connector、Bio/Nio/Apr性能对比
- Tomcat 8(十)HTTP/AJP Connector、Bio/Nio/Apr性能对照
- tomcat bio nio apr 模式性能测试与个人看法
- tomcat-tomcat bio nio apr 模式性能测试与个人看法
- tomcat bio nio apr 模式性能测试
- tomcat bio nio apr 模式性能测试与个人看法
- java aio tomcat bio nio apr 模式性能测试
- tomcat bio nio apr 模式性能测试与个人看法
- Tomcat Connector运行模式bio/nio/apr,优化Tomcat运行性能
- ab测试tomcat并发性能(测试BIO与NIO差别)(一)
- Tomcat 6 支持 NIO -- Tomcat的四种基于HTTP协议的Connector性能比较
- Tomcat 的三种(bio,nio.apr) 高级 Connector 运行模式
- Tomcat Connector三种运行模式(BIO, NIO, APR)的比较和优化
- tomcat7.0.27的bio,nio.apr高级运行模式(转)
- Tomcat 的三种(bio,nio.apr) 高级 Connector 运行模式(未完善)
- Tomcat 的三种(bio,nio.apr) 高级 Connector 运行模式
- Tomcat 的三种(bio,nio.apr) 高级 Connector 运行模式
- tomcat 7 HTTP Connector BIO/NIO
- Tomcat 的三种(bio,nio.apr) 高级 Connector 运行模式
- tomcat的三种模式(bio、nio、apr)