Tomcat 源码学习 之 Http11ConnectionHandler

 

Class Name org.apache.coyote.http11.Http11ConnectionHandler
Inheritance

Handler

Related Classes

Http11Protocol

RequestGroupInfo

Http11Processor

Functionality Maitainance processor list,assign cooresponding processor to input requests.

 

 

Analysis

Http11ConnectionHandler is a static class been defined in Http11Protocal.java file, it's very strange design that it actually inherited from Handler interface which was defined in  JIoEndpoint. Not sure why Tomcat design the connector this way, but there must be a reason.

 

Recalling to blog about JIoEndpoint, Http11ConnectionHandler will be used by cocurrent threads in SocketProcessor.run() method, which means, Http11ConnectionHandler need to be working file in multiple thread. That's why thread safe was considered highest priority when desin this class.

 

Fields

There are five instance fields defined in this class:

 

  • Http11Protocal proto, reference to the protocal instace, this instance was readonly in this class.
  • AtomicLong registerCount, this field count the number of processors been registered in JMX by handler. As you can see, AtomicLong type was used to ensure the atomic access to this value in the multiple threads environment.
  • RequestGroupInfo global, it is currently used only as a JMX artifact, to aggregate the data collected from each RequestProcessor thread.
  • ConcurrentHashMap<SocketWrapper<Socket>, Http11Processor> connections, each socket will be assigned one Http11Processor, we need to make sure this map is thread safe.
  • ConcurrentLinkedQueue<Http11Processor> recycledProcessors, idle processors could be used to assign to new socket. because of the default implimentation of ConcurrentLinkedQueue is unbounded, Http11ConnectionHandler inherited it and implements as bounded.
Methods

The key method of Http11ConnectionHandler is the "process" method:

 

        public SocketState process(SocketWrapper<Socket> socket, SocketStatus status) {
            Http11Processor processor = connections.remove(socket);
            try {
                if (processor == null) {
                    processor = recycledProcessors.poll();
                }
                if (processor == null) {
                    processor = createProcessor();
                }

                if (proto.isSSLEnabled() && (proto.sslImplementation != null)) {
                    processor.setSSLSupport(
                            proto.sslImplementation.getSSLSupport(
                                    socket.getSocket()));
                } else {
                    processor.setSSLSupport(null);
                }
                
                SocketState state = socket.isAsync()?processor.asyncDispatch(status):processor.process(socket);
                if (state == SocketState.LONG) {
                    connections.put(socket, processor);
                    socket.setAsync(true);
                    // longPoll may change socket state (e.g. to trigger a
                    // complete or dispatch)
                    return processor.asyncPostProcess();
                } else {
                    socket.setAsync(false);
                    recycledProcessors.offer(processor);
                }
                return state;
            } catch(java.net.SocketException e) {
                // SocketExceptions are normal
                log.debug(sm.getString(
                        "http11protocol.proto.socketexception.debug"), e);
            } catch (java.io.IOException e) {
                // IOExceptions are normal
                log.debug(sm.getString(
                        "http11protocol.proto.ioexception.debug"), e);
            }
            // Future developers: if you discover any other
            // rare-but-nonfatal exceptions, catch them here, and log as
            // above.
            catch (Throwable e) {
                ExceptionUtils.handleThrowable(e);
                // any other exception or error is odd. Here we log it
                // with "ERROR" level, so it will show up even on
                // less-than-verbose logs.
                log.error(sm.getString("http11protocol.proto.error"), e);
            }
            recycledProcessors.offer(processor);
            return SocketState.CLOSED;
        }

 

The method will first check if an existing processor been assign to current socket, use the existing processor if has, otherwise a new one will be created.

 

Processor will set it's SSL support based on the setting in ProtocalHandler, we will leave this part in future discussion.

 

After that, the socket will be processed by the processor differently according to if the socket is an asynchronized. 

 

  • If it's an asynchronized socket, it will call processor's asyncDispatch method. A LONG status will return if process succesufully, and processor's asyncPostProcess method will be called.
  • If it's not an asynchronized socket, it will call processor's process method.

The processor will be recyled once finished process, and the socket status will be set to CLOSED.

 

你可能感兴趣的:(Web)