Tomcat源码分析(四):请求处理

请求处理

架构图

在这里插入图片描述

在这里插入图片描述

Connector的创建

在解析Tomcat的启动流程中,提到过在启动service的过程中,会启动它包含的connector和engine
其中的connector是通过解析server.xml文件创建的,在解析server.xml文件时会添加如下的解析规则

digester.addRule("Server/Service/Connector",
                         new ConnectorCreateRule());

接着看下ConnectorCreateRule的begin方法

public void begin(String namespace, String name, Attributes attributes)
            throws Exception {
    // 获取当前service
    Service svc = (Service)digester.peek();
    Executor ex = null;
    // 判断server.xml文件中的Connector标签是否指定了executor属性,如果指定了这属性,那么Connector中的protocolHandler会使用这个线程池
    if ( attributes.getValue("executor")!=null ) {
        ex = svc.getExecutor(attributes.getValue("executor"));
    }
    // 通过协议名称来创建相应的connector
    Connector con = new Connector(attributes.getValue("protocol"));
    // 指定线程池,将线程池通过setExecutor方法设置到当前连接的protocolHandler
    if (ex != null) {
        setExecutor(con, ex);
    }
    String sslImplementationName = attributes.getValue("sslImplementationName");
    if (sslImplementationName != null) {
        setSSLImplementationName(con, sslImplementationName);
    }
    digester.push(con);
}

首先看下Connector的构造方法

public Connector(String protocol) {
	// 通过协议名称,确定ProtocolHandler的实现类
	// 一般这里传入的是HTTP1.1,因此对应的实现类是org.apache.coyote.http11.Http11NioProtocol
    setProtocol(protocol);
    // Instantiate protocol handler
    ProtocolHandler p = null;
    // 创建ProtocolHandler
    try {
        Class<?> clazz = Class.forName(protocolHandlerClassName);
        p = (ProtocolHandler) clazz.getConstructor().newInstance();
    } catch (Exception e) {
        log.error(sm.getString(
                "coyoteConnector.protocolHandlerInstantiationFailed"), e);
    } finally {
        this.protocolHandler = p;
    }

    if (Globals.STRICT_SERVLET_COMPLIANCE) {
        uriCharset = StandardCharsets.ISO_8859_1;
    } else {
        uriCharset = StandardCharsets.UTF_8;
    }

    // Default for Connector depends on this (deprecated) system property
    if (Boolean.parseBoolean(System.getProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "false"))) {
        encodedSolidusHandling = EncodedSolidusHandling.DECODE;
    }
}

Connector的初始化

protected void initInternal() throws LifecycleException {

    super.initInternal();

    // Initialize adapter
    // 初始化adapter
    adapter = new CoyoteAdapter(this);
    protocolHandler.setAdapter(adapter);

    // Make sure parseBodyMethodsSet has a default
    if (null == parseBodyMethodsSet) {
        setParseBodyMethods(getParseBodyMethods());
    }

    if (protocolHandler.isAprRequired() && !AprLifecycleListener.isInstanceCreated()) {
        throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoAprListener",
                getProtocolHandlerClassName()));
    }
    if (protocolHandler.isAprRequired() && !AprLifecycleListener.isAprAvailable()) {
        throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoAprLibrary",
                getProtocolHandlerClassName()));
    }
    if (AprLifecycleListener.isAprAvailable() && AprLifecycleListener.getUseOpenSSL() &&
            protocolHandler instanceof AbstractHttp11JsseProtocol) {
        AbstractHttp11JsseProtocol<?> jsseProtocolHandler =
                (AbstractHttp11JsseProtocol<?>) protocolHandler;
        if (jsseProtocolHandler.isSSLEnabled() &&
                jsseProtocolHandler.getSslImplementationName() == null) {
            // OpenSSL is compatible with the JSSE configuration, so use it if APR is available
            jsseProtocolHandler.setSslImplementationName(OpenSSLImplementation.class.getName());
        }
    }

    try {
        protocolHandler.init();
    } catch (Exception e) {
        throw new LifecycleException(
                sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e);
    }
}

