Tomcat Series 1 — Overall architecture

Many high end development positions require at least some research into common middleware source code. This is because all the secrets are hidden in the source code, reading the source code can give us a deeper understanding of the framework or middleware, and we can learn some of the best design practices from studying the source code. With so much middleware and source code, where do we start? In fact, most middleware or frameworks have some common parts, such as network programming, multithreading, reflection and class loading technologies. So if you dig deep into one or two mediums, then you can go back and look at other middleware, and it’s easy to understand the technology and the rationale behind it. As an old WEB end framework, Tomcat is worth looking at both its overall architecture design and its internal flexible application of some technologies.

When learning the framework, I generally have an overall understanding of the framework. Knowing how it works as a whole, and then delving into just one part of it, will get you more bang for your buck.

The overall architecture

We want to understand a framework, first to understand what it does, Tomcat, as we all know, is used to handle Socket requests connected to it. Tomcat then has two functions:

  • External processing connection, the received byte flow into the desired Request and Response objects
  • The internal processing Servlet distributes the corresponding Request Request to the corresponding Servlet

Tomcat is divided into two parts: the Connnector handles external connections and the Container manages internal Servelet. The general diagram is as follows

The big box on the outer layer represents a Tomcat Service. A Tomcat Service can correspond to multiple services. Each Service has a connector and a container. These relationships can also be seen in the Tomcat directory configuration file server.xml.

<Server port="8006" shutdown="SHUTDOWN">
  <Service name="Catalina">

    <Connector port="8080" protocol="HTTP / 1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <Connector port="8010" protocol="AJP / 1.3" redirectPort="8443" />

    <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"
       
      </Host>
    </Engine>
  </Service>
</Server>

Copy the code

A Service can have more than one Connector, and the container is an Engine.

The overall architecture of Tomcat is simply this correspondence. Let’s take a brief look at the overall architecture of connectors and containers.

The connector

We can see that the connector is passing a ServletRequest object to the container and the container is passing a ServletResponse object to the connector, which is definitely not possible during network transport because of the byte stream that is being sent over the network. So the functional requirements of connectors can be summarized as follows.

  • The Socket connection
  • Read the byte stream in the request network
  • The byte stream is parsed according to the corresponding protocol (Http/AJP) to generate a unifiedTomcat RequestT object
  • willTomcat RequesTo the container
  • Container returnTomcat Responseobject
  • willTomcat ResponseObject to a byte stream
  • Returns the byte stream to the client

In fact, the above subdivision can be summarized as the following three points

  • Network communication
  • Application layer protocol parsing
  • TomcatRequest/ResponsewithServletRequest/ServletResponseObject conversion

In Tomcat, it also uses three classes to achieve the above three functions, which correspond to the following

  • EndPoint
  • Processor
  • Adapter

That’s what they look like on a graph

The container

A container, as its name implies, is a appliance for holding things. So what does this Tomcat container contain? In fact, the main is the Servlet installed. So how is the container designed? Tomcat’s container design is based on the composite design pattern (if you don’t know the composite design pattern, please read my previous article.) You can see the relationship in server.xml as well.

  <Engine name="Catalina" defaultHost="localhost">
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

      </Host>
    </Engine>

Copy the code

In this case we can only see two modules in the container, one is the top module Engine, the other is Host, there are actually two modules, one is Context for each application folder in our WebApp, each folder is a Context, There is also a module Wrapper that corresponds to all the servlets in our Context, and the Wrapper manages the mapping of access relationships to specific servlets. The graph looks something like this.

All modules of the Container in Tomcat implement the Container interface, and the significance of the combined mode is to enable users to use a single object and a combined object consistently. That is, no matter how many contexts are added, the purpose of the combined mode is to find the servlets below it. And no matter how many hosts you add, it’s just to find the Servlet below. With so many modules designed in the container, how does Tomcat find the corresponding Servlet to handle a request?

How to locate the request

Let’s take the simplest example. We have launched Tomcat on our native app, and we have deployed BuxueWushu under WebApp. We enter http://localhost:8080/buxuewushu/add.do in the browser is how to find corresponding Servlet for processing?

When we start Tomcat, the connector initializes and listens for the configured port number, in this case port 8080 for HTTP.

  • The request is sent to port 8080 on the native machine, picked up by the HTTP/1.1 Connector listening there
  • Connector Connector converts the byte stream to what is required by the containerServletRequestObject to peerServiceThe container module Engine under
  • Engine gets addresshttp://localhost:8080/buxuewushu/add. Matches the following Host Host
  • Matches a Host named localhost, even if the request is for a specific IP address and no Host is configured, the Host named localhost will be processed because it is the default Host.
  • Host matches the path as/buxuewushuContext, that is, find the appropriate folder under WebApp
  • Context matches a servlet whose URL rule is *. Do and corresponds to a servlet class
  • Call itdoGetordoPostmethods
  • The Servlet returns the object to the Context after execution
  • Context is returned to Host
  • Host is returned to Engine
  • The Engine returns to the Connector
  • The Connector Connector parses the object into a byte stream and sends it to the client

Previous articles on Tomcat

  • A weird trip to find StackOverflowError problems
  • How to debug Tomcat source code breakpoint

reference

  • In-depth dismantling of Tomcat&Jetty