栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Tomcat 源码分析 (连接器) (六)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Tomcat 源码分析 (连接器) (六)

文章目录
      • 1.连接器概述
      • 2.连接器组件
      • 3.创建连接器对象
      • 4.IO模型与协议

1.连接器概述

Tomcat要实现两个核心功能

  1. 处理Socket连接,负责网络字节流与Request和Response对象的转化。
  2. 加载和管理Servlet,以及具体处理Request请求。

因此Tomcat设计了两个核心组件连接器(Connector)和容器(Container)来分别做这两件事情。连接器负责对外交流,容器负责内部处理。


连接器就是接收http请求并解析http请求,然后将请求交给servlet容器。

org.apache.catalina.connector.Connector

Coyote 是Tomcat的连接器框架的名称 , 是Tomcat服务器提供的供客户端访问的外部接口。客户端通过Coyote与服务器建立连接、发送请求并接受响应 。

  1. Coyote 封装了底层的网络通信(Socket 请求及响应处理),为Catalina 容器提供了统一 的接口,使Catalina 容器与具体的请求协议及IO操作方式完全解耦。
  2. Coyote 将Socket 输 入转换封装为 Request 对象,交由Catalina 容器进行处理,处理请求完成后,Catalina 通 过Coyote 提供的Response 对象将结果写入输出流 。
  3. Coyote 作为独立的模块,只负责具体协议和IO的相关操作,与Servlet 规范实现没有直接关系,因此即便是Request 和 Response 对象也并未实现Servlet规范对应的接口,而是在Catalina中将他们进一步封装为ServletRequest和ServletResponse 。

2.连接器组件

  • EndPoint
  • Processor:Coyote 协议处理接口
  • ProtocolHandler: Coyote 协议接口
  • Adapter: 实现类为CoyoteAdapter

EndPoint:

  1. Coyote 通信端点,即通信监听的接口,是具体Socket接收和发送处理 器,是对传输层的抽象,因此EndPoint用来实现TCP/IP协议的。
  2. Tomcat 并没有EndPoint 接口,而是提供了一个抽象类AbstractEndpoint , 里面定 义了两个内部类:Acceptor和SocketProcessor。Acceptor用于监听Socket连接请求。 SocketProcessor用于处理接收到的Socket请求,它实现Runnable接口,在Run方法里 调用协议处理组件Processor进行处理。为了提高处理能力,SocketProcessor被提交到 线程池来执行。而这个线程池叫作执行器(Executor),我在后面的专栏会详细介绍 Tomcat如何扩展原生的Java线程池。

Processor:

  1. Coyote 协议处理接口 ,如果说EndPoint是用来实现TCP/IP协议的,那么 Processor用来实现HTTP协议,Processor接收来自EndPoint的Socket,读取字节流解 析成Tomcat Request和Response对象,并通过Adapter将其提交到容器处理, Processor是对应用层协议的抽象。

ProtocolHandler:

  1. Coyote 协议接口, 通过Endpoint 和 Processor , 实现针对具体协 议的处理能力。Tomcat 按照协议和I/O 提供了6个实现类 : AjpNioProtocol , AjpAprProtocol, AjpNio2Protocol , Http11NioProtocol ,Http11Nio2Protocol , Http11AprProtocol。我们在配置tomcat/conf/server.xml 时 , 至少要指定具体的 ProtocolHandler , 当然也可以指定协议名称: HTTP/1.1 ,如果安装了APR,那么 将使用Http11AprProtocol , 否则使用 Http11NioProtocol 。

Adapter:

  1. 实现类为CoyoteAdapter,这是 适配器模式的经典运用,连接器调用CoyoteAdapter的Sevice方法,传入的是Tomcat Request对象,CoyoteAdapter负责将Tomcat Request转成ServletRequest,再调用容 器的Service方法。
3.创建连接器对象

