“This is the eighth day of my participation in the August More Text Challenge. For more details, see August More Text Challenge

1. Overall architecture design of Tomcat

Tomcat has two core functions: 1, processing Socket connection, responsible for the network byte stream and Request and Response object conversion. 2, load and manage servlets, as well as specific processing Request Request. So Tomcat designs two core components, the Connector and the Container, to do these two things, respectively. The connector is responsible for external communication, and the container is responsible for internal processing.

Tomcat supports the following I/O models:

  • NIO: Non-blocking I/O implemented using the Java NIO class library.
  • NIO2: Asynchronous I/O implemented using the latest NIO2 class library in JDK 7.
  • APR: Implemented using the Apache portable runtime, a native library written in C/C++.

Tomcat supports the following application-layer protocols:

  • HTTP/1.1: This is the access protocol used by most Web applications.
  • AJP: For integration with a Web server such as Apache.
  • HTTP/2: HTTP 2.0 greatly improves Web performance.

To enable Tomcat to support multiple I/O models and application layer protocols, a container can be connected to multiple connectors, just like a room with multiple doors. However, neither individual connectors nor containers can provide services externally. They need to be assembled to work, which is called a Service component. Note here that the Service is just an extra layer of wrapping around the connector and container to put them together. Tomcat may have more than one Service, which is also designed for flexibility. By configuring multiple services in Tomcat, you can use different port numbers to access different applications deployed on the same machine.

Tomcat connector

The connector masks the differences between various protocols and I/O models, and the end result is a standard ServletRequest object for the Servlet container. The workflow for connectors is roughly as follows:

  • Listen for network port for connection request
  • Network connection request accepted
  • Read the byte stream in the request
  • The byte stream is parsed according to the specific application layer protocol (HTTP/APR) to generate a unified Tomcat Request object
  • Convert the Tomcat Request object into a standard ServletRequest and submit it to the Servlet container
  • Call the Servlet container to get the ServletResponse
  • Convert a ServletResponse into a Tomcat Response object
  • Convert Tomcat Response into a network byte stream
  • Writes the response byte stream back to the browser

In the above the working process of the connector can be concluded that the connector has three main functions: network communication, the application layer protocol parsing, Tomcat Request/Response with ServletRequest/ServletResponse conversion between. So the designers of Tomcat designed three components to implement these three functions: the Endpoint, Processor, and Adapter.

The Endpoint provides a byte stream for the Processor to process. After processing, the Processor provides the Tomcat Request object to the Adapter. Adapter converts the Tomcat Request object into a standard ServletRequest and provides it to the Servlet container.

The I/O model and application layer protocols can be combined freely, such as NIO+HTP, NIO2+HTTP, or NIO2+AJP. So Tomcat is designed to have a ProtocolHandler interface that handles I/O and application-layer protocol changes. Various combinations of communication models and protocols have corresponding concrete implementation classes, such as Http11NioProtocol and AjpNioProtocol.

In the figure above, you can see that there are concrete implementation classes for each combination of I/O and application layer protocols in Tomcat. The use in use can be freely combined.

2.1 Relationships between the three components of a connector

The three core components of the connector: Endpoint, Processor, and Adapter are described above. In the class inheritance diagram above, you can see that Endpoint+Processor is put together as a ProtocolHandler component, as follows:

2.2 ProtocolHandler components

From the class inheritance diagram above, you can see that connectors in Tomcat use ProtocolHandler to handle network connection and application layer protocols, mainly including endpoints and processors.

1, the Endpoint

The Endpoint is a communication Endpoint. It is a specific Socket receiving and sending processor and an abstraction of the transport layer. Therefore, the Endpoint is used to implement the TPC/IP protocol.

AbstractEndpoint is an abstract interface to the Endpoint. The implementation classes include NioEndpoint and Nio2Endpoint. It has two important sub-components: Acceptor and SocketProcessor.

Acceptor is used to listen for Socket connection requests. The SocketProcessor processes the received Socket requests. It implements the Runnable interface and calls the protocol processing component Processor in the run method. Tomcat to improve processing power. The SocketProcessor is committed to the thread pool for execution. This thread pool is named Executor in Tomcat.

2, the Processor

The Processor implements THE HTTP protocol. The Processor accepts the Socket from the Endpoint, parses it into Tomcat Request and Response objects, and submits them to the container through the Adapter. You can see it in the figure above. The Processor is an abstraction of the protocol at the application layer. The class diagram is shown below. The Processor is an interface that defines methods such as processing requests. Its abstract implementation class, AbstractProcessor, encapsulates some properties common to the protocol and does not implement methods. The concrete implementation has AJPProcessor, HTTP11Processor, etc., these concrete implementation classes to achieve the specific protocol parsing method and request processing mode.

After receiving the Socket connection, the EndPoint generates a SocketProcessor task and submits it to the thread pool for processing. The SocketProcessor’s Run method calls the Processor component to parse the application-layer protocol. After the Processor parses the Request object, it calls the Service method of the Adapter.

2.3 Adapter

The requested information may vary from client to client, and Tomcat defines its own Request class to “store” the Request information. The ProtocolHandler interface resolves the Request and generates the Tomcat Request class. However, the Request object is not a standard ServletRequest, which means that the container cannot be invoked with Tomcat Request as an argument. The Tomcat designer’s solution was to introduce a CoyoteAdapter. This is a classic use of the adapter pattern. The connector calls the Sevice method of the CoyoteAdapter and passes in the Tomcat Request object. The CoyoteAdapter converts the Tomcat Request into a ServletRequest and invokes the container’s Service method.

Third, summary

Tomcat’s overall architecture consists of two core component connectors and containers. The connector is responsible for external communication, and the container is responsible for internal processing. The ProtocolHandler interface encapsulates the differences between the communication protocol and the I/O model. The ProtocolHandler is divided into the EndPoint module and the Processor module. The EndPoint is responsible for the underlying Socket communication. Proccesor is responsible for application layer protocol resolution. The connector calls the container through the Adapter.