Tomcat 8(十)HTTP/AJP Connector、Bio/Nio/Apr性能对比

Tomcat 8(七)解读Bootstrap介绍过,Connector初始化/启动的时候,将初始化/启动内部的ProtocolHandler。其实ProtocolHandler只是个接口

ProtocolHandler的UML图(以下这些类在org.apache.coyote包下)

创建Connector对象时,Connector的构造函数内会根据server.xml的Connector标签的配置创建ProtocolHandler(默为Http11NioProtocol)

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)方法内容:

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 {
                setProtocolHandlerClassName
                    ("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

<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

<%@ 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注释掉

<!--
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
-->

并修改Connector标签的protocol属性

测试JIoEndpoint的配置:

<Connector port="8080" protocol="org.apache.coyote.http11.Http11Protocol "
               connectionTimeout="20000"
               redirectPort="8443" />

测试NioEndpoint的配置:

<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性能对比

时间: 2024-10-06 00:31:21

Tomcat 8(十)HTTP/AJP Connector、Bio/Nio/Apr性能对比的相关文章

Tomcat Connector三种运行模式(BIO, NIO, APR)的比较和优化

Tomcat Connector的三种不同的运行模式性能相差很大,有人测试过的结果如下: 这三种模式的不同之处如下: BIO: 一个线程处理一个请求.缺点:并发量高时,线程数较多,浪费资源. Tomcat7或以下,在Linux系统中默认使用这种方式. NIO: 利用Java的异步IO处理,可以通过少量的线程处理大量的请求. Tomcat8在Linux系统中默认使用这种方式. Tomcat7必须修改Connector配置来启动: <Connector port="8080" pro

Tomcat Connector三种执行模式(BIO, NIO, APR)的比較和优化

Tomcat Connector的三种不同的执行模式性能相差非常大,有人測试过的结果例如以下: 这三种模式的不同之处例如以下: BIO: 一个线程处理一个请求.缺点:并发量高时,线程数较多,浪费资源. Tomcat7或下面,在Linux系统中默认使用这样的方式. NIO: 利用Java的异步IO处理.能够通过少量的线程处理大量的请求. Tomcat8在Linux系统中默认使用这样的方式. Tomcat7必须改动Connector配置来启动: <Connector port="8080&qu

tomcat bio nio apr 模式性能测试

转自:tomcat bio nio apr 模式性能测试与个人看法 11.11活动当天,服务器负载过大,导致部分页面出现了不可访问的状态.那后来主管就要求调优了,下面是tomcat bio.nio.apr模式以及后来自己测试的一些性能结果. 原理方面的资料都是从网上找的,并且把多个地方的整理到了一起,觉得很有意义.(后面对tomcat默认页面测试的数据是自己测出来的),tomcat 的三种模式如果用对了场合,性能绝对有大幅度的提升.当然调优也并不只在这一个方面,还有内存(堆内存.非堆内存.新生代

Java--Stream,NIO ByteBuffer,NIO MappedByteBuffer性能对比

目前Java中最IO有多种文件读取的方法,本文章对比Stream,NIO ByteBuffer,NIO MappedByteBuffer的性能,让我们知道到底怎么能写出性能高的文件读取代码. package com.seeyon.nio; import org.junit.Test; import java.io.*; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.Fi

Tomcat 的三种(bio,nio.apr) 高级 Connector 运行模式

tomcat的运行模式有3种.修改他们的运行模式.3种模式的运行是否成功,可以看他的启动控制台,或者启动日志.或者登录他们的默认页面http://localhost:8080/查看其中的服务器状态. 1)bio 默认的模式,性能非常低下,没有经过任何优化处理和支持. 2)nio 利用java的异步io护理技术,no blocking IO技术. 想运行在该模式下,直接修改server.xml里的Connector节点,修改protocol为  <Connector port="80&quo

tomcat connector : bio nio apr

先记录 BIO: blocking I/O,阻塞式I/O操作 一个线程处理一个请求.缺点:并发量高时,线程数较多,浪费资源. Tomcat7或以下,在Linux系统中默认使用这种方式. NIO:non-blocking I/O 利用Java的异步IO处理,可以通过少量的线程处理大量的请求. Tomcat8在Linux系统中默认使用这种方式. Tomcat7必须修改Connector配置来启动: <Connector port="8080" protocol="org.a

Tomcat Connector(BIO, NIO, APR)三种运行模式(转)

Tomcat支持三种接收请求的处理方式:BIO.NIO.APR . BIO 阻塞式I/O操作即使用的是传统 I/O操作,Tomcat7以下版本默认情况下是以BIO模式运行的,由于每个请求都要创建一个线程来处理,线程开销较大,不能处理高并发的场景,在三种模式中性能也最低. 配置如下(tomcat安装目录下的/conf/server.xml): <Connector port="8080" protocol="HTTP/1.1" connectionTimeout

java并发之bio nio aio

最近在进行tomcat优化,发现tomcat connector并发支持bio nio apr,发现想要理解tomcat并发离不开java io的理解.所有本文先探讨java对io的支持.java的io需要操作系统的支持,本文描述linux系统对io的支持,windows系统因为java生成环境使用少不再论述. 一.linux操作系统io的支持 1.同步阻塞 I/O(bio) 2.同步非阻塞I/O(nio) 3.异步非阻塞 I/O(aio) 二.java 包对io的支持 原文地址:https:/

Netty5序章之BIO NIO AIO演变

Netty5序章之BIO NIO AIO演变 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络服务器和客户端程序.Netty简化了网络程序的开发,是很多框架和公司都在使用的技术.更是面试的加分项.Netty并非横空出世,它是在BIO,NIO,AIO演变中的产物,是一种NIO框架.而BIO,NIO,AIO更是笔试中要考,面试中要问的技术.也是一个很好的加分项,加分就是加工资,你还在等什么?本章带你细细品味三者的不同! 流程图: 技术:BIO,NIO,AIO 说明:g