On the design of Tomcat multi-layer container

Time:2021-9-14

Tomcat’s container is used to load servlets. How is Tomcat’s servlet container designed?

Hierarchy of containers

Tomcat designs four containers: engine, host, context and wrapper

Tomcat makes the servlet container very flexible through this layering.

  • Context represents a web application
  • Wrapper represents a servlet. There may be multiple servlets in a web application
  • Host represents a virtual host or a site. Tomcat can be configured with multiple virtual host addresses, and multiple web applications can be deployed under a virtual host
  • Engine refers to the engine, which is used to manage multiple virtual sites. A service can only have one engine at most

Observe Tomcat’s server.xml configuration file. Tomcat adopts component-based design, and the outermost layer is server

These containers have a parent-child relationship to form a tree structure, and Tomcat uses a composite pattern to manage these containers.

All container components implement the container interface, so the composite pattern allows users to

Single container object
The lowest wrapper

Composite container object
Context, host or engine above
The use of is consistent.

Container interface definition:


public interface Container extends Lifecycle {
    public void setName(String name);
    public Container getParent();
    public void setParent(Container container);
    public void addChild(Container child);
    public void removeChild(Container child);
    public Container findChild(String name);
}

The process of requesting to locate the servlet

With so many levels of containers, how does Tomcat determine which servlet in the wrapper container handles the request?
Tomcat uses the mapper component to accomplish this task.

Mapper locates the URL requested by the user to a servlet

working principle

Mapper component saves the configuration information of web application: the mapping relationship between container component and access path, such as

  • The domain name configured in the host container
  • Web application path in context container
  • Path of servlet mapping in wrapper container

This configuration information is a multi-level map.

When a request arrives, mapper component can locate a servlet by parsing the domain name and path in the request URL, and then finding it in its saved map.
A request URL will only locate to a wrapper container, that is, a servlet.

If there is an online shopping system, there are

  • Background management system for b-end managers
  • Online shopping system for C-end users

The two systems run on the same Tomcat. In order to isolate their access domain names, two virtual domain names are configured:

manage.shopping.com
Managers access Tomcat through this domain name to manage users and commodities, and user management and commodity management are two separate web applications

user.shopping.com
C-end users search goods and place orders through this domain name. The search function and order management are also two independent web applications

In this way, Tomcat will create a service component and an engine container component, create two host sub containers under the engine container, and create two context sub containers under each host container. Since a web application usually has multiple servlets, Tomcat will also create multiple wrapper sub containers in each context container. Each container has a corresponding access path

How does Tomcat locate a URL to a servlet?

First, select the service and engine according to the protocol and port number
Each connector of Tomcat listens to different ports. For example, the default HTTP connector of Tomcat listens to port 8080 and the default AJP connector listens to port 8009. The URL accesses port 8080, so it will be received by the HTTP connector, and a connector belongs to a service component, so the service component is determined. In addition to multiple connectors, there is also an engine container in a service component, so the service is determined and the engine is determined.

Select the host based on the domain name.
Mapper component finds the corresponding host container through the domain name in the URL, such as user.shopping.com, so mapper finds the host2 container.

Find the context component according to the URL path
After the host is determined, mapper matches the path of the corresponding web application according to the path of the URL. For example, in the example, you accessed / order, so you found the context container context4.

Finally, find the wrapper (servlet) according to the URL path
After the context is determined, mapper finds the specific wrapper and servlet according to the servlet mapping path configured in web.xml.

Not only servlets will process requests. Both parent and child containers on the lookup path will process requests:

  • The adapter in the connector will call the service method of the container to execute the servlet
  • The first one to get the request is the engine container. After the engine container processes the request, it will pass the request to its own sub container host to continue processing, and so on
  • Finally, the request will be passed to the wrapper container, and the wrapper will call the final servlet to process it

The pipeline valve pipeline used in this calling process is in the responsibility chain mode. In the process of processing a request, many processors process the request in turn. Each processor is responsible for doing its own corresponding processing. After processing, it will call the next processor to continue processing.

Valve represents a processing point, such as authority authentication and logging.


public interface Valve {
  public Valve getNext();
  public void setNext(Valve valve);
  public void invoke(Request request, Response response)
}

Since valve is a processing point, the invoke method is used to process requests.
Pipeline interface:


public interface Pipeline extends Contained {
  public void addValve(Valve valve);
  public Valve getBasic();
  public void setBasic(Valve valve);
  public Valve getFirst();
}

Therefore, valve linked list is maintained in pipeline, and valve can be inserted into pipeline.
There is no invoke method in Pipeline, because the trigger of the whole call chain is that Valve completes its own processing, and calls getNext.invoke to call the next Valve.

Each container has a pipeline object. As long as the first valve of the pipeline is triggered, the valve in the pipeline in the container will be called. But how can pipelines of different containers be triggered in a chain?
For example, the pipeline in the engine needs to call the pipeline in the lower container host.
Pipeline has a getbasic method. This basicvalve is at the end of the valve chain and is responsible for calling the first valve in the pipeline of the lower container.

The whole calling process is triggered by the adapter in the connector, which will call the first valve of the engine:

Wrapper

The last valve of the container will create a filter chain, call the dofilter method, and finally call the service method of the servlet.

What’s the difference between valve and filter?

  • Valve is the private mechanism of Tomcat and is tightly coupled with Tomcat. Servlet API is a public standard. All web containers, including jetty, support filter
  • Valve works at the web container level and intercepts requests from all applications. Servlet filter works at the application level and only intercepts all requests of a web application. If you want to be an interceptor of the entire web container, you must use valve.

This is the end of this article about the design of Tomcat multi-layer container. For more information about Tomcat multi-layer container, please search the previous articles of developeppaer or continue to browse the relevant articles below. I hope you will support developeppaer in the future!