zoukankan      html  css  js  c++  java
  • Tomcat 8(十)HTTP/AJP Connector、Bio/Nio/Apr性能对照

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

    ProtocolHandlerUML(下面这些类在org.apache.coyote包下)


    创建Connector对象时,Connector的构造函数内会依据server.xmlConnector标签的配置创建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 ServerApplication 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


    以下来測试下HTTPAJP的性能

    測试环境:win8.1 64位(4核、4G内存) + Tomcat8.0.3 64位 + jdk1.7.0_51 64位

    压力測试工具:Apache ab

    监控工具:Process Explorer、任务管理器

    測试方法:在Tomcatwebappsexamples下创建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,监听8080port的Connector使用HTTP/1.1协议;监听8009port的Connector使用AJP/1.3协议,这两个port默认使用apr模式。使用abHTTP 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内部都有一个EndpointProtocolHandler初始化/启动的时候,将初始化/启动其内部的Endpoint

    Tomcat有三种Endpoint:JIoEndpoint、NioEndpoint、AprEndpoint

    ProtocolHandlerEndpoint的相应关系

    Http11Protocol/AjpProtocol使用JIoEndpoint

    Http11NioProtocol/AjpNioProtocol使用NioEndpoint

    Http11AprProtocol/AjpAprProtocol使用AprEndpoint

    Server.xmlConnector标签配置的部分属性(port),在Endpoint中才真正被使用。因此仅仅有Endpoint启动了,Tomcat才開始监听指定端口

    学习这三种Endpoint之前,须要了解下java iojava nio,可參考这两篇文章:

    http://www.cnblogs.com/flyoung2008/p/3251826.html

    http://tutorials.jenkov.com/java-nio/index.html

    JIoEndpoint:使用java io(也称为bio)技术,即一个请求相应一个线程。缺点:并发量高时,线程数较多,占资源

    NioEndpoint:使用java nio技术,能够通过少量的线程处理大量的请求

    AprEndpointAprApache Portable Runtime,从操作系统层面解决io堵塞问题。使用Apr时将用到Tomcatin cnative-1.dll (使用Apr时,应用了jni技术)

    Tomcat 8默认配置下,HTTP ConnectorAJP Connector均使用Apr。測试AprEndpoint,使用Tomcat 8的默认配置就可以。測试JIoEndpointNioEndpoint须要将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适用于高并发需求

  • 相关阅读:
    ue4 材质表达式分类
    UE4材质特别属生记录
    tangent space与object space
    better-scroll插件 api
    better-scroll 与 Vue 结合
    git 简介
    vue 插件
    前端小程序——js+canvas 给图片添加水印
    使用Node.js给图片加水印的方法
    Vue框架 周期
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4494509.html
Copyright © 2011-2022 走看看