这里主要就是创建了一个Adapter,并且将ProtocolHandler和Adapter关联起来,然后启动了ProtocolHandler
所以说Connector主要包含两个组件:ProtocolHandler和Adapter
接着看下AbstractHttp11Protocol的init,主要是调用了父类的init方法

public void init() throws Exception {
    // Upgrade protocols have to be configured first since the endpoint
    // init (triggered via super.init() below) uses this list to configure
    // the list of ALPN protocols to advertise
    for (UpgradeProtocol upgradeProtocol : upgradeProtocols) {
        configureUpgradeProtocol(upgradeProtocol);
    }

    super.init();

    // Set the Http11Protocol (i.e. this) for any upgrade protocols once
    // this has completed initialisation as the upgrade protocols may expect this
    // to be initialised when the call is made
    for (UpgradeProtocol upgradeProtocol : upgradeProtocols) {
        if (upgradeProtocol instanceof Http2Protocol) {
            ((Http2Protocol) upgradeProtocol).setHttp11Protocol(this);
        }
    }
}

接着看AbstractProtocol的init

public void init() throws Exception {
   if (getLog().isInfoEnabled()) {
       getLog().info(sm.getString("abstractProtocolHandler.init", getName()));
   }

   if (oname == null) {
       // Component not pre-registered so register it
       oname = createObjectName();
       if (oname != null) {
           Registry.getRegistry(null, null).registerComponent(this, oname, null);
       }
   }

   if (this.domain != null) {
       ObjectName rgOname = new ObjectName(domain + ":type=GlobalRequestProcessor,name=" + getName());
       this.rgOname = rgOname;
       Registry.getRegistry(null, null).registerComponent(
               getHandler().getGlobal(), rgOname, null);
   }
	// 拼接endpoint的名称,默认是http-nio-8080
   String endpointName = getName();
   endpoint.setName(endpointName.substring(1, endpointName.length()-1));
   endpoint.setDomain(domain);
   endpoint.init();
}

主要是设置Endpoint的一些属性,比如名称, 然后初始化,最终会调用AbstractEndpoint的init方法

public void init() throws Exception {
    if (bindOnInit) {
        bind();
        bindState = BindState.BOUND_ON_INIT;
    }
    if (this.domain != null) {
        // Register endpoint (as ThreadPool - historical name)
        oname = new ObjectName(domain + ":type=ThreadPool,name=\"" + getName() + "\"");
        Registry.getRegistry(null, null).registerComponent(this, oname, null);

        ObjectName socketPropertiesOname = new ObjectName(domain +
                ":type=SocketProperties,name=\"" + getName() + "\"");
        socketProperties.setObjectName(socketPropertiesOname);
        Registry.getRegistry(null, null).registerComponent(socketProperties, socketPropertiesOname, null);

        for (SSLHostConfig sslHostConfig : findSslHostConfigs()) {
            registerJmx(sslHostConfig);
        }
    }
}

这里最重要的部分就是调用bind方法,这里看下NioEndpoint的bind方法

public void bind() throws Exception {

	// 使用java nio监听本地的8080端口
   if (!getUseInheritedChannel()) {
       serverSock = ServerSocketChannel.open();
       socketProperties.setProperties(serverSock.socket());
       InetSocketAddress addr = (getAddress()!=null?new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort()));
       serverSock.socket().bind(addr,getAcceptCount());
   } else {
       // Retrieve the channel provided by the OS
       Channel ic = System.inheritedChannel();
       if (ic instanceof ServerSocketChannel) {
           serverSock = (ServerSocketChannel) ic;
       }
       if (serverSock == null) {
           throw new IllegalArgumentException(sm.getString("endpoint.init.bind.inherited"));
       }
   }
   serverSock.configureBlocking(true); //mimic APR behavior

   // 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;
   }
   setStopLatch(new CountDownLatch(pollerThreadCount));

   // Initialize SSL if needed
   initialiseSsl();

	// 打开selector池
   selectorPool.open();
}

下面看下打开selector池都做了什么

