2. Process HTTP requests in the Web container

The Web container runs on the computer as a process, and we know that processes are the smallest unit of system resource allocation and threads are the smallest unit of system task execution. From this point of view, The Web container is like the building or community where the recipient of the parcel lives. The HTTP logistics express system can only deliver the parcel to the reception desk of the building or community property, which does not belong to the logistics express system, just like the Web container does not belong to the computer network infrastructure. The reason for this division of labor is that the network routing information is controlled by the domain name server (DNS), router and other devices, while the internal architecture information of the Web container is known only by itself. There is also a complex process that goes through between receiving an HTTP request from a Web container and routing it to a specific application, and understanding this process can be useful for both daily development and problem analysis. Now, veteran brother, I’m going to take you through the process.

There are many Web container types in the JAVA language, including Tomcat, Jetty, Resin, Websphere, Weblogic, JBoss, Glassfish, GonAS, etc. Tomcat is an open source Web container maintained by Apache Software Foundation. With a market share of nearly 60%, Tomcat is by far the most popular Web container, spanning both Web servers and Java application servers, as shown in the figure below.

<Server port="8005" shutdown="SHUTDOWN">

  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />

  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JasperListener" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>

  <Service name="Catalina">
    <Connector port="8080" protocol="HTTP / 1.1"The maxThreads connectionTimeout = = "150""20000"
               redirectPort="8443" />
               
    <Connector port="8009" protocol="AJP / 1.3" redirectPort="8443"/> <Connector port= "8443" maxThreads= "150" minSpareThreads= "25" maxSpareThreads= "75"enableLookups ="false"AcceptCount =" 100 "debug=" 0 "Scheme =" HTTPS "Secure ="true"ClientAuth ="false"SslProtocol =" TLS "/> <Engine name="Catalina" defaultHost="localhost">
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>
      
      <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log." suffix=".txt"
               pattern="%h %l %u %t " %r" %s %b" />
      </Host>
    </Engine>
  </Service>
</Server>
Copy the code

2.1 Overview of Tomcat Core Components

If you use Config Tomcat regularly, the above configuration files are familiar to you. To facilitate your understanding, we will extract the key nodes in the above configuration file and then analyze them one by one.

<Server>                              
    <Service>
        <Connector />
        <Connector />
        <Engine>
            <Host>
                <Context />
            </Host>
        </Engine>        
    </Service>
</Server>
Copy the code

This structure contains the core components of Tomcat: the Server component is at the top level and represents the entire Tomcat container. A Server component can contain one or more Service components. A Service is a layer on top of a Connector and an Engine, and it assembles them together to provide services. A Service can contain multiple connectors, but only one Engine. Different connectors receive requests for protocols on different ports, while Engine handles requests. Engine contains one or more hosts, and Host contains one or more contexts. Engine, Host, and Context are all container components. A Host component represents a virtual Host. A Context component represents a Web application running on a Host.

2.1.1 Top class component Server

It is the only root element of the entire configuration file and represents the entire Tomcat container, which can contain multiple services. The main responsibility of a Server is to manage multiple services, provide external access to clients, and maintain the life cycle of all services, including initializing services, ending services, and locating services to be accessed by clients. The Lifecycle of all Tomcat components is controlled through the Lifecycle interface. Components that inherit this interface and implement the methods in it can be controlled by the parent component. In this way, the Server component can control the Lifecycle of all components. The Server is controlled by starting and shutting down Tomcat. In the previous configuration example, the Server configuration is as follows:

<Server port="8005" shutdown="SHUTDOWN">
Copy the code

Where, the attribute shutdown specifies the instruction to shutdown the Server. The port attribute specifies the port on which the Server receives the shutdown command. If the value is set to -1, this port can be disabled.

2.1.2 Top class component Service

A Service can contain multiple connectors but only one Engine. The Connector is responsible for receiving requests from the client. The Engine handles requests that Connector receives. As in the previous configuration example, the Service configuration is as follows:

<Service name="Catalina">
Copy the code

We can name the Service using the property name. Different services are responsible for monitoring the ports bound by their Connector.

2.1.3 Connector component Connector

The working modes of Tomcat can be divided into the following two categories:

  • As a Web server: The request comes directly from the client HTTP request (or browser).
  • As a Java Web application server: Requests come from front-facing Web servers, usually Apache, IIS, Nginx, and so on. Tomcat’s main advantage is that as a JSP/Servlet container, it is inefficient in handling static resources. Therefore, it is usually integrated with Web servers such as Apache, IIS, and Nginx. The AJP protocol is responsible for the interaction between Tomcat and the integrated Web server.

    Each Service can have one or more Connectors. In different working modes, Tomcat needs to define corresponding Connectors for different types of requests so that it can correctly receive requests from the client based on the protocol. You can define a Connector using a variety of attributes, some of which apply only to a particular Connector type. Generally speaking, there are four common types of Connector: HTTP, SSL, AJP, and Proxy.

    As a communications interface, the Connector receives requests from external clients for its particular Service and sends replies back to external clients. The specific responsibilities include creating Request and Response objects to exchange data with external clients, and handing the Request to the accompanying Engine for processing. By modifying the Connector properties, you can control the network protocol and port number monitored by the Service as shown in the following example:

