The overall architecture

Core functions:

  • Handle socket connections and convert network byte streams to Request and Response objects.
  • Load and manage servlets and handle Request requests specifically.

Tomcat supports the following IO models: NIO, NIO2, and APR Tomcat supports the following application-layer protocols: HTTP1.1 AJP HTTP2.0

The top layer of Tomcat is server. A server has multiple services, and a service has multiple connectors and a container. The connectors and containers communicate with each other through ServletRequest and ServletResponse.

By combining patterns, template methods, observer patterns, and skeleton abstract classes, Tomcat defines a base class LifeCycleBean that implements the LifeCycle interface, adding common logic, LifeCycle state transitions and maintenance, triggering of life events, and adding and removing listeners. Subclasses are responsible for implementing their own methods such as init, stop, and start.

  • Tomcat has custom listeners
  • @webListener annotation to define your own listener

StandardServer, StandardService, and so on are concrete implementation classes for Server and Service components that inherit from LifecycleBase.

StandardEngine, StandardHost, StandardContext, and StandardWrapper are concrete implementation classes for the corresponding container components, and since they are containers, they inherit the ContainerBase abstract class, ContainerBase implements the Container interface and inherits the LifecycleBase class, which has separate lifecycle management and functionality interfaces.

Connector Connector

Connectors are further refined:

  • Listening network port
  • Accept network requests
  • Read the network byte stream
  • The byte stream is parsed according to the application layer protocol to generate unified Tomcat Request and Tomcat Response objects
  • Convert the Tomcat Request object into a servletRequest
  • Call the servlet container, resulting in a servletResponse
  • Convert the servletResponse into a Tomcat Response
  • Convert Tomcat Response to network byte stream
  • Write the response byte stream back to the browser

In terms of highly cohesive functions:

  • Network communication
  • Application layer protocol parsing
  • Tomcat Request/Response and Servlet Request/Response conversion

Components interact through interfaces, which have the advantage of encapsulating change.

The Endpoint provides the byte stream to the Processor, the Processor provides the Tomcat Request object to the Adapter, and the Adapter provides the Servlet Request to the container.

The Endpoint and Processor are abstractly assembled together to form a ProtocolHandler component.

ProtocolHandler

Endpoint

The abstract implementation class is AbstractEndpoint, and the specific subclass is NioEndpoint and Nio2Endpoint. The two important components are Acceptor and SocketProcessor.

Acceptors listen for Socket connection requests. Socketprocessors process received Socket requests and submit them to the thread pool Executor for processing.

Processor

The socket receives the Endpoint, reads the byte stream, parses it into Tomcat request and response, and submits it to the container for processing through the Adapter. The specific implementation classes of Processor AjpProcessor and Http11Processor implement the specific protocol parsing method and request processing mode.

After receiving the socket connection, the Endpoint generates a socketProcessor for processing by the thread pool. The Run method invokes the Processor to parse application layer protocols. After the Tomcat request is generated, the Service method of the Adapter is invoked.

Adapter

The ProtocolHandler interface is responsible for resolving the Request, generating the Tomcat ReqUST, CoyoteAdapter Service method, converting the Tomcat Request object into a ServletRequest, and invoking the Service method.

Container, the Container

The hierarchy of containers

Parent-child Engine, Host, Context, Wrapper, and Servlet. Context represents a Web application, wrapper represents a servlet, Context has multiple wrappers, and host has multiple contexts.

Host represents a virtual Host, or a site, you can configure multiple virtual Host addresses for Tomcat, and a virtual Host can deploy multiple Web applications; An Engine is used to manage multiple virtual sites. A Service can have at most one Engine.

The container processes the request once through the pipeline-Valve responsibility chain, invoke processing method,

Each container has a Pipeline that fires the first Valve, and the Valve of that container is called to the first Valve of the underlying container through the getBasic method of the Pipeline.

The entire invocation is triggered by the Adapter in the connector, calling the first Valve in the Engine.

// Calling the container
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
Copy the code

The last Valve in the Wrapper container creates a filter chain and calls the doFilter method, which eventually calls the servlet’s service method.

final class StandardWrapperValve
    extends ValveBase {
    
   @Override
      public final void invoke(Request request, Response response)
          throws IOException, ServletException {
          // ...
          
          ApplicationFilterChain filterChain =
                ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);

        // Call the filter chain for this request
        // NOTE: This also calls the servlet's service() method
        Container container = this.container;
        try {
            if((servlet ! =null) && (filterChain ! =null)) {
                // Swallow output if needed
                if (context.getSwallowOutput()) {
                    try {
                        SystemLogHandler.startCapture();
                        if (request.isAsyncDispatching()) {
                            request.getAsyncContextInternal().doInternalDispatch();
                        } else {
                        
                        // dofilterfilterChain.doFilter(request.getRequest(), response.getResponse()); }}finally {
                        String log = SystemLogHandler.stopCapture();
                        if(log ! =null && log.length() > 0) { context.getLogger().info(log); }}}else {
                    if (request.isAsyncDispatching()) {
                        request.getAsyncContextInternal().doInternalDispatch();
                    } else {
                    	// dofilterfilterChain.doFilter (request.getRequest(), response.getResponse()); }}}}catch() {
        // ...}}}Copy the code

ServletContext is a member variable in Tomcat, and ApplicationContext in Spring is the ServletContext property in the Servlet specification.