public void open() throws IOException {
    enabled = true;
    getSharedSelector();
    if (SHARED) {
        blockingSelector = new NioBlockingSelector();
        blockingSelector.open(getSharedSelector());
    }

}
protected Selector getSharedSelector() throws IOException {
    if (SHARED && SHARED_SELECTOR == null) {
        synchronized ( NioSelectorPool.class ) {
            if ( SHARED_SELECTOR == null )  {
                SHARED_SELECTOR = Selector.open();
                log.info("Using a shared selector for servlet write/read");
            }
        }
    }
    return  SHARED_SELECTOR;
}

默认情况下SHARED为true
上面的代码会创建一个共享的selector对象
接着看BlockingSelector的open

public void open(Selector selector) {
   sharedSelector = selector;
   poller = new BlockPoller();
   poller.selector = sharedSelector;
   poller.setDaemon(true);
   poller.setName("NioBlockingSelector.BlockPoller-"+(threadCounter.getAndIncrement()));
   poller.start();
}

将之前生成的共享selector传给BlockPoller,BlockPoller继承了Thread,然后启动这个Thread

Connector启动

下面看下startInternal方法

protected void startInternal() throws LifecycleException {

    // Validate settings before starting
    if (getPort() < 0) {
        throw new LifecycleException(sm.getString(
                "coyoteConnector.invalidPort", Integer.valueOf(getPort())));
    }

    setState(LifecycleState.STARTING);

    try {
        protocolHandler.start();
    } catch (Exception e) {
        throw new LifecycleException(
                sm.getString("coyoteConnector.protocolHandlerStartFailed"), e);
    }
} 

主要就是启动了ProtocolHandler

ProtocolHandler启动

接着看Http11NioProtocol的start方法,首先会调用父类AbstractProtocol的start

public void start() throws Exception {
    if (getLog().isInfoEnabled()) {
        getLog().info(sm.getString("abstractProtocolHandler.start", getName()));
    }

    endpoint.start();

    // Start timeout thread
    asyncTimeout = new AsyncTimeout();
    Thread timeoutThread = new Thread(asyncTimeout, getNameInternal() + "-AsyncTimeout");
    int priority = endpoint.getThreadPriority();
    if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
        priority = Thread.NORM_PRIORITY;
    }
    timeoutThread.setPriority(priority);
    timeoutThread.setDaemon(true);
    timeoutThread.start();
}

主要就是启动Endpoint

Endpoint启动

首先判断是否已经监听了本地的端口,如果没有监听,那么会进行监听,这里因为之前在初始化的时候已经监听过了,所以这里不会执行监听逻辑

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

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

		// 缓存处理器
        processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                socketProperties.getProcessorCache());
        // 缓存PollerStack
        eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                        socketProperties.getEventCache());
        // 缓存NioChannel,每个Channle带有buffer
        nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                socketProperties.getBufferPool());

        // Create worker collection
        // 创建worker线程池
        if (getExecutor() == null) {
            createExecutor();
        }
		
		// 初始化一个用来管理连接数的latch
        initializeConnectionLatch();

        // Start poller threads
        // 创建并且启动Poller线程

        pollers = new Poller[getPollerThreadCount()];
        for (int i=0; i<pollers.length; i++) {
        	// 创建的过程中会新创建一个Selector,并且绑定到当前的poller上
            pollers[i] = new Poller();
            Thread pollerThread = new Thread(pollers[i], getName() + "-ClientPoller-"+i);
            pollerThread.setPriority(threadPriority);
            pollerThread.setDaemon(true);
            pollerThread.start();
        }

		// 启动Acceptor
        startAcceptorThreads();
    }
}
创建worker线程池

这里主要做的就是
(1)创建了一个TaskQueue,类型是LinkedBlockingQueue,可以看出是一个用来存储需要运行的任务的队列
(2)创建了一个线程池,并且使用刚才创建的TaskQueue作为任务队列

public void createExecutor() {
    internalExecutor = true;
    TaskQueue taskqueue = new TaskQueue();
    TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority());
    executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);
    taskqueue.setParent( (ThreadPoolExecutor) executor);
}
启动Acceptor
protected final void startAcceptorThreads() {
	// 默认值为1
    int count = getAcceptorThreadCount();
    acceptors = new Acceptor[count];

    for (int i = 0; i < count; i++) {
        acceptors[i] = createAcceptor();
        String threadName = getName() + "-Acceptor-" + i;
        acceptors[i].setThreadName(threadName);
        Thread t = new Thread(acceptors[i], threadName);
        t.setPriority(getAcceptorThreadPriority());
        t.setDaemon(getDaemon());
        t.start();
    }
}
Acceptor接收连接

