Tomcat series (3) — How does Tomcat start and stop with one click
Before Tomcat is embedded in SpringBoot, we always put the project as a War package in the Tomcat webApp directory, and then run the command start.sh for Linux system, and run the command start.sh for Windows system. After running the command start.bat, you can start up and access the page. Sh or shutdown.bat to stop the application. How does Tomcat start all containers with a single command?
Script analysis
Start. sh and start.bat have the same contents, so this section mainly analyzes the contents of start.sh.
os400=false
case "`uname`" in
OS400*) os400=true;;
esac
# resolve links - $0 may be a softlink
# PRG is the path of the script. If the current script file is a soft connection, the path of the PRG real file will be resolved
PRG="$0"
while [ -h "$PRG"];do Check whether it is a soft connection
ls=`ls -ld "$PRG"` If the connection is soft, the output contains Lin -> source string
link=`expr "$ls" : - > '. * \ \ (. *) $'` The pattern matches the path of the source file
if expr "$link" : '/. *' > /dev/null; then $link ($link, $link, $link, $link, $link, $link, $link, $link, $link
PRG="$link"
else
PRG=`dirname "$PRG"` /"$link" If no directory is included, the soft connection and the source file are in the same directory
fi
done
Get the script directory path
PRGDIR=`dirname "$PRG"`
EXECUTABLE=catalina.sh
# Check that target executable exists
if $os400; then
# -x will Only work on the os400 if the files are:
# 1. owned by the user
# 2. owned by the PRIMARY group of the user
# this will not work if the user belongs in secondary groups
eval
else
if [ ! -x "$PRGDIR"/"$EXECUTABLE" ]; then
echo "Cannot find $PRGDIR/$EXECUTABLE"
echo "The file is absent or does not have execute permission"
echo "This file is needed to run this program"
exit 1
fi
fi
Run the start command of catalina.sh
exec "$PRGDIR"/"$EXECUTABLE" start "$@"
Copy the code
It does two things in a nutshell
- Get the real path to the script
- perform
catalina.sh
thestart
The command
Sh is the same as start.sh but is followed by the stop command of catalina.sh
Catalina. Sh scripts
The important steps in the script are the following
-
Set two important environment variables, CATALINA_HOME and CATALINA_BASE
PRGDIR=`dirname "$PRG"` [ -z "$CATALINA_HOME" ] && CATALINA_HOME=`cd "$PRGDIR/.." >/dev/null; pwd` [ -z "$CATALINA_BASE" ] && CATALINA_BASE="$CATALINA_HOME" Copy the code
-
Set the CLASSPATH variable. Note that there is no setenv.sh file by default
CLASSPATH= if [ -r "$CATALINA_BASE/bin/setenv.sh" ]; then . "$CATALINA_BASE/bin/setenv.sh" elif [ -r "$CATALINA_HOME/bin/setenv.sh" ]; then . "$CATALINA_HOME/bin/setenv.sh" fi Copy the code
-
Pass in bootstrap.jar as the CLASSPATH variable
if [ ! -z "$CLASSPATH"];then CLASSPATH="$CLASSPATH": fi CLASSPATH="$CLASSPATH""$CATALINA_HOME"/bin/bootstrap.jar if [ -z "$CATALINA_OUT"];then CATALINA_OUT="$CATALINA_BASE"/logs/catalina.out fi Copy the code
-
Execute the script arguments by executing the main method of the bootstrap class in bootstrap.jar and passing in the start argument
shift eval exec "\"$_RUNJAVA\ "" "\"$LOGGING_CONFIG\ "" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \ -D$ENDORSED_PROP="\"$JAVA_ENDORSED_DIRS\ "" \ -classpath "\"$CLASSPATH\ "" \ -Djava.security.manager \ -Djava.security.policy=="\"$CATALINA_BASE/conf/catalina.policy\"" \ -Dcatalina.base="\"$CATALINA_BASE\ "" \ -Dcatalina.home="\"$CATALINA_HOME\ "" \ -Djava.io.tmpdir="\"$CATALINA_TMPDIR\ "" \ org.apache.catalina.startup.Bootstrap "$@" start Copy the code
In the above script, we can see that the last execution is from the main method of Bootstrap as the entry, so we open the Tomcat source code into the Bootstrap class to see what it does.
Priming class analysis
As an entry class for Tomcat, let’s take a look at what we do in Bootstrap. Only the important code in the main method is posted here.
Bootstrap.init (); // Initialize the classloader and load the Catalina file into memory. Stringcommand = "start";
if (args.length > 0) {
command = args[args.length - 1];
}
if (command.equals("startd")) {
args[args.length - 1] = "start"; // Call daemon.load(args) of Catalina.java; // Call daemon.start() for catalina.java; }else if (command.equals("stopd")) {
args[args.length - 1] = "stop"; // Call catalina.java stop daemon.stop(); }else if (command.equals("start")) {
daemon.setAwait(true);
daemon.load(args);
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.");
}
Copy the code
Here are different methods called Catalina based on the commands passed in from the script. Since we mainly analyze how Tomcat can start and stop with one click, we mainly analyze Catalina’s start method.
We see this in Catalina’s SATRT method
getServer().start();
Copy the code
Subsequent debugging will be done with the Start method for Lifecycle, which will be listed
public interface Lifecycle {
public void addLifecycleListener(LifecycleListener listener);
public LifecycleListener[] findLifecycleListeners();
public void removeLifecycleListener(LifecycleListener listener);
public void init() throws LifecycleException;
public void start() throws LifecycleException;
public void stop() throws LifecycleException;
public void destroy() throws LifecycleException;
public LifecycleState getState();
public String getStateName();
public interface SingleUse {
}
}
Copy the code
Then looking at its implementation class, we see that all the components in the overall architecture we talked about earlier implement this class. Its subclass LifecycleBase implements start, init, stop and other methods, and calls startInternal, initInternal, stopInternal methods accordingly. One might imagine that the template design pattern is applied here, abstracting out the public code of all subclasses, and then redefining an internal abstraction method whose subclasses implement their own custom operations.
In server.xml we found that the first tier was also a Server, and then Catalina’s SATRT method started the first Server.
The above shows the hierarchy of all Tomcat modules. As long as there is a hierarchy, we should be able to immediately think of the composite design pattern. From this hierarchy we can get the relationship between modules, big and small, inside and outside.
- Big and small: Big components manage widgets, such as Servers manage Services, and services manage connectors and containers
- Inside and out: Connectors control external connections, while outer components call inner components to perform business functions. That is, the request processing process is driven by the outer component.
So, according to the above two, we know that there is small to have big, there is inside to have outside. This is the loading order of the whole hierarchy: small components first, then large components, inner components first, then outer components. This should give you an idea of how Tomcat can start and stop with one click. By hierarchy, load priority. Layers of iteration are initiated. And stopping is pretty much the same as starting. It’s also a layer of iteration that stops.
The articles
How to debug Tomcat source code breakpoint
Tomcat Series 1 — Overall architecture
Tomcat series 2 – EndPoint source code parsing
A weird trip to find StackOverflowError problems
A simple RPC framework for hand – to – hand
A Simple RPC Framework (2) – Project transformation
Refer to the article
- Expr command instance
- Tomcat running script and Startup process analysis catalina.sh