当前位置: 首页 > 科技观察

大公司程序员带你死磕Tomcat—Tomcat如何做到一键式启停

时间:2023-03-22 16:25:22 科技观察

大公司的程序员教你如何一键启动和停止Tomcat如果是Linux系统,运行命令start.sh。如果是Windows系统,运行命令start.bat启动,进入页面。如果要停止运行,只需要运行shutdown.sh或者shutdown.bat就可以停止程序,那么Tomcat是如何做到只用一个命令就启动所有容器的呢?脚本分析start.sh和start.bat里面的内容是一样的,所以这里主要分析start.sh的内容。os400=falsecase"`uname`"inOS400*)os400=true;;esac#resolvelinks-$0maybeasoftlink#PRG为脚本路径,如果当前脚本文件为软链接,则解析PRG真实文本文件所在路径位于PRG="$0"while[-h"$PRG"];do#判断是否是软连接ls=`ls-ld"$PRG"`#如果是软连接则输出包含字符串link=`exproflin->source"$ls":'.*->\(.*\)$'`#模式匹配源文件的路径ifexpr"$link":'/.*'>/dev/null;then#正则匹配/.*这里expr会输出匹配的个数,如果不为0表示$link包含目录PRG="$link"elsePRG=`dirname"$PRG"`/"$link"#当目录不存在时包含,表示软链接和源文件在同一个目录下fidone#获取脚本目录路径PRGDIR=`dirname"$PRG"`EXECUTABLE=catalina.sh#Checkthattargetexecutableexistsif$os400;then#-xwillOnlyworkontheos400ifthefilesare:#1.ownedbytheuser#2.ownedbythePRIMARYgroupoftheuser#thiswillnotworkiftheuserbelongsinsecondaryseuro"$PRGDIR"/"$EXECUTABLE"];thenecho"找不到$PRGDIR/$EXECUTABLE"echo"Thefileisabsenordoesnothaveexecutepermission"echo"Thisfileisneededtorunthisprogram"exit1fifi#executecatalina.sh的启动命令exec"$PRGDIR"/"$EXECUTABLE"start"$@"其实上面只是做了两件事,获取脚本的真实路径执行catalina.sh的启动命令和shutdown。sh和start.sh命令是一样的,只不过catalina.sh的stop命令是在后面执行的。catalina.sh脚本脚本中的重要步骤如下1、设置两个重要的环境变量,CATALINA_HOME,CATALINA_BASEPRGDIR=`dirname"$PRG"`[-z"$CATALINA_HOME"]&&CATALINA_HOME=`cd"$PRGDIR/..">/dev/null;pwd`[-z"$CATALINA_BASE"]&&CATALINA_BASE="$CATALINA_HOME"设置CLASSPATH变量,这里注意,默认没有setenv.sh文件,可以新建一个,添加参数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"Fipassbootstrap.jar作为CLASSPATH变量if[!-z"$CLASSPATH"];thenCLASSPATH="$CLASSPATH":fiCLASSPATH="$CLASSPATH""$CATALINA_HOME"/bin/bootstrap.jarif[-z"$CATALINA_OUT"];thenCATALINA_OUT="$CATALINA_BASE"t;/logs/catalina.outfi执行脚本参数,执行bootstrap.jar中Bootstrap类中的main方法,传入参数startshiftevaexec"\"$_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在上面的脚本中,我们可以看到最终执行是以Bootstrap的main方法为入口,所以我们打开Tomcat源码,进入Bootstrap类看它做了什么作为Tomcat的入口类分析了哪些启动类,我们先来看看Bootstrap中做了什么。这里只贴出main方法中的重要代码。//初始化类加载器并将Catalina文件加载到内存中bootstrap.init();Stringcommand="start";if(args.length>0){command=args[args.length-1];}if(command.equals("startd")){args[args.length-1]="start";//调用Catalina.java的load方法daemon.load(args);//调用Catalina的startdaemon.start()。java;}elseif(command.equals("stopd")){args[args.length-1]="stop";//调用Catalina.java的stopdaemon.stop();}elseif(command.equals("start")){daemon.setAwait(true);daemon.load(args);daemon.start();if(null==daemon.getServer()){System.exit(1);}}elseif(command.equals("stop")){daemon.stopServer(args);}elseif(command.equals("configtest")){daemon.load(args);if(null==daemon.getServer()){System.exit(1);}System.exit(0);}else{log.warn("Bootstrap:command\""+command+"\"doesnotexist.");}这里根据传入的命令不同调用Catalina的命令不同脚本方法。由于我们主要分析Tomcat是如何实现一键启动和停止的,所以我们主要分析Catalina的启动方法。在Catalina的satrt方法中,我们看到了这句getServer().start();Debugging之后,我们通过了Lifecycle的start方法,列出了Lifecycle的方法;publicvoiddestroy()throwsLifecycleException;publicLifecycleStategetState();publicStringgetStateName();publicinterfaceSingleUse{}}然后再看它的实际类,我们发现我们上面提到的整体架构中的组件都实现了这个类。在其子类LifecycleBase中,实现了start、init、stop等方法,相应调用了startInternal、initInternal、stopInternal方法。如果我们理解这里的设计模式,应该会想到这里使用了模板设计模式,抽象出所有子类的公共代码,然后重新定义一个内部抽象方法,其子类实现自己的自定义操作。在Server.xml中,我们发现第一层也是Server,然后在Catalina的satrt方法中第一次启动也是Server。上面显示了所有Tomcat模块的层次结构。只要是有层次结构的,我们应该马上就能想到组合设计模式。从这个层次结构中,我们可以得到模块之间的大小、内部和外部的关系。.有大有小:大组件管理小组件,比如Server管理Service,Service管理connectors和container。有内部和外部:连接器控制外部连接,外部组件调用内部组件完成业务功能。即请求处理的过程是由外部组件驱动的。那么根据以上两点,我们就知道,只有小才能有大,有内才能有外。这是整个层级的加载顺序,先加载小组件再加载大组件,先加载内部组件再加载外部组件。至此我们应该明白了Tomcat是如何实现一键启停的。按层级,加载的优先级。层层迭代开始。停止与开始大致相同。也是逐层迭代停止。

最新推荐
猜你喜欢