<Connector port="8080" protocol="HTTP / 1.1"The maxThreads connectionTimeout = = "150""20000" 
           redirectPort="8443" />

<Connector port="8009" protocol="AJP / 1.3" redirectPort="8443"/> <Connector port= "8443" maxThreads= "150" minSpareThreads= "25" maxSpareThreads= "75"enableLookups ="false"AcceptCount =" 100 "debug=" 0 "Scheme =" HTTPS "Secure ="true"ClientAuth ="false"SslProtocol TLS =" "/ >Copy the code
  • In configuration 1, the client can access Tomcat using HTTP through port 8080.
  • In configuration two, clients can access Tomcat through port 8009 using AJP. The AJP protocol is primarily used to collaborate with other HTTP server connections. This connector will be used when Tomcat is integrated with other HTTP servers.
  • Configuration 3: The client can access Tomcat using HTTPS through port 8443.

The definition of a connector can be configured with a wide range of properties. The following is a description of common properties:

  • Address: specifies the address that the connector listens to. The default is all addresses, that is, 0.0.0.0.
  • MaxThreads: supports the maximum number of concurrent connections. The default value is 200.
  • Port: listening port. The default value is 0.
  • Protocol: protocol used by the connector. The default value is HTTP/1.1. AJP/1.3 is used when defining the AJP protocol.
  • RedirectPort: If HTTPS is mandatory, the request for HTTP will be redirected to port 8443.
  • ConnectionTimeout: indicates the timeout period of the connection, expressed in milliseconds. The default value is 60000, that is, 1 minute.
  • EnableLookups: Whether to use request.getremoteHost () to query the DNS server to obtain the host name of the client.
  • AcceptCount: Indicates the maximum length of a wait queue. Typically, new requests are placed on a wait queue when all Tomcat processing threads are busy.

2.1.4 Container Component Engine

An Engine can contain multiple hosts, which are the component of a Service component that handles requests. It receives requests from one or more connectors and processes them, encapsulating the results of the processing as a response to the Connector, which is ultimately passed back to the external client. In the previous example configuration file, the Engine is configured as follows:

<Engine name="Catalina" defaultHost="localhost">
Copy the code

The attribute name is used for logs and error messages, and its value is guaranteed to be unique in the entire Server. The defaultHost attribute specifies the defaultHost name. If the Host name specified in the HTTP request does not exist, the Host specified by defaultHost will be used. Therefore, the value of defaultHost must match the name value of one of the Host components in Engine.

2.1.5 Container Component Host

Host represents a virtual Host. It corresponds to an entity on the computer network, that is, a domain name or IP address registered on the DNS server, for example, www.abc.com or 201.187.10.21. A Host can contain multiple contexts, and each Context represents a Web application. Host is responsible for installing, expanding, starting, and ending each Web application.

When filling in the recipient address, the client identifies the server it wants to access with the Host name. Tomcat extracts the Host name from the Host field in the HTTP request header and then matches the corresponding virtual Host. If no match is found, the HTTP request is sent to the defaultHost defaultHost. Therefore, the default host does not need to be the network name registered on the DNS server, for example, localhost. In the previous configuration example, the Host configuration is as follows:

<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
Copy the code

The attribute name specifies the name of the virtual host. The appBase property specifies the directory where the Web application resides. The default value is Webapps, which is a relative path that identifies the Webapps folder in the root directory of the Tomcat installation. The unpackWARs property specifies whether to decompress the WAR file of the Web application. If the value is true, Tomcat will run the Web application in the decompressed file structure. If false, Tomcat will run the Web application directly using the WAR file. The autoDeploy property specifies whether the Web application is automatically deployed.

2.1.6 Container Component Context

Context represents a Web application running on a particular virtual host and handles all requests for a particular Web application. Each Web application is based either on a WAR file or the corresponding file directory after the WAR file is decompressed. In the previous configuration file example, we do not see the configuration of the Context, because Host automatic deployment is enabled. The Web application is not configured for static deployment in the configuration file. Instead, Tomcat automatically deploits the Context components according to specific rules. Context uniquely identifies itself through the path property. Since automatic Deployment of Web applications is not relevant to the topic of this article, I won’t go into it. If you are interested in this topic, you can find resources to expand on it.

2.1.7 Nested class elements

In addition to the core components, Tomcat provides Listener, GlobalNamingResources, Realm, Valve, etc. These components are embedded in the core components for use. We categorize them as embedded components and will not cover the topic.

2.2 Tomcat process for PROCESSING HTTP Requests

