JavaWeb学习之——Tomcat篇Connector

概述

        Tomcat最底层是使用Socket来进行连接的,而Connector的作用就是将接受到的请求转换为Request和Response。Request和Response是按照HTTP协议来封装的,封装完成后就交给Container进行处理。Container处理完成后又返回给Connector,由Connector返给客户端

Connector的结构

190331_DuNB_3039671.png

        Connector主要是通过ProtocolHandler来处理请求的。不用的ProtocolHandler代表不同的连接类型。例如Http11Protocal使用普通的socket(同步处理),http11NioProtocal使用的NioSocket来链接。ProtocolHandler里面有3个很重要的组件:

  1. Endpoint:处理最底层的Socket链接(一串字符流)
  2. Processor:用户将Endpoint收到的内容封装成Requst(也就是需要解析HTTP协议)
  3. Adapter将请求适配到合适的Sevlet容器

ProtocolHandler

<!-- 定义一个Connector,在8080端口箭头HTTP的请求 -->
<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" />
   
<!-- 定义一个Connector,在8009端口箭头AJP的请求 -->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

在server.xml中就有Connector的配置。图中配置了监听HTTP请求和AJP请求

ProtocolHandler有一个抽象实现类AbstractProtocal,下面有3个子类,分别是对Ajp,Http,spdy协议的实现

  • Ajp(apache JServ Protocol),Apache的定向包协议,主要用于前端服务器(如Apache)之间的通信,他是长连接。
  • Http:略
  • Spdy: 是google开发的协议,效率比Http搞,但使用不广泛

在Connector中默认是使用org.apache.coyote.http11.Http11NioProtocol。

Endpoint

Endpoint用于处理具体的连接和数据传输,实现是比较复杂的。NioEndpoint集成AnstractEndpoint,AnstractEndpoint也是一个模板类,例如start()方法在AnstractEndpoint中,其中bind()方法由子类去实现

    public final void start() throws Exception {
        if (bindState == BindState.UNBOUND) {
            bind();
            bindState = BindState.BOUND_ON_START;
        }
        startInternal();
    }
    public abstract void bind() throws Exception;

NioEndpoint的bind()方法就是初始化ServerSocketChannel和Selector

    public void bind() throws Exception {

        serverSock = ServerSocketChannel.open();
        socketProperties.setProperties(serverSock.socket());
        InetSocketAddress addr = (getAddress()!=null?new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort()));
        serverSock.socket().bind(addr,getBacklog());
        serverSock.configureBlocking(true); //mimic APR behavior
        serverSock.socket().setSoTimeout(getSocketProperties().getSoTimeout());

        // Initialize thread count defaults for acceptor, poller
        if (acceptorThreadCount == 0) {
            // FIXME: Doesn't seem to work that well with multiple accept threads
            acceptorThreadCount = 1;
        }
        if (pollerThreadCount <= 0) {
            //minimum one poller thread
            pollerThreadCount = 1;
        }
        stopLatch = new CountDownLatch(pollerThreadCount);

        // Initialize SSL if needed
        initialiseSsl();

        selectorPool.open();
    }

启动是在startInternal()方法中,主要做了2个事情,初始化Poller线程和Accept线程,Accept负责接收Socket请求,然后具体的处理方法是在Poller线程中。(Accept和Poller是内部类)

    public void startInternal() throws Exception {

        if (!running) {
            running = true;
            paused = false;

            processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                    socketProperties.getProcessorCache());
            eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                            socketProperties.getEventCache());
            nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                    socketProperties.getBufferPool());

            // Create worker collection
            if ( getExecutor() == null ) {
                createExecutor();
            }

            initializeConnectionLatch();

            // Start poller threads
            pollers = new Poller[getPollerThreadCount()];
            for (int i=0; i<pollers.length; i++) {
                pollers[i] = new Poller();
                Thread pollerThread = new Thread(pollers[i], getName() + "-ClientPoller-"+i);
                pollerThread.setPriority(threadPriority);
                pollerThread.setDaemon(true);
                pollerThread.start();
            }

            startAcceptorThreads();
        }
    }

Processor

主要用于处理应用层协议(如HTTP),分别由3个基本协议对应3个基本的抽象类

Adapter

Adapter只有一个实现类,就是CoyoteAdapter类。

  • 把org.apache.coyote包下的Request和Response封装为org.apache.catalina.connector的Request和Response
  • 从Serivce中的Container获取第一个管道,然后调用管道的invoker方法(管道可以理解为一个过滤链,最后会调用StandardWrapperValue来处理Filter和Servlet)

转载于:https://my.oschina.net/u/3039671/blog/809865

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值