Connector.java

    public Connector() {
        this("HTTP/1.1"); //创建出
    }


    public Connector(String protocol) {
        boolean apr = AprStatus.isAprAvailable() &&
            AprStatus.getUseAprConnector();
        ProtocolHandler p = null;
        try {
            p = ProtocolHandler.create(protocol, apr);
        } catch (Exception e) {
            log.error(sm.getString(
                    "coyoteConnector.protocolHandlerInstantiationFailed"), e);
        }
        if (p != null) {
            protocolHandler = p;
            protocolHandlerClassName = protocolHandler.getClass().getName();
        } else {
            protocolHandler = null;
            protocolHandlerClassName = protocol;
        }
        // Default for Connector depends on this system property
        setThrowOnFailure(Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"));
    }


    public Connector(ProtocolHandler protocolHandler) {
        protocolHandlerClassName = protocolHandler.getClass().getName();
        this.protocolHandler = protocolHandler;
        // Default for Connector depends on this system property
        setThrowOnFailure(Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"));
    }

ProtocolHandler.create()

    public static ProtocolHandler create(String protocol, boolean apr)
            throws ClassNotFoundException, InstantiationException, IllegalAccessException,
            IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
        if (protocol == null || "HTTP/1.1".equals(protocol)
                || (!apr && org.apache.coyote.http11.Http11NioProtocol.class.getName().equals(protocol))
                || (apr && org.apache.coyote.http11.Http11AprProtocol.class.getName().equals(protocol))) {
            if (apr) {
                return new org.apache.coyote.http11.Http11AprProtocol();
            } else {
                return new org.apache.coyote.http11.Http11NioProtocol();
            }
        } else if ("AJP/1.3".equals(protocol)
                || (!apr && org.apache.coyote.ajp.AjpNioProtocol.class.getName().equals(protocol))
                || (apr && org.apache.coyote.ajp.AjpAprProtocol.class.getName().equals(protocol))) {
            if (apr) {
                return new org.apache.coyote.ajp.AjpAprProtocol();
            } else {
                return new org.apache.coyote.ajp.AjpNioProtocol();
            }
        } else {
            // Instantiate protocol handler
            Class clazz = Class.forName(protocol);
            return (ProtocolHandler) clazz.getConstructor().newInstance();
        }
    }

该处可能会传 HTTP 或者 AJP ,根据不同的协议创建不同的协议处理器。也就是连接器,我们看到这里的全限定名是 org.apache.coyote.http11.Http11NioProtocol或者 org.apache.coyote.ajp.Ajp11NioProtocol,这两个类都是在 coyote 包下,也就是连接器模块。

后面的连接器的初始化和启动在之前的文章有写
init() 和 startInternal()

4.IO模型与协议

Tomcat 支持的IO模型(自8.5/9.0 版本起,Tomcat 移除了 对 BIO 的支持)

  • NIO: 非阻塞I/O,采用Java NIO类库实现。
  • NIO2: 异步I/O,采用JDK 7最新的NIO2类库实现。
  • APR: 采用Apache可移植运行库实现,是C/C++编写的本地库。如果选择该方 案,需要单独安装APR库。

应用层协议:

  • Http/1.1
  • AJP: 用于和Web服务器集成(如Apache),以实现对静态资源的优化以及 集群部署,当前支持AJP/1.3。
  • Http/2: HTTP 2.0大幅度的提升了Web性能。下一代HTTP协议 , 自8.5以及9.0 版本之后支持。


在 8.0 之前 , Tomcat 默认采用的I/O方式为 BIO , 之后改为 NIO。 无论 NIO、NIO2 还是 APR, 在性能方面均优于以往的BIO。 如果采用APR, 甚至可以达到 Apache HTTP Server 的影响性能。

Tomcat为了实现支持多种I/O模型和应用层协议,一个容器可能对接多个连接器,就好比一个房间有多个门。但是单独的连接器或者容器都不能对外提供服务,需要把它们组装起来才能工作,组装后这个整体叫作Service组件。这里请你注意,Service本身没有做什么重要的事情,只是在连接器和容器外面多包了一层,把它们组装在一起。Tomcat内可能有多个Service,这样的设计也是出于灵活性的考虑。通过在Tomcat中配置多个Service,可以实现通过不同的端口号来访问同一台机器上部署的不同应用。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1028072.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号