Source: github.com/c-rainstorm/blog/blob/master/tomcat/

A lot of things are very clear in the sequence diagram, there is no need to introduce it step by step, so this article mainly focuses on the diagram, and then gives a brief explanation of some contents.

The tool used to draw the graphics is PlantUML + Visual Studio Code + PlantUML Extension

This article introduces Tomcat in accordance with tomcat-9.0.0.M22.

Tomcat.apache.org/tomcat-9.0-…

Overview

When the Connector starts, it starts a set of threads for different stages of request processing.

  1. Acceptor thread group. To accept a new connection and encapsulate it, select a Poller and add the new connection to Poller’s event queue.
  2. Poller Thread group. It is used to listen for Socket events, encapsulate the Socket and add it to the task queue in the worker thread pool when the Socket is readable or writable, etc.
  3. Worker Thread group. It is used to process the Request, including analyzing the Request packet and creating the Request object, and calling the container’s Pipeline for processing.

The ThreadPoolExecutor where the Acceptor, Poller, and worker reside is maintained in the NioEndpoint.

Connector Init and Start

  1. InitServerSocket () opens a ServerSocket with serversocketchannel.open (). By default, the ServerSocket is bound to port 8080. The default connection queue length is 100. You can customize this by configuring the acceptCount attribute of the Connector in conf/server.xml.
  2. CreateExecutor () is used to create the Worker thread pool. By default, 10 Worker threads are started, and the maximum number of wokers is 200 when Tomcat processes requests. You can customize these properties by configuring minSpareThreads and maxThreads of the Connector in conf/server.xml.
  3. Pollor is used to detect ready sockets. The default is no more than 2, math.min (2, runtime.geTruntime ().availableProcessors()); . We can customize this by configuring pollerThreadCount.
  4. Acceptor is used to accept new connections. The default value is 1. We can customize this by configuring acceptorThreadCount.

Requtst Process

Acceptor

  1. Acceptor after the starting blocks in the ServerSocketChannel. The accept (); Method, which returns a SocketChannel when a new connection arrives.
  2. After configuring the Socket, we encapsulate the Socket into the NioChannel and register it with the Poller. First of all, we start multiple Poller threads. When registering, connections are allocated equally to each Poller. NioEndpoint maintains a Poller array. When one connection is allocated to pollers[index], the next connection will be allocated to pollers[(index+1)%pollers.length].
  3. The addEvent() method adds the Socket to the Poller’s PollerEvent queue. At this point the Acceptor’s task is complete.

Poller

  1. The selector. Select (1000). When Poller starts, there is no registered Channel in the selector, so the method can only block when executed. All the Poller Shared a Selector, its implementation class is the sun. The nio. Ch. EPollSelectorImpl
  2. The events() method registers the Socket that was added to the event queue via the addEvent() method with EPollSelectorImpl and Poller processes it only when the Socket is readable
  3. The createSocketProcessor() method encapsulates the Socket into the SocketProcessor, which implements the Runnable interface. The worker thread processes the Socket by calling its run() method.
  4. The Execute (SocketProcessor) method submits the SocketProcessor to the thread pool and places it in the workQueue of the thread pool. WorkQueue is an instance of BlockingQueue. At this point Poller’s job is done.

Worker

  • After the worker thread is created, it executes the runWorker() method of ThreadPoolExecutor to try to fetch the task from the workQueue, but the workQueue is initially empty. So the worker thread blocks in the workqueue.take () method.
  • When a new task is added to the workQueue, the workqueue.take () method returns a Runnable, It is usually a SocketProcessor, and the worker thread then calls the SocketProcessor’s run() method to process the Socket.
  • CreateProcessor () creates an Http11Processor that parses the Socket and wraps the contents of the Socket into the Request. Pay attention to this Request is for the temporary use of a class, it is the full name of the class of org. Apache. Coyote. Request,
  • The postParseRequest() method wraps the Request and handles the mapping (from the URL to the corresponding Host, Context, or Wrapper).
  1. Before submit the Rquest CoyoteAdapter to Container handling, and org. Apache. Coyote. Request packaging to org. The apache. Catalina. The Request, Passed to the Container handling Request is org. Apache. Catalina. The Request.
  2. Connectori.getservice ().getMapper().map(), which is used to query the URL mapping in the Mapper. Mapping will be kept to the org. Apache. Catalina. The Request, the Container Request processing phase. The getHost () is the use of this is the stage of query to the mapping of the host, Request.getcontext (), request.getwrapper (), and so on.
  • Connector.getService().getContainer().getPipeline().getFirst().invoke() will pass the request to the Container for processing, Container processing is also performed in Worker threads, of course, but this is a separate module, so it’s a separate section.

Container

  • Note that almost every container has more than one registered Valve on its StandardPipeline, and we’ll only focus on the Basic Valve for each container. The other Valves did it before Basic Valve.
  • Request.gethost ().getPipeline().getFirst().invoke() first gets the corresponding StandardHost and executes its pipeline.
  • Request.getcontext ().getPipeline().getFirst().invoke() obtains the corresponding StandardContext and executes its pipeline.
  • Request.getwrapper ().getPipeline().getFirst().invoke() first gets the corresponding StandardWrapper and executes its Pipeline.
  • The most important one is Basic Valve of StandardWrapper, StandardWrapperValve
  1. When a Servlet implements the SingleThreadModel interface, StandardWrapper maintains a set of Servlet instances. When a Servlet implements the SingleThreadModel interface, StandardWrapper maintains a set of Servlet instances. This is the enjoy yuan model. Of course, SingleThreadModel was deprecated after Servlet 2.4.
  2. The createFilterChain() method gets all the filters from the StandardContext and adds all the filters that match the Request URL to the filterChain.
  3. DoFilter () executes the filter chain and calls the Servlet’s service() method when all filters have been executed.

Reference: www.amazon.com/How-Tomcat-… Product.dangdang.com/25084132.ht… Tomcat.apache.org/tomcat-9.0-… Www-eu.apache.org/dist/tomcat… Gearever.iteye.com/blog/184420…

Recent hot articles recommended:

1.1,000+ Java interview questions and answers (the latest version of 2021)

2. Finally got the IntelliJ IDEA activation code through the open source project, how sweet!

3. Ali Mock tool officially open source, kill all the Mock tools on the market!

4.Spring Cloud 2020.0.0 is officially released, a new and disruptive version!

5. “Java Development Manual (Songshan version)” the latest release, speed download!

Feel good, don’t forget to click “like” + forward oh!