接着看Acceptor中执行了什么操作

public void run() {

   int errorDelay = 0;

   // Loop until we receive a shutdown command
   while (running) {

       // Loop if endpoint is paused
       while (paused && running) {
           state = AcceptorState.PAUSED;
           try {
               Thread.sleep(50);
           } catch (InterruptedException e) {
               // Ignore
           }
       }

       if (!running) {
           break;
       }
       state = AcceptorState.RUNNING;

       try {
           //if we have reached max connections, wait
           // 在启动Endpoint的时候,创建了一个用来管理连接数的latch,这里使用的就是之前创建的latch
           // 如果当前的连接数已经超过了最大连接数,那么会阻塞线程
           // 此处增加有效的连接数
           countUpOrAwaitConnection();

           SocketChannel socket = null;
           try {
               // Accept the next incoming connection from the server
               // socket
               // 接收客户端的连接
               socket = serverSock.accept();
           } catch (IOException ioe) {
               // We didn't get a socket
               countDownConnection();
               if (running) {
                   // Introduce delay if necessary
                   errorDelay = handleExceptionWithDelay(errorDelay);
                   // re-throw
                   throw ioe;
               } else {
                   break;
               }
           }
           // Successful accept, reset the error delay
           errorDelay = 0;

           // Configure the socket
           if (running && !paused) {
               // setSocketOptions() will hand the socket off to
               // an appropriate processor if successful
               // 将连接发送给适合的处理器
               if (!setSocketOptions(socket)) {
                   closeSocket(socket);
               }
           } else {
               closeSocket(socket);
           }
       } catch (Throwable t) {
           ExceptionUtils.handleThrowable(t);
           log.error(sm.getString("endpoint.accept.fail"), t);
       }
   }
   state = AcceptorState.ENDED;
}
protected boolean setSocketOptions(SocketChannel socket) {
    // Process the connection
    try {
        //disable blocking, APR style, we are gonna be polling it
        socket.configureBlocking(false);
        Socket sock = socket.socket();
        socketProperties.setProperties(sock);

        NioChannel channel = nioChannels.pop();
        if (channel == null) {
            SocketBufferHandler bufhandler = new SocketBufferHandler(
                    socketProperties.getAppReadBufSize(),
                    socketProperties.getAppWriteBufSize(),
                    socketProperties.getDirectBuffer());
            if (isSSLEnabled()) {
                channel = new SecureNioChannel(socket, bufhandler, selectorPool, this);
            } else {
                channel = new NioChannel(socket, bufhandler);
            }
        } else {
            channel.setIOChannel(socket);
            channel.reset();
        }
        // 将当前的连接使用round-robin注册到一个poller上
        getPoller0().register(channel);
    } catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        try {
            log.error("",t);
        } catch (Throwable tt) {
            ExceptionUtils.handleThrowable(tt);
        }
        // Tell to close the socket
        return false;
    }
    return true;
}
public void register(final NioChannel socket) {
   socket.setPoller(this);
   NioSocketWrapper ka = new NioSocketWrapper(socket, NioEndpoint.this);
   socket.setSocketWrapper(ka);
   ka.setPoller(this);
   ka.setReadTimeout(getSocketProperties().getSoTimeout());
   ka.setWriteTimeout(getSocketProperties().getSoTimeout());
   ka.setKeepAliveLeft(NioEndpoint.this.getMaxKeepAliveRequests());
   ka.setReadTimeout(getConnectionTimeout());
   ka.setWriteTimeout(getConnectionTimeout());
   // 复用PollerEvent对象
   PollerEvent r = eventCache.pop();
   ka.interestOps(SelectionKey.OP_READ);//this is what OP_REGISTER turns into.
   if ( r==null) r = new PollerEvent(socket,ka,OP_REGISTER);
   else r.reset(socket,ka,OP_REGISTER);
   addEvent(r);
}

