What is a Tomcat
Java EE(Java Platform Enterprise Edition) is an open source Java Web application server that implements some of the technical specifications of Java EE. Examples include Java Servlets, Java Server Page, JSTL, and Java WebSocket. Java EE is a standard platform launched by Sun Company for enterprise-level applications. It defines a series of technical specifications for enterprise-level development. In addition to the above, there are EJB, Java Mail, JPA, JTA, JMS, etc., which all depend on the implementation of specific containers.
Tomcat and Jetty both provide only the Servlet and JSP specifications required for Java Web containers. Developers need to rely on other open source implementations to implement the rest of the functionality.
Glassfish is introduced by Sun. After the latest Java EE specification comes out, Glassfish will be implemented first, so it is the first choice to study the latest Java EE technology.
The most common scenario is to use Tomcat as a Java Web server, using the power that Spring provides out of the box, and relying on other open source libraries to implement responsible business functions.
The Servlet container
Tomcat consists of Container, Connector and related components.
Server: refers to the entire Tomcat Server, which contains multiple groups of services. It is responsible for managing and starting each Service. At the same time, it listens for the shutdown command sent from port 8005 to shutdown the entire container.
Service: A component-based Web Service encapsulated by Tomcat and provided externally. It contains two core components, Connectors and Container, and multiple functional components. Each Service is independent, but shares resources of the same JVM.
Connector: Tomcat connects to the outside world. It listens on a fixed port to receive external requests, send them to the Container, and return the processing results of the Container to the outside world.
Container: Catalina is a Servlet Container consisting of multi-layer containers that manage the Servlet lifecycle and invoke servlet-related methods.
Loader: encapsulates Java ClassLoader and is used to load class files in Containers. Realm: Tomcat provides access authentication and role management mechanisms for Web applications;
JMX: Defines technical specifications in Java SE, which is a framework for embedding management functions for applications, devices, and systems. The running status of Tomcat can be remotely monitored through JMX.
Jasper: Tomcat’s Jsp parsing engine, which converts JSPS into Java files and compiles them into class files. Session: Manages and creates sessions, persists sessions (customizable), and supports Session groups.
Pipeline: Acts as a pipe in a container, in which a variety of valves (valves) can be installed. Requests and responses are processed by each valve in the Pipeline, providing a flexible and configurable mechanism for processing requests and responses.
Naming: Java Naming and directory interface, a set of apis for accessing Naming and directory services in Java applications. A naming service associates names with objects, allowing us to access objects by name. A directory service is also a naming service, where objects have names as well as properties. In Tomcat, YOU can use JNDI to define data sources and configuration information for the separation of development and deployment.
The Container of
Engine: a top-level container for servlets, containing one or more Host subcontainers; Host: a virtual Host that is responsible for web application deployment and Context creation. Context: A Web application Context that contains multiple wrappers and is responsible for parsing and managing all Web resources in Web configuration. Wrapper: The low-level container that encapsulates servlets and is responsible for creating, executing, and destroying Servlet instances.
Life cycle Management To facilitate the management of the life cycle of components and containers, Tomcat defines 12 states from creation, start, stop, and destruction. The Tomcat life cycle manages internal state changes. Components and containers only need to implement the corresponding lifecycle methods to complete the operations within each lifecycle (initInternal, startInternal, stopInternal, destroyInternal).
For example, when performing an initialization operation, it will determine whether the current state is New, and if not, it will throw a lifecycle exception. If yes, set the current state to Initializing and execute the initInternal method, which is implemented by the subclass. If the method is successfully executed, set the former state to Initialized and if the execution fails, set the state to Failed.
The life cycle management of Tomcat introduces an event mechanism. When the life cycle status of a component or container changes, the event listener will be notified, and the listener will perform corresponding operations by judging the event type. The addition of event listeners can be configured in the server.xml file;
Adding listeners is used to configure Various Containers of Tomcat to decouple the configuration logic from containers. Such as EngineConfig, HostConfig, ContextConfig. HostConfig: processes application deployment, parsing meta-INF /context. XML, and creating context ContextConfig for the application. Mainly parses and merges web. XML, and scans various web resources (filters, servlets, listeners) of applications.
Tomcat startup process
The startup starts from the start.sh script provided by Tomcat. The shell script calls the main method of Bootstrap, and actually calls the load and start methods of Catalina.
The load method parses config/server.xml through Digester, creating containers and setting properties based on relationships and configuration information in the XML. Catalina then calls StandardServer’s init and start methods to initialize and start the container.
According to the configuration relationship of XML, the child element of Server is Service, and the child element of Service is the top-level container Engine. Each layer container has its own child container, and these elements realize various methods of life cycle management. Therefore, it is easy to complete the entire container startup, shutdown and other lifecycle management.
StandardServer listens on port 8005 (configurable) after the init and start methods are called. If shutdown is received, it exits the loop and executes the stop and destroy methods. The Tomcat container is closed. The JVM runtime.geTruntime ()﴿. AddShutdownHook method is also called to close the container in the event of an unexpected virtual machine exit.
All containers are derived from ContainerBase. The base class encapsulates the repetitive work in ContainerBase. It is responsible for starting the container-related components Loader, Logger, Manager, Cluster, Pipeline, and subcontainer. Submit multiple threads via the thread pool, return the Future object, start the child container internally, and then call the Future object’s GET method to wait for the result of execution).
List<Future<Void>> results = new ArrayList<Future<Void>>();
for (int i = 0; i < children.length; i++) {
results.add(startStopExecutor.submit(new StartChild(children[i])));
}
boolean fail = false;
for(Future<Void> result: results) {try {
result.get();
} catch (Exception e) {
log.error(sm.getString("containerBase.threadedStartFailed"), e);
fail = true; }}Copy the code
Note: Catalina. home: indicates the installation directory. Catalina. base: working directory; The default user. Dir
- Server.xml configates the Host element and specifies the appBase attribute, which defaults to $Catalina.base /webapps/
- Server.xml configures the Context element, specifying the docBase element, specifying the path of the Web application
- Custom configuration: $catalina. Base/EngineName/HostName/XXX. XML configuration Context elements
HostConfig listens for the StandardHost container event and parses the above configuration file in the start method:
- Scan all folders and WAR packages in the appBase path, parse meta-INF /context.xml for each application, create StandardContext, and add context to Host’s child container.
- Parsing $catalina. Base/EngineName/HostName/under all the Context configuration, find the location of the corresponding web should use, parse each application meta-inf/Context. The XML, and create StandardContext, Add the Context to the Host’s child container.
Note:
- HostConfig does not actually parse context.xml, it does so in ContextConfig.
- The watched Resource file (context.xml configuration file) is checked periodically in HostConfig
ContextConfig parse context.xml in sequence:
- First parse the global configuration config/context.xml
- And then parse the Host’s default configuration EngineName/HostName/context. The XML. The default
- Finally, parse the meta-INF /context.xml of the application
ContextConfig parses web.xml in order:
- First parse the global config/web.xml configuration
- And then parse the Host’s default configuration EngineName/HostName/web. XML. The default and then parse MEB – INF/web. The application of XML
- Scan the JAR file in web-INF /lib/, parse meta-INF /web-fragment. XML, merge THE XML, encapsulate it into WebXml, and set the Context
Note:
- Scanning for annotations (filters, Listeners, servlets) in Web applications and JARS is done in the above steps.
- The container’s periodic execution: backgroundProcess, implemented by ContainerBase, starts threads only at the top of the container. (backgroundProcessorDelay=10 flag bits to control)
**Servlet life cycle **
Servlets are server-side programs written in Java. Its main function is to interactively browse and modify data to generate dynamic Web content.
- The request arrives at the server and the server maps to the corresponding Servlet based on the URL
- Determine if the Servlet instance exists, load and instantiate the Servlet and call the init method if it does not
- The Server creates Request and Response objects, respectively, and calls the Servlet instance’s Service method (the service method internally calls the corresponding doXXX method based on the HTTP Request method type).
- The doXXX method is implemented by business logic, which obtains Request parameters from the Request object and returns the result to the caller through the response object after processing
- Server calls the destroy() method of the Servlet when the Server no longer needs the Servlet (typically when the Server is shut down).
load on startup
A value of 0 or greater means that the container loads the servlet when the application starts. When it is a negative number or not specified, it indicates that the container is loaded when the servlet is selected; The smaller the positive value is, the higher the priority of starting the servlet is.
single thread model
New servlet entity objects are created each time a servlet is accessed, but this does not guarantee thread-safety, and Tomcat limits the number of instances of servlets. Best Practice: Do not use this model, and do not have global variables in servlets
** Request process **
- Listen for HTTP or AJP requests based on the connector and port specified by the server.xml configuration
- When the Request arrives, the connection is established, the Request parameters are parsed, Request and Response objects are created, and the invoke method of the top-level container Pipeline is invoked
- Layer by layer between containers, eventually calling the Service method of the business Servlet
- The Connector writes data from the response stream to the socket
**Pipeline 与 Valve **
Pipeline can be understood as the Pipeline in reality. Valve is the Valve in the Pipeline. Request and Response objects are processed and controlled by each Valve in the Pipeline.
The basic Valve is called last in the pipe and is responsible for calling the first valve in the child container.
The three main methods in Valve :setNext, getNext, invoke; The relationship between the Valves is a one-way chain structure, with the invoke method of the next Valve itself being called.
The corresponding basic valve of each layer container is StandardEngineValve, StandardHostValve, StandardContextValve and StandardWrapperValve respectively.
The JSP engine
JSP life cycle
- Compilation phase: The servlet container compiles the servlet source text and generates the servlet class
- Initialization phase: Load the servlet class corresponding to the JSP, create an example, and call its initialization method
- Execution phase: Invoke the service method of the servlet instance corresponding to the JSP
- Destruction phase: Invoke the destruction method of the servlet instance corresponding to the JSP, and then destroy the servlet instance
JSP element code snippet: <% code snippet %> JSP declaration: <%! declaration; [ declaration; ] +… %> JSP expression: <%= expression %> JSP comment: <%– comment –%> JSP directive: <% @directive = “value” %> JSP behavior: < JSP :action_name attribute= “value” /> HTML element: HTML /head/body/div/p/… JSP implicit objects: Request, Response, Out, Session, Application, config, pageContext, Page, Exception
**JSP element description ** code snippet: contains any number of Java statements, variables, methods, or expressions; JSP declarations: A declaration statement can declare one or more variables, methods, for subsequent Java code to use; JSP expression: Output Java expression value,String form; JSP comment: To comment code and comment out a section of code JSP directive: used to set properties related to the entire JSP page, <% @page… %> Defines page dependencies such as language, contentType, errorPage, isErrorPage, import, isThreadSafe, session, etc. <% @include… %> contains other JSP files, HTML files, or text files that are part of the JSP file and are compiled to execute the <% @taglib… %> Introduces the definition of the tag library, which can be custom tag JSP behavior: JSP :include, JSP :useBean, JSP :setProperty, JSP :getProperty, JSP: Forward
**Jsp parsing process **
- Code snippet: Output directly within the _jspService() method
- JSP declaration: Output in the servlet class
- JSP expressions: output directly within the _jspService() method
- JSP comments: simply ignore and do not output
- JSP instruction: according to different instructions to distinguish,include: to introduce the file parsing; Page-related properties act as JSP properties and affect the behavior of parsing and request processing
- JSP behavior: Different behaviors have different processing methods. JSP :useBean, for example, will fetch the bean object from pageContext according to the scope’s category. If not, the bean will be created and stored in the pageContext of the corresponding scope
- HTML: Output directly within the _jspService() method
- JSP implicit objects: declared in the _jspService() method and used only in methods;
Connector
Blocking IO
Non-blocking IO
** IO multiplexing **
The difference between blocking and non-blocking is whether a read or write system call blocks if there is no data to read or no buffer space to write to.
The advantage of IO multiplexing is that it can listen for both readable and writable events on multiple sockets at the same time. This enables applications to listen on multiple sockets at the same time, freeing up application thread resources.
Tomcat Connector comparison
- JIO: A TCP module written in java. IO that blocks IO
- NIO: TCP module written in Java.nio, non-blocking IO, (IO multiplexing)
- APR: Apache Portable Runtime, which uses JNI to read files and transfer them over the network
Apache Portable Runtime is a highly Portable library that is at the heart of Apache HTTP Server 2.x. APR has many uses, including access to advanced IO functions (such as SendFile, ePoll, and OpenSSL), operating system-level functions (random number generation, system state, etc.), and local process processing (shared memory, NT pipes, and Unix sockets).
The meanings of the fields in the table are as follows:
- Support Polling: indicates whether socket event Polling based on I/O multiplexing is supported
- Polling Size: indicates the maximum number of connections for Polling
- Wait for next Request: The BIO does not release the thread while it is waiting for the next Request, so the number of concurrent connections that can be processed with keep-alive=true is limited
- Read Request Headers: The Request header data is small and can be parsed by the container without blocking
- Read Request Body: Reading the data from the Request Body is a matter of applying business logic, and Servlet restrictions are required to block reading
- Write Response: Similar to the logic used to read the Request body, block the Write
NIO handles related classes
The Poller thread gets the PollerEvent from EventQueue, executes the PollerEvent run method, calls the Selector select method, and creates Http11NioProcessor if a Socket is readable and executes it in the thread pool.
CoyoteAdapter is a Connector to a Container. Http11NioProcessor calls its service method to internally create Request and Response objects. And invoke the first Valve invoke method in the top-level container’s Pipeline
Mapper resolves mapping rules from HTTP URLS to servlets and provides map methods externally
Main parameters of NIO Connector
Comet
Comet is a push technology used in the Web. It enables the Server to send updated information to the client in real time without the need for the client to issue a request. Before WebSocket comes out, if Comet is not used, the Server can only be simulated by polling the browser. Comet supports servlets that asynchronously process IO, fire events when data is readable on a connection, and write data asynchronously (blocking)
To implement Comet, Tomcat only needs to inherit HttpServlet and implement CometProcessor interface
- Begin: initiates a new Request connection call, initializes objects related to Request and Response, and saves the Response object for subsequent data writing
- Read: called when a request connection has data to Read
- End: When data is available, called if it reads until the End of the file or response is closed
- Error: Called when an exception occurs on the connection, such as data reading exception, connection disconnection, processing exception, or socket timeout
Note:
- Read: In a POST request that has data but is not processed in a BEGIN event, Read is called. If Read does not Read data, an Error callback is raised to close the socket
- End: also called when the socket times out and response is closed. Called when the server is shut down
- Error: The socket will be closed except when the socket times out
- End and Error times should close the current Comet session by calling the close method of CometEvent Note: Be thread-safe when events are triggered
Asynchronous servlets
Traditional process:
- First, the Servlet parses the request data after receiving the request.
- Next, some method of the business interface is invoked to complete the business processing;
- Finally, the response is submitted based on the result of the processing, and the Servlet thread terminates
Asynchronous processing flow:
- The client sends a request
- The Servlet container allocates a thread to process a Servlet in the container
- The servlet calls Request.startAsync (), saves the AsyncContext, and returns
- Container threads that exist in any way exit, but response remains open
- Business threads use saved AsyncContext to complete the response (thread pool)
- The client receives a response. Procedure
The Servlet thread forwards the request to an asynchronous thread to perform the business processing, and the thread itself returns to the container. At this point, the Servlet has not generated the response data. After the asynchronous thread has processed the business, Response data can be generated directly (asynchronous threads have references to ServletRequest and ServletResponse objects)
Why is asynchrony supported in Web applications?
Asynchrony is introduced for time-consuming requests: a slow database query, an external REST API call, or some other I/ O-intensive operation. Such time-consuming requests can quickly drain the Servlet container’s thread pool, affecting scalability.
Note: From the client’s point of view, Request is still like any other HTTP request-response interaction, only it takes longer
Asynchronous event listening
- OnStartAsync: Request triggered when the startAsync method is called
- OnComplete: Triggered when syncContext calls the complete method
- OnError: Triggered when an exception occurs during the processing of a request
- OnTimeout: Indicates that the socket times out
Note: onError/ onTimeout will be triggered, followed by a callback onComplete, onComplete will not be able to operate request and response