The overall architecture

An overview of the

We know that if you want to design a system, you need to understand the requirements first. Tomcat implements two core functions:

  1. Handles Socket connections and is responsible for converting network byte streams to Request and Response objects.
  2. Load and manage servlets, as well as specifically handle Request requests. 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.

As you can see from the diagram, the top layer is Server, which in this case means a Tomcat instance. A Server has one or more services, and a Service has multiple connectors and a container. Connectors communicate with containers through standard ServletRequest and ServletResponse.

Connector design

What is a connector

The connector masks the differences between protocols and I/O models to the Servlet container, which is a standard ServletRequest object, whether HTTP or AJP.

Functional refinement of connectors

Listen for network ports. Network connection request accepted. Read the network request byte stream. The byte stream is resolved according to the specific application layer protocol (HTTP/AJP) to generate a unified Tomcat Request object. Convert the Tomcat Request object to a standard ServletRequest. Call the Servlet container to get the ServletResponse. Convert ServletResponse into a Tomcat Response object. Convert Tomcat Response into a network byte stream. Writes the response byte stream back to the browser.

A submodule of the connector

By analyzing the detailed feature list of the connector, we found that the connector needs to perform three highly cohesive functions:

  • Network communication.
  • Application layer protocol resolution.
  • Tomcat Request/Response with ServletRequest/ServletResponse transformation. These three functions correspond to components that perform their functions:
  • Endpoint: a communication endpoint, an abstraction of the transport layer, which can have implementations of different I/O models such as non-blocking I/O, asynchronous I/O, or APR
  • Processor: The Processor implements the HTTP protocol. The Processor receives the Socket from the Endpoint, reads the byte stream, parses it into Tomcat Request and Response objects, and submits them to the container for processing through the Adapter. Processor is an abstraction of application-layer protocols. This layer can have Http protocol variations, such as Http, HTTPS, AJP
  • adapter

ProtocolHandler components

The ProtocolHandler component encapsulates the EndPoint and Processor components. Here is a combination of the two dimensions

Connector assembly diagram

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 parsing the Request object, the Processor invokes the Service method of the Adapter.

Adapter component

The Adapter component completes the transformation of Tomcat Request ->Servlet Request. The CoyoteAdapter is responsible for transforming the Tomcat Request into a ServletRequest and then calling the service method of the container.

Why one more layer of Adapter?

Problem: It is not better to convert the processor directly to the container’s Servletrequest and Servletresponse. Why do you need to convert Tomcat’s request and response first, and then use adapter to do one layer conversion?

Answer: If the connector creates ServletRequest and ServletResponse objects directly, then it is coupled to the Servlet protocol. The designer thinks that the connector should be as independent as possible and that it does not have to work with the Servlet container. In addition, the performance cost of object conversion is relatively low. Tomcat adopts a deferred resolution strategy for the HTTP request body. That is, when the TomcatRequest object is converted into a ServletRequest, the contents of the request body are not read until the container processes the request.

Why do tomcat and Nginx performance differences occur?
  1. Nginx/ APACHE generally do reverse proxy and handle static HTML resources, do relatively simple things, KPI is to be fast, so use C language implementation, directly call the operating system API, take full advantage of the advanced features of the operating system.

  2. Tomcat is used to process dynamic requests and needs to run Java applications, so it is implemented in Java, so “fast” is not its main KPI. Java calls to the operating system API are made through JNI, with an implicit performance cost. In addition, Tomcat uses the Apache APR local library for I/O communication, and its performance is close to that of Apache and Nginx.

Can the same Tomcat be set to multiple port numbers to launch multiple applications?

Yes, configure multiple services in server.xml, or multiple Connectors in the same service

Multilayer container design

The container hierarchy

Omcat designs four containers, which are Engine, Host, Context and Wrapper.

A Tomcat instance contains a service. A service contains an Engine and multiple connectors. An Engine contains multiple hosts. A Host package contains multiple contexts and a Context contains multiple wrappers and a Wrapper contains a servlet

Request the process of locating the Servlet

  • This is done by the Mapper component, which stores the mapping relationship between the container component and the access path and locates the container based on the requested URL

    • The port number identifies the Service and Engine
    • Domain name identifies Host
    • URL Path Identifies the Context Web application
    • URL path to locate Wrapper (Servlet)
  • At each level of localization, some processing is done on the request

    • Pipeline-valve container calls (chain of responsibility pattern)
    • Valve represents a processing point (such as permission authentication, logging, etc.) that processes requests; Valve is connected by a linked list and maintained by pipeline
    • Valve calls the next Valve with getNext().invoke(), and the last valve (Basic) calls the first Valve of the pipeline of the next layer container
    • Adapter calls the first Valve of the Engine Pipeline
    • Finally, Valve creates a Filter chain that eventually calls the Servlet’s service method

  • Comparison between Valve and Filter
    • Valve is a private mechanism of Tomcat, and Filter is a public standard for the Servlet API
    • Valve works at the container level, blocking all applications; Servlet Filters work at the application level and can only intercept requests from one application
What is the difference between the Context component in Tomcat and the ServletContext interface in the Servlet specification? How does it relate to the ApplicationContext in Spring?
  • In Servlet specification, ServletContext represents the Context environment of Web application, and the concept of Web application corresponding to Tomcat is Context, so from the design, ServletContext will naturally become a member variable of the Context implementation of Tomcat
  • Tomcat internal implementation also is such, ServletContext corresponding tomcat implementation is org. Apache. Catalina. Core. ApplicationContext, The Context corresponding tomcat container implementation is org. Apache. Catalina. Core. StandardContext. ApplicationContext is a member variable of StandardContext.
  • Spring’s ApplicationContext was introduced earlier. During tomcat startup, a ContextLoaderListener will listen to the container initialization event. Its contextInitialized method, Spring initializes the global Spring root container ApplicationContext, which Spring stores in the ServletContext after initialization. In summary, In the Servlet specification, ServletContext is a member variable of Tomcat’s Context implementation, and Spring’s ApplicationContext is a property of ServletContext in the Servlet specification.
Basic Valve was a little confused. For example, if there are multiple host containers in the engine container, how does basic Valve know which host value to point to?

When Mapper maps a Request, it stores a Host, Context, and other objects in the Request object. The selected container is used to process the specific Request. Valve in Engine gets the Host container from the Request object.

In the production environment, one Tomcat corresponds to one application, and multiple applications use multiple Tomcat. What is the difference between it and one Tomcat to load multiple applications?

The purpose of deploying multiple Web applications in the same Tomcat instance is to save resources such as memory. However, the configuration and deployment are a bit complicated, the applications interact with each other, and the hardware cost is low.

note

This article is my personal study of Li Haoshuang’s column course, combined with the column articles and the teacher’s questions to students organized study notes. For sharing only. For more exciting content, you can scan the below two codes, and subscribe to Li Jishuang’s In-depth Dismantling of Tomcat & Jetty during geek time. Obtain first-hand learning materials.