主要就是将客户端的连接对象封装成了一个PollerEvent,然后将这个event加入到了一个名为events的队列中

Poller消费放入队列中的事件

因为Poller实现了Runnable接口,所以我们看下他的run方法

public void run() {
    // Loop until destroy() is called
    while (true) {

        boolean hasEvents = false;

        try {
            if (!close) {
            	// 从event队列中获取所有PollerEvent,然后调用其run方法,执行完毕后,调用reset来重置PollerEvent,并且重新添加会缓存中来进行复用
                hasEvents = events();
                // 获取当前触发事件的通道个数
                if (wakeupCounter.getAndSet(-1) > 0) {
                    // If we are here, means we have other stuff to do
                    // Do a non blocking select
                    keyCount = selector.selectNow();
                } else {
                    keyCount = selector.select(selectorTimeout);
                }
                wakeupCounter.set(0);
            }
            if (close) {
                events();
                timeout(0, false);
                try {
                    selector.close();
                } catch (IOException ioe) {
                    log.error(sm.getString("endpoint.nio.selectorCloseFail"), ioe);
                }
                break;
            }
        } catch (Throwable x) {
            ExceptionUtils.handleThrowable(x);
            log.error("",x);
            continue;
        }
        // Either we timed out or we woke up, process events first
        if (keyCount == 0) {
            hasEvents = (hasEvents | events());
        }

		// 遍历当前已经触发的事件
        Iterator<SelectionKey> iterator =
            keyCount > 0 ? selector.selectedKeys().iterator() : null;
        // Walk through the collection of ready keys and dispatch
        // any active event.
        while (iterator != null && iterator.hasNext()) {
            SelectionKey sk = iterator.next();
            iterator.remove();
            NioSocketWrapper socketWrapper = (NioSocketWrapper) sk.attachment();
            // Attachment may be null if another thread has called
            // cancelledKey()
            if (socketWrapper != null) {
                processKey(sk, socketWrapper);
            }
        }

        // Process timeouts
        timeout(keyCount,hasEvents);
    }

    getStopLatch().countDown();
}

接着看下PollerEvent的run方法

public void run() {
	// 通过Acceptor接收到的连接生成的PollerEvent的interestOps是OP_REGISTER
	// 因此会走第一个分支
    if (interestOps == OP_REGISTER) {
    	// 将当前socket的channle注册到poller中的selector中,并且设置等待事件为读事件
        try {
            socket.getIOChannel().register(
                    socket.getPoller().getSelector(), SelectionKey.OP_READ, socketWrapper);
        } catch (Exception x) {
            log.error(sm.getString("endpoint.nio.registerFail"), x);
        }
    } else {
        final SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
        try {
            if (key == null) {
                // The key was cancelled (e.g. due to socket closure)
                // and removed from the selector while it was being
                // processed. Count down the connections at this point
                // since it won't have been counted down when the socket
                // closed.
                socket.socketWrapper.getEndpoint().countDownConnection();
                ((NioSocketWrapper) socket.socketWrapper).closed = true;
            } else {
                final NioSocketWrapper socketWrapper = (NioSocketWrapper) key.attachment();
                if (socketWrapper != null) {
                    //we are registering the key to start with, reset the fairness counter.
                    int ops = key.interestOps() | interestOps;
                    socketWrapper.interestOps(ops);
                    key.interestOps(ops);
                } else {
                    socket.getPoller().cancelledKey(key);
                }
            }
        } catch (CancelledKeyException ckx) {
            try {
                socket.getPoller().cancelledKey(key);
            } catch (Exception ignore) {}
        }
    }
}

接着看下processKey方法