Based on the various core components described in the previous sections, let’s take a look at how Tomcat sends HTTP requests to specific Web applications for processing once they are delivered to Tomcat’s host:

  • Select Service and Engine based on protocol type and port number. The Connector component of a Service listens for requests for a specific protocol and port. Therefore, when Tomcat is started, the Service component starts listening on specific ports. For example, the Service Catalina listens on HTTP port 8080 and AJP port 8009. When an HTTP request reaches a specific port on the host network card, Tomcat selects a Service to handle the request based on the protocol type and port number, and the Engine is determined. By configuring multiple Services on a Server, you can access different applications on the same host through different ports.
  • Select Host by domain name or IP address: After the Service is selected, Tomcat will process the request by looking for a Host in the Service that matches the domain name or IP address specified in the HTTP request header. If no match is found, the request is processed using the default virtual host defaultHost configured in Engine.
  • Select Context based on the URI: The context-path in the URI specifies the Web application that the HTTP request will access. When the request arrives, Tomcat selects the Web application to process the request based on the matching degree between the path attribute of Context and context-Path in the URI. For example: If the path attribute of the Web application spring-Demo is /spring-demo, the request /spring-demo/user/register will be processed by Spring-Demo.

In the end, we’ll go through the process as an example of sending an HTTP request to the following address:

http://201.187.10.21:8080/spring-demo/user/register

  1. The client (or browser) sends a request to port 8080 on the host (201.187.10.21), which is received by the Coyote HTTP/1.1 Connector listening on that port.
  2. Connector passes the request to its Service’s Engine for processing and waits for the Engine to respond.
  3. The Engine gets the request and extracts the Host name from the header (201.187.10.21), looking for a match among all virtual Host hosts.
  4. If no virtual Host of the same name is matched, Engine passes the request to the default virtual Host named localhost.
  5. After receiving the request, the Host will match all the contexts it owns according to the value of context-path in the URI (/spring-demo/user/register). Pass the request to the Context representing the spring-Demo application for processing.
  6. Context constructs HttpServletRequest and HttpServletResponse objects, and calls spring-Demo as parameters. The application completes the process of business logic execution and result data storage, and waits for the response data.
  7. The Context receives the HttpServletResponse object returned by the application and returns it to Host.
  8. Host returns the HttpServletResponse object to Engine.
  9. The Engine returns the HttpServletResponse object to the Connector.
  10. The Connector returns the HttpServletResponse object to the client (or browser).

2.3 Analysis of Tomcat Architecture Evolution Trend

From the above architecture analysis, Tomcat the Java Web application server function is very powerful, it can support a variety of protocols in one instance process, at the same time support multiple virtual hosts, each virtual host also support the deployment of multiple applications, with strong scalability and flexibility. Why does it have such an architecture? This actually matches the infrastructure of Tomcat when it was born. At that time, servers were mainly minicomputers or PC servers, lacking the virtual technology of dividing resources such as containers, and processes were the smallest unit of system resource allocation. In order to make full use of resources on each computer, we usually deploy multiple applications on the same computer. However, the complexity of running multiple Tomcat instances on one computer is very high. It is better to deploy multiple Web applications on the same Tomcat instance. In this way, configuration, operation and maintenance management is more convenient.

In this architecture, Tomcat needs to go through the above complex process to process HTTP requests, which also confirms veteran brother’s belief that there is no absolutely good or bad architecture, and the architecture that matches the current business scenario is a good architecture! With the development of Internet services and the rise of cloud computing, in order to better manage large-scale application clusters, we need to use virtualization technologies such as containers to divide large particle resources into smaller and standard units. Only one Web container is installed in each container, and only one application is deployed in each Web container. Under the standardization, we can adopt the automatic operation of cloud computing.

If this trend continues, the architecture of the Web container will become less complex and less valuable. In the past, Tomcat was installed separately and applications were deployed to Tomcat later. However, under the current development mode of Spring Boot, Tomcat is used as an embedded Web container in the Starter mode, and it no longer needs to be installed and deployed independently. In a trend toward more standardization, Tomcat is mostly default, so users don’t have to pay much attention to it. To analyze and understand the reason for it is what the veteran brother said in the opening of the title: know what it is and why.

This evolution process is just like the change of housing style. In ancient cities, population density was not so large, and each family was a bungalow with a single door and courtyard. As modern population pouring into cities, earlier residential space utilization is too low, unable to support the rapid growth of residential demand, the high-rise building was born at this time, each building has multiple floors, each floor is divided into many houses, each house lived a household, Tomcat architecture is similar to the high-rise buildings. But modern city’s population is still growing, earlier high-rise cannot meet the demand of living, is not standardized, the lack of property management, peripheral is not complete, space utilization has yet to be improved, in this case the residential area was born, and standardization has improved, also form a complete set of property management, it is similar to the cloud.

The main value of this article is to help you sort out the end-to-end process framework, which is often referred to as the global or God perspective. With this framework, we can look for related node information according to our own needs to study and learn, so as not to get lost in details. Of course, considering that each of us has different work and study situations, and the problems we encounter are also different, the content of this article cannot cover all the problems we encounter, please leave your comments and ask questions.

Today first share here, if you feel valuable, please move your finger to forward to other partners in need. In addition, I will share my experience in career planning, job interviews, skills improvement and influence building in the future. Please pay attention to this column or “IT veteran brother”!

Other articles in this series are indexed below:

  • Spring: HTTP Request Processing flow and mechanism [1]
  • Spring: HTTP Request Processing and mechanism [3]
  • Spring: HTTP Request Processing flow and mechanism [4]
  • Spring: HTTP Request Processing flow and mechanism [5]