Tomcat architecture
Before the server.cat is initialized, the Tomcat will be started xml to create a multi-layer container. This container is composed of several components, with server xml as an example, this xml file contains the components to be started.
<Server> <Service> <Connector /> <Connector /> <Engine> <Host> <Context /> </Host> </Engine> </Service> </Server>
- The topmost component is server. Tomcat will first create a server during initialization. Parse xml files by creating Digester, and create standard server (the default server) using reflection;
- The top-level component is Service. A Server can have multiple services in the code StandardServer#initInternal You can see that the init() method of each Service will be traversed. In the init() method, each Service implements its own initInternal() method. When a Server is initialized, one or more services will be initialized. Each Service contains multiple connectors and a container. The main function of Service is to package the connector and container together. Each Service corresponds to different port numbers, that is, different applications. An application listens to a port number, otherwise there will be a port conflict, resulting in the transmitted data packet not knowing which port number to give;
- Connector is a connector component. The connector is responsible for network communication, parses the application layer protocol, and uses the adapter mode to convert Request / Response to ServletRequest/ ServletResponse. There are multiple connectors because different connectors resolve different protocols and support different I/O models. Protocols include HTTP 1.1 and HTTP 2, and I/O models include NIO and IO;
- Engine is a container component, representing the engine, which is used to manage multiple virtual sites. A Server has only one engine. with StandardServcie#initInternal For example, use engine Init() initializes it, where engine is standard engine. The container is composed of four components, which are used to receive the ServletRequest/ ServletResponse sent by the connector for processing. After processing, it is sent to the connector to send it to the corresponding client;
- Host is a container component and represents a virtual host (domain name). A Service has multiple hosts, that is, multiple domain names. For example, localhost https://manage.shopping.com/ , https://user.shopping.com/ Etc;
- Context is a container component, which represents a Web application and processes requests;
- Wrapper is a container component and represents a Servlet. There are multiple servlets in a Context to process requests.
The picture comes from the in-depth disassembly of Tomcat & jetty. A Tomcat (i.e. Server) instance contains multiple services. Each Service corresponds to different applications and listens to different ports. A Service contains multiple connectors and a container. The connector and container communicate through ServletRequest and servletresponse.
One click start of Tomcat
As can be seen from the previous structure introduction, Tomcat's container has a parent-child relationship. One click Startup is completed by starting the parent component, which starts a series of child components.
Tomcat startup process
Create the instance Catalina by reflection, and call the initialization load() and start() methods of the instance Catalina. These two methods will call the methods of each component for one key initialization and one key startup.
- bootstrap.init() , create a reflection instance Catalina;
- daemon.load() , daemon is bootstrap. After initialization, catalina.com will be called Load () method, and then the initialization method initInternal of each component will be called to achieve one click initialization;
- daemon.start() , call Catalina Start () method, and then call the start method of each component to achieve one click start.
public static void main(String args[]) { // Ensure thread safety synchronized (daemonLock) { if (daemon == null) { // Don't set daemon until init() has completed Bootstrap bootstrap = new Bootstrap(); try { bootstrap.init(); } catch (Throwable t) { handleThrowable(t); t.printStackTrace(); return; } // Use variables to save the current class instance daemon = bootstrap; } else { // When running as a service the call to stop will be on a new // thread so make sure the correct class loader is used to // prevent a range of class not found exceptions. Thread.currentThread().setContextClassLoader(daemon.catalinaLoader); } } try { String command = "start"; if (args.length > 0) { command = args[args.length - 1]; } if (command.equals("startd")) { args[args.length - 1] = "start"; daemon.load(args); daemon.start(); } else if (command.equals("stopd")) { args[args.length - 1] = "stop"; daemon.stop(); } else if (command.equals("start")) { daemon.setAwait(true); // Initialize each component daemon.load(args); // Start each component daemon.start(); if (null == daemon.getServer()) { System.exit(1); } } else if (command.equals("stop")) { daemon.stopServer(args); } else if (command.equals("configtest")) { daemon.load(args); if (null == daemon.getServer()) { System.exit(1); } System.exit(0); } else { log.warn("Bootstrap: command \"" + command + "\" does not exist."); } } catch (Throwable t) { // Unwrap the Exception for clearer error reporting if (t instanceof InvocationTargetException && t.getCause() != null) { t = t.getCause(); } handleThrowable(t); t.printStackTrace(); System.exit(1); } }