protected void processKey(SelectionKey sk, NioSocketWrapper attachment) {
   try {
       if (close) {
           cancelledKey(sk);
       } else if ( sk.isValid() && attachment != null ) {
           if (sk.isReadable() || sk.isWritable() ) {
               if ( attachment.getSendfileData() != null ) {
                   processSendfile(sk,attachment, false);
               } else {
                   unreg(sk, attachment, sk.readyOps());
                   boolean closeSocket = false;
                   // Read goes before write
                   // 处理读
                   if (sk.isReadable()) {
                       if (!processSocket(attachment, SocketEvent.OPEN_READ, true)) {
                           closeSocket = true;
                       }
                   }
                   // 处理写
                   if (!closeSocket && sk.isWritable()) {
                       if (!processSocket(attachment, SocketEvent.OPEN_WRITE, true)) {
                           closeSocket = true;
                       }
                   }
                   if (closeSocket) {
                       cancelledKey(sk);
                   }
               }
           }
       } else {
           // Invalid key
           cancelledKey(sk);
       }
   } catch (CancelledKeyException ckx) {
       cancelledKey(sk);
   } catch (Throwable t) {
       ExceptionUtils.handleThrowable(t);
       log.error("",t);
   }
}
public boolean processSocket(SocketWrapperBase<S> socketWrapper,
            SocketEvent event, boolean dispatch) {
   try {
       if (socketWrapper == null) {
           return false;
       }
       // 从SocketProcessor中获取一个实例
       SocketProcessorBase<S> sc = processorCache.pop();
       if (sc == null) {
           sc = createSocketProcessor(socketWrapper, event);
       } else {
           sc.reset(socketWrapper, event);
       }
       // 获取之前启动Acceptor时创建的worker 线程池
       Executor executor = getExecutor();
       // 判断是否提交到线程池中运行,或者是在当前线程执行
       if (dispatch && executor != null) {
           executor.execute(sc);
       } else {
           sc.run();
       }
   } catch (RejectedExecutionException ree) {
       getLog().warn(sm.getString("endpoint.executor.fail", socketWrapper) , ree);
       return false;
   } catch (Throwable t) {
       ExceptionUtils.handleThrowable(t);
       // This means we got an OOM or similar creating a thread, or that
       // the pool and its queue are full
       getLog().error(sm.getString("endpoint.process.fail"), t);
       return false;
   }
   return true;
}
Processor处理连接

SocketProcessorBase的run方法会执行doRun

public final void run() {
    synchronized (socketWrapper) {
        // It is possible that processing may be triggered for read and
        // write at the same time. The sync above makes sure that processing
        // does not occur in parallel. The test below ensures that if the
        // first event to be processed results in the socket being closed,
        // the subsequent events are not processed.
        if (socketWrapper.isClosed()) {
            return;
        }
        doRun();
    }
}

接着看NioEndpoint中的内部实现类SocketProcessor中的doRun

protected void doRun() {
   NioChannel socket = socketWrapper.getSocket();
   SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());

   try {
       int handshake = -1;

       try {
           if (key != null) {
           		// 因为Handshake是https中的内容,niochannel不处理,所以这里会直接返回true
               if (socket.isHandshakeComplete()) {
                   // No TLS handshaking required. Let the handler
                   // process this socket / event combination.
                   handshake = 0;
               } else if (event == SocketEvent.STOP || event == SocketEvent.DISCONNECT ||
                       event == SocketEvent.ERROR) {
                   // Unable to complete the TLS handshake. Treat it as
                   // if the handshake failed.
                   handshake = -1;
               } else {
                   handshake = socket.handshake(key.isReadable(), key.isWritable());
                   // The handshake process reads/writes from/to the
                   // socket. status may therefore be OPEN_WRITE once
                   // the handshake completes. However, the handshake
                   // happens when the socket is opened so the status
                   // must always be OPEN_READ after it completes. It
                   // is OK to always set this as it is only used if
                   // the handshake completes.
                   event = SocketEvent.OPEN_READ;
               }
           }
       } catch (IOException x) {
           handshake = -1;
           if (log.isDebugEnabled()) log.debug("Error during SSL handshake",x);
       } catch (CancelledKeyException ckx) {
           handshake = -1;
       }
       if (handshake == 0) {
           SocketState state = SocketState.OPEN;
           // Process the request from this socket
           // 如果是读事件,那么此时的event是OPEN_READ
           // 如果是写事件,那么此时的event是OPEN_WRITE
           if (event == null) {
               state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ);
           } else {
           		// 交给handler继续处理
               state = getHandler().process(socketWrapper, event);
           }
           if (state == SocketState.CLOSED) {
               close(socket, key);
           }
       } else if (handshake == -1 ) {
           getHandler().process(socketWrapper, SocketEvent.CONNECT_FAIL);
           close(socket, key);
       } else if (handshake == SelectionKey.OP_READ){
           socketWrapper.registerReadInterest();
       } else if (handshake == SelectionKey.OP_WRITE){
           socketWrapper.registerWriteInterest();
       }
   } catch (CancelledKeyException cx) {
       socket.getPoller().cancelledKey(key);
   } catch (VirtualMachineError vme) {
       ExceptionUtils.handleThrowable(vme);
   } catch (Throwable t) {
       log.error("", t);
       socket.getPoller().cancelledKey(key);
   } finally {
       socketWrapper = null;
       event = null;
       //return to cache
       if (running && !paused) {
           processorCache.push(this);
       }
   }
}

