tomcat基本流程
// Start our child containers, if any Container children[] = findChildren(); List<Future<Void>> results = new ArrayList<>(); for (int i = 0; i < children.length; i++) { // 这句代码就是会调用ContainerBase下的一个个子容器的call方法 results.add(startStopExecutor.submit(new StartChild(children[i]))); }
private static class StartChild implements Callable<Void> { private Container child; public StartChild(Container child){ this.child = child; } @Override public Void call() throws LifecycleException { child.start(); return null; } }
deployDescriptors(configBase, configBase.list()); // Deploy WARs deployWARs(appBase, filteredAppPaths); // Deploy expanded folders deployDirectories(appBase, filteredAppPaths);
ContextConfig.webConfig()的step9解析到servlets包装成wrapper对象
StandardContext.startInternal()->最终会调用 if (!loadOnStartup(findChildren()))
官网 :https://tomcat.apache.org/tomcat-8.0-doc/architecture/startup/serverStartup.pdf
01 查看tomcat进程pid ps -ef | grep tomcat 02 查看进程的信息 cat /pro/pid/status 03 查看进程的cpu和内存 top -p pid
jconsole、jvisualvm、arthas、psi-probe等
1.1 优化思路
1.1.1 conf/server.xml核心组件
Server
官网描述 :Server interface which is rarely customized by users. 【pass】
Service
官网描述 :The Service element is rarely customized by users. 【pass】
Connector
官网描述 :Creating a customized connector is a significant effort. 【 need 】
Engine
官网描述 :The Engine interface may be implemented to supply custom Engines, though this is uncommon.
【pass】
Host
官网描述 :Users rarely create custom Hosts because the StandardHost implementation provides significant
additional functionality. 【pass】
Context
官网描述 :The Context interface may be implemented to create custom Contexts, but this is rarely the case
because the StandardContext provides significant additional functionality. 【 maybe 】
Context既然代表的是web应用,是和我们比较接近的,这块我们考虑对其适当的优化
conclusion:Connector and Context
1.1.2 conf/server.xml非核心组件
官网 :https://tomcat.apache.org/tomcat-8.0-doc/config/index.html
Listener
Listener(即监听器)定义的组件,可以在特定事件发生时执行特定的操作;被监听的事件通常是Tomcat的启动和停止。
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!--监听内存溢出-->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
Global Resources
GlobalNamingResources元素定义了全局资源,通过配置可以看出,该配置是通过读取$TOMCAT_HOME/ conf/tomcat-users.xml实现的。
The GlobalNamingResources element defines the global JNDI resources for the [Server] (https://tomcat.apache.org/tomcat-8.0-doc/config/server.html)
<GlobalNamingResources> <Resource name="UserDatabase" auth="Container" type="org.apache.catalina.UserDatabase" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" pathname="conf/tomcat-users.xml" /> </GlobalNamingResources>
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" />
Realm,可以把它理解成“域”;
Realm提供了一种用户密码与web应用的映射关系,从而达到角色安全管理的作用。
在本例 中,Realm的配置使用name为UserDatabase的资源实现。
而该资源在Server元素中使用GlobalNamingResources配置
<Realm className="org.apache.catalina.realm.LockOutRealm"> <!-- This Realm uses the UserDatabase configured in the global JNDI resources under the key "UserDatabase". Any edits that are performed against this UserDatabase are immediately available for use by the Realm. --> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
</Realm>
<servlet> <servlet-name>default</servlet-name> <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>listings</param-name> <param-value>false</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
<servlet> <servlet-name>jsp</servlet-name> <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class> <init-param> <param-name>fork</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>xpoweredBy</param-name> <param-value>false</param-value> </init-param> <load-on-startup>3</load-on-startup> </servlet> <servlet-mapping> <servlet-name>jsp</servlet-name> <url-pattern>*.jsp</url-pattern> <url-pattern>*.jspx</url-pattern> </servlet-mapping>
<welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> </welcome-file-list>
<mime-mapping> <extension>123</extension> <mime-type>application/vnd.lotus-1-2-3</mime-type> </mime-mapping> <mime-mapping> <extension>3dml</extension> <mime-type>text/vnd.in3d.3dml</mime-type> </mime-mapping>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
public Connector(String protocol) {
setProtocol(protocol);
}
setProtocol(protocol)因为配置文件中传入的是HTTP/1.1,并且这里没有使用APR,一会我们会演示APR
else {
if ("HTTP/1.1".equals(protocol)) {
setProtocolHandlerClassName ("org.apache.coyote.http11.Http11NioProtocol");
} else if ("AJP/1.3".equals(protocol)) {
setProtocolHandlerClassName ("org.apache.coyote.ajp.AjpNioProtocol");
} else if (protocol != null) {
setProtocolHandlerClassName(protocol);
}
}
org.apache.coyote.http11.Http11Protocol - blocking Java connector
org.apache.coyote.http11.Http11NioProtocol - non blocking Java NIO connector
org.apache.coyote.http11.Http11Nio2Protocol - non blocking Java NIO2 connector
org.apache.coyote.http11.Http11AprProtocol - the APR/native connector.
The Executor represents a thread pool that can be shared between components in Tomcat. Historically there has been a thread pool per connector created but this allows you to share a thread pool, between (primarily) connector but also other components when those get configured to support executors
<Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/>
值太低,并发请求多了之后,多余的则进入等待状态。
值太高,启动Tomcat将花费更多的时间。
比如可以改成250。
reloadable:如果这个属性设为true,tomcat服务器在运行状态下会监视在WEB- INF/classes和WEB-INF/lib目录下 class文件的改动,如果监测到有class文件被更新 的,服务器会自动重新加载Web应用。 在开发阶段将reloadable属性设为true,有助 于调试servlet和其它的class文件,但这样用加重服务器运行负荷,建议 在Web应用的 发存阶段将reloadable设为false。
<Host startStopThreads="0"> </Host>