接下来看AbstractProtocol的process方法
代码比较长,看几个重要的部分

S socket = wrapper.getSocket();
Processor processor = connections.get(socket);

其中connections是一个socket映射到Processor的map

private final Map<S,Processor> connections = new ConcurrentHashMap<>();

当连接第一次创建的时候,这里获取到的processor是null
接下来有三个当processor是null的执行分支
第一个if是处理https相关的

if (processor == null) {
  String negotiatedProtocol = wrapper.getNegotiatedProtocol();
  // OpenSSL typically returns null whereas JSSE typically
  // returns "" when no protocol is negotiated
  if (negotiatedProtocol != null && negotiatedProtocol.length() > 0) {
      UpgradeProtocol upgradeProtocol = getProtocol().getNegotiatedProtocol(negotiatedProtocol);
      if (upgradeProtocol != null) {
          processor = upgradeProtocol.getProcessor(wrapper, getProtocol().getAdapter());
          if (getLog().isDebugEnabled()) {
              getLog().debug(sm.getString("abstractConnectionHandler.processorCreate", processor));
          }
      } else if (negotiatedProtocol.equals("http/1.1")) {
          // Explicitly negotiated the default protocol.
          // Obtain a processor below.
      } else {
          // TODO:
          // OpenSSL 1.0.2's ALPN callback doesn't support
          // failing the handshake with an error if no
          // protocol can be negotiated. Therefore, we need to
          // fail the connection here. Once this is fixed,
          // replace the code below with the commented out
          // block.
          if (getLog().isDebugEnabled()) {
              getLog().debug(sm.getString("abstractConnectionHandler.negotiatedProcessor.fail",
                      negotiatedProtocol));
          }
          return SocketState.CLOSED;
          /*
           * To replace the code above once OpenSSL 1.1.0 is
           * used.
          // Failed to create processor. This is a bug.
          throw new IllegalStateException(sm.getString(
                  "abstractConnectionHandler.negotiatedProcessor.fail",
                  negotiatedProtocol));
          */
      }
  }
}

第二个if是从recycledProcessors缓存中获取一个

if (processor == null) {
    processor = recycledProcessors.pop();
    if (getLog().isDebugEnabled()) {
        getLog().debug(sm.getString("abstractConnectionHandler.processorPop", processor));
    }
}

第三个if是重新创建一个processor,这里getProtocol返回的是Http11NioProtocol

if (processor == null) {
    processor = getProtocol().createProcessor();
    register(processor);
    if (getLog().isDebugEnabled()) {
        getLog().debug(sm.getString("abstractConnectionHandler.processorCreate", processor));
    }
}

然后创建一个Http11Processor,这里使用的Adapter是CoyoteAapter

@Override
protected Processor createProcessor() {
    Http11Processor processor = new Http11Processor(this, getEndpoint());
    processor.setAdapter(getAdapter());
    processor.setMaxKeepAliveRequests(getMaxKeepAliveRequests());
    processor.setConnectionUploadTimeout(getConnectionUploadTimeout());
    processor.setDisableUploadTimeout(getDisableUploadTimeout());
    processor.setRestrictedUserAgents(getRestrictedUserAgents());
    processor.setMaxSavePostSize(getMaxSavePostSize());
    return processor;
}

然后将这个socket和processor放到connections这个map中

connections.put(socket, processor);

然后会执行一个循环,主要是调用processor的process来处理连接

do {
	// 省略
    state = processor.process(wrapper, status);

} while ( state == SocketState.UPGRADING);

这里主要看下实现类Http11Processor
首先看下其构造函数
主要是创建了http解析器,输入缓冲,请求对象,输出缓冲,响应对象

public Http11Processor(AbstractHttp11Protocol<?> protocol, AbstractEndpoint<?> endpoint) {
 super(endpoint);
  this.protocol = protocol;

  httpParser = new HttpParser(protocol.getRelaxedPathChars(),
          protocol.getRelaxedQueryChars());

  inputBuffer = new Http11InputBuffer(request, protocol.getMaxHttpHeaderSize(),
          protocol.getRejectIllegalHeader(), httpParser);
  request.setInputBuffer(inputBuffer);

  outputBuffer = new Http11OutputBuffer(response, protocol.getMaxHttpHeaderSize(),
          protocol.getSendReasonPhrase());
  response.setOutputBuffer(outputBuffer);

  // Create and add the identity filters.
  inputBuffer.addFilter(new IdentityInputFilter(protocol.getMaxSwallowSize()));
  outputBuffer.addFilter(new IdentityOutputFilter());

  // Create and add the chunked filters.
  inputBuffer.addFilter(new ChunkedInputFilter(protocol.getMaxTrailerSize(),
          protocol.getAllowedTrailerHeadersInternal(), protocol.getMaxExtensionSize(),
          protocol.getMaxSwallowSize()));
  outputBuffer.addFilter(new ChunkedOutputFilter());

  // Create and add the void filters.
  inputBuffer.addFilter(new VoidInputFilter());
  outputBuffer.addFilter(new VoidOutputFilter());

  // Create and add buffered input filter
  inputBuffer.addFilter(new BufferedInputFilter());

  // Create and add the gzip filters.
  //inputBuffer.addFilter(new GzipInputFilter());
  outputBuffer.addFilter(new GzipOutputFilter());

  pluggableFilterIndex = inputBuffer.getFilters().length;
}

接着看下process方法,主要是根据入参SocketEvent值的不同,执行不同的逻辑,这里主要看下当入参是SocketEvent.OPEN_READ的执行逻辑

else if (status == SocketEvent.OPEN_READ) {
    state = service(socketWrapper);
} 

主要是调用servier方法来处理
首先会通过调用setSocketWrapper来进行一些初始化,主要是初始化inputBufffer和outputBuffer

protected final void setSocketWrapper(SocketWrapperBase<?> socketWrapper) {
    super.setSocketWrapper(socketWrapper);
    inputBuffer.init(socketWrapper);
    outputBuffer.init(socketWrapper);
}

然后调用inputBuffer的parseeRequestLine来处理请求行

if (!inputBuffer.parseRequestLine(keptAlive)) {
    if (inputBuffer.getParsingRequestLinePhase() == -1) {
        return SocketState.UPGRADING;
    } else if (handleIncompleteRequestLineRead()) {
        break;
    }
}

以及调用parseHeaders来处理请求头

if (!http09 && !inputBuffer.parseHeaders()) {
    // We've read part of the request, don't recycle it
    // instead associate it with the socket
    openSocket = true;
    readComplete = false;
    break;
}

然后将请求交给Adapter来进行处理

getAdapter().service(request, response);

在service中,首先将coyote中的request和response转换成继承了HttpServletRequest的Request和Response

Request request = (Request) req.getNote(ADAPTER_NOTES);
Response response = (Response) res.getNote(ADAPTER_NOTES);

if (request == null) {
    // Create objects
    request = connector.createRequest();
    request.setCoyoteRequest(req);
    response = connector.createResponse();
    response.setCoyoteResponse(res);

    // Link objects
    request.setResponse(response);
    response.setRequest(request);

    // Set as notes
    req.setNote(ADAPTER_NOTES, request);
    res.setNote(ADAPTER_NOTES, response);

    // Set query string encoding
    req.getParameters().setQueryStringCharset(connector.getURICharset());
}

然后会调用当前连接所属的Service中的container,来将请求传递到container

connector.getService().getContainer().getPipeline().getFirst().invoke(
                        request, response);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值