Tomcat结构分析
来源:互联网 发布:我是传奇结局知乎 编辑:程序博客网 时间:2024/06/09 21:45
来自:http://panlianghui-126-com.iteye.com/blog/810056
Tomcat是一个基于组件的服务器,它的构成组件都是可配置的,其中最外层的组件是Catalina Servlet容器,其它的组件按照一定的格式要求配置在这个容器中
Tomcat各组件是在<Tomcat_HOME>\conf\server.xml文件中配置,其配置文件内容如下
- <Server port="8005" shutdown="SHUTDOWN">
- <Service name="Catalina">
- <!--The connectors can use a shared executor, you can define one or more named thread pools-->
- <!--
- <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
- maxThreads="150" minSpareThreads="4"/>
- -->
- <!-- A "Connector" represents an endpoint by which requests are received
- and responses are returned. Documentation at :
- Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
- Java AJP Connector: /docs/config/ajp.html
- APR (HTTP/AJP) Connector: /docs/apr.html
- Define a non-SSL HTTP/1.1 Connector on port 8080
- -->
- <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
- <!-- A "Connector" using the shared thread pool-->
- <!--
- <Connector executor="tomcatThreadPool"
- port="8080" protocol="HTTP/1.1"
- connectionTimeout="20000"
- redirectPort="8443" />
- -->
- <!-- Define a SSL HTTP/1.1 Connector on port 8443
- This connector uses the JSSE configuration, when using APR, the
- connector should be using the OpenSSL style configuration
- described in the APR documentation -->
- <!--
- <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
- maxThreads="150" scheme="https" secure="true"
- clientAuth="false" sslProtocol="TLS" />
- -->
- <!-- Define an AJP 1.3 Connector on port 8009 -->
- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>
- <!-- An Engine represents the entry point (within Catalina) that processes
- every request. The Engine implementation for Tomcat stand alone
- analyzes the HTTP headers included with the request, and passes them
- on to the appropriate Host (virtual host).
- Documentation at /docs/config/engine.html -->
- <!-- You should set jvmRoute to support load-balancing via AJP ie :
- <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
- -->
- <Engine defaultHost="localhost" name="Catalina">
- <!--For clustering, please take a look at documentation at:
- /docs/cluster-howto.html (simple how to)
- /docs/config/cluster.html (reference documentation) -->
- <!--
- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
- -->
- <!-- The request dumper valve dumps useful debugging information about
- the request and response data received and sent by Tomcat.
- Documentation at: /docs/config/valve.html -->
- <!--
- <Valve className="org.apache.catalina.valves.RequestDumperValve"/>
- -->
- <!-- 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"/>
- <!-- Define the default virtual host
- Note: XML Schema validation will not work with Xerces 2.2.
- -->
- <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true" xmlNamespaceAware="false" xmlValidation="false">
- <!-- SingleSignOn valve, share authentication between web applications
- Documentation at: /docs/config/valve.html -->
- <!--
- <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
- -->
- <!-- Access log processes all example.
- Documentation at: /docs/config/valve.html -->
- <!--
- <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
- prefix="localhost_access_log." suffix=".txt" pattern="common" resolveHosts="false"/>
- -->
- <Context docBase="TestTomcat" path="/TestTomcat" reloadable="true" source="org.eclipse.jst.j2ee.server:TestTomcat"/><Context docBase="xishuizhipanBlog" path="/xishuizhipanBlog" reloadable="true" source="org.eclipse.jst.jee.server:xishuizhipanBlog"/></Host>
- </Engine>
- </Service>
- </Server>
server.xm文件的基本结构如下:
<Server> 代表了整个Catalina Servlet 容器,它是Tomcat实例的顶层元素。可包含一个或多个<Service>元素
<Service>包含一个<Engine>元素,以及一个或多个<Connector>元素,这些<Connector>元素共享同一个<Engine>元素
<Connector>代表和客户程序实际交互的组件,它负责接收客户请求,以及返回客户响应结果。
<Engine>每个<Service>元素只能包含一个<Engine>元素. <Engine>元素处理在同一个<Service>中所有<Connector>元素接收到的客户请求.
<Host>一个<Engine>元素中可以包含多个<Host>元素.每个<Host>元素定义了一个虚拟主机,它可以包含一个或多个Web应用.
<Contex>每个<Context>元素代表了运行虚拟主机上的但个Web应用.一个<Host>元素中可以包含多个<Context>元素.
组件的关系图如下
下面,介绍Tomcat的基本元素
1.配置Server元素
Server>元素代表了整个Catalina Servler容器,它是Tomcat实例的顶层元素,由org.apache.catalina.Server接口来定义.<Server>元素中可以包含一个或者多个<Service>元素,但<Server>元素不能作为任何其他元素的子元素.
- <Server port="8005" shutdown="SHUTDOWN">
className :指定实现org.apache.catalina.Server接口的类,默认值为org.apache.catalina.core.StandardServer.
port :指定Tomcat服务器监听shutdown命令的端口.终止Tomcat服务运行时,必须在Tomcat服务器所在的机器上发出Shutdown命令.该属性是必须设定的.
shutdown :指定终止Tomcat服务器运行时,发给Tomcat服务器的shutdown监听端口的字符串.该属性是必须设定的.
2.配置Service元素
<Service>元素由org.apache.catalina.Service接口定义,它把韩一个<Engine>元素,以及一个或多个<Connector>元素,这些<Connector>元素共享一个<Engine>元素.
- <Service name="Catalina">
<Service>处理所有直接由Tomcat服务器接收的Web客户请求。
className :指定实现org.apache.catalina.Service接口的类,默认值org.apache.catalina.core.StandardService.
name :定义Service的名字.
3.配置Engine元素
<Engine>元素由org.apahe.catalina.Engine接口定义. 每个<Service>元素只能包括一个<Engine>元素. <Engine>元素处理在同一个<Service>中所有<Connector>元素接收到的客户请求.
- <Engine defaultHost="localhost" name="Catalina">
className :指定实现org.apache.catalina.Engine接口的类,默认值为org.apache.catalina.core.StandardEngine.
name :定义Engine的名字.
在<Engine>元素中可以包含如下的子元素:
<Logger>
<Realm>
<Valve>
<Host>
4.配置Connector元素
<Connector>元素由org.apache.catalina.Connector接口定义.<Connector>元素代表与客户程序实际交互的组件,它负责接收客户的请求,以及向客户返回响应结果。
- <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>
第一个<Connector>元素定义了一个HTTP Connector,它通过8080端口接收HTTP请求;
第二个<Connector>元素定义了一个JK Connector,它通过8009端口接收由其他HTTP服务器(如Apache服务器)转发过来的客户请求.
<Connector>属性含义(共同属性):
--------------------------------------------------------------
className :指定实现org.apache.catalina.Connector 接口的类,默认值为org.apache.catalina.core.StandardConnector.
enableLookups :如果设为true,表示支持域名解析,可以把IP地址解析为主机名.Web应用调用request.getRemostHost方法将返回客户的主机名.该属性默认值为true.
redirectPort :指定转发端口.如果当前端口只支持non-SSL请求,在需要安全通信的场合,将把客户请求转发到基于SSL的redirectPort的端口.
HttpConnector的属性描述如下:
--------------------------------------------------------------
calssName :指定实现org.apache.catalina.Connector接口的类,默认值为org.apache.coyote.tomcat5.CoyoteConnector.
enableLookups :同上.
redirectPort :同上.
prot :设定TCP/IP断口号,默认为8080.
address :如果服务器有两个以上IP地址,该属性可以设定端口监听的IP地址,默认情况下,端口会监听服务器上所有IP地址.
bufferSize :设定由端口创建的输入流的缓存大小,默认值为2048byte.
protocol :设定HTTP协议,默认值为HTTP/1.1.
maxThreads :设定处理客户请求的线程的最大数目,这个值也决定了服务器可以同时响应客户请求的最大数目,默认值为200.
acceptCount :设定在监听端口队列中的最大客户请求数,默认值为10. 如果队列已满,客户请求将被拒绝.
connectionTimeout :定义建立客户连接超时的时间,以毫秒为单位.如果设置为-1,表示不限制建立客户连接的时间.
JK Connector 的属性如下:
--------------------------------------------------------------
className :指定实现org.apache.catalina.Connector接口的类,默认值为org.apache.coyote.tomact5.CoyoteCnnector.
enableLookups :同上.
redirectPort :同上.
port :设定AJP端口号.
protocol :必须设定为AJP/1.3协议.
5.配置<Host>元素
<Host>元素由org.apache.catalina.Host接口定义.一个<Engine>元素可以包含多个<Host>元素.每个<Host>元素定义了一个虚拟主机,它可以包含一个或多个Web应用.
- <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true" xmlNamespaceAware="false" xmlValidation="false">
以上代码定义了一个名为localhost的虚拟主机,Web客户访问它的URL为: http://localhost:8080/
className :指定实现org.apache.catalina.Host接口的类,默认值为org.apache.catalina.core.StandardHost.
appBase :指定虚拟主机的目录,可以指定绝对目录,也可以指定相对于<CATALINA_HOME>的相对目录. 如果此项没有设定,默认值为<CATALINA_HOME>/webapps.
unpackWARs :如果此项设为true,表示将把Web应用的WAR文件先展开为开放目录结构后再运行.如果设为false,将直接运行WAR文件.
autoDeploy :如果此项设为true,表示当Tomcat服务器处于运行状态时,能够监测appBase下的文件,如果有新的Web应用加入进来,会自动发布这个Web应用.
alias :指定虚拟主机的别名,可以指定多个别名.
deployOnStartup :如果此项设为true,表示Tomcat服务器启动时会自动发布appBase目录下的所有Web应用,如果Web应用在server.xml中没有相应的<Context>元素,将采用Tomcat默认的Context. deployOnStartup的默认值为true.
name :定义虚拟主机的名字.}
在<Host>元素中可以包含如下的子元素:
<Logger>
<Realm>
<Valve>
<Context>
6.配置Contex元素
<Context>元素由org.apache.catalina.Context接口定义. <Context>元素是使用最频繁的元素. 每个<Context>元素代表了运行在虚拟主机上的单个Web应用. 一个<Host>元素中可以包含多个<Context>元素.
- <Context docBase="TestTomcat" path="/TestTomcat" reloadable="true" source="org.eclipse.jst.j2ee.server:TestTomcat"/><Context docBase="xishuizhipanBlog" path="/xishuizhipanBlog" reloadable="true" source="org.eclipse.jst.jee.server:xishuizhipanBlog"/></Host>
className :指定实现org.apache.catalina.Context接口的类,默认值为org.apache.catalina.core.StandardContext.
path :指定访问该Web应用的URL入口.
docBase :指定Web应用的文件路径.可以给定绝对路径,也可以给定相对于Host的appBase属性的相对路径. 如果Web应用采用开放目录结构,那就指定Web应用的根目录;如果Web应用是个WAR文件,那就指定WAR文件的路径.
reloadable :如果这个属性设为true,Tomcat服务器在运行状态下会监视在WEB-INF/class和WEB-INF/lib目录下CLASS文件的改动.如果检测到有calss文件被更新,服务器会自动重新加载Web应用.
cookies :指定是否通过Cookie来支持Session,默认为true.
useNaming :指定是否支持JNDI,默认为true.
<----------------------------------------------------------------------------------------------------------------------------->
下面解说下tomcat的启动过程
从开始学习网页编程时,我就一直在疑惑,为什么这个程序不要main函数,直接启动服务器就行了。但是服务器又是怎么启动的?
最近看了一片文档,以及自己查看tomcat源码,才大概了解那么一点。
1.启动tomcat
apache-tomcat-6.0.29\bin\bootstrap.jar
org.apache.catalina.startup.Bootstrap start
Bootstrap是Tomcat的入口。比如启动、关闭、重启都是通过这个类实现对tomcat的控制。
2.ClassLoader的使用
Tomcat对不同的模块可能使用不同的ClassLoader加载。这也就是为什么很多类不在启动的classpath中,却可以被它调用的原因。
下面是Bootstrap初始化ClassLoader的方法:
- private void initClassLoaders() {
- try {
- commonLoader = createClassLoader("common", null);
- if( commonLoader == null ) {
- // no config file, default to this loader - we might be in a 'single' env.
- commonLoader=this.getClass().getClassLoader();
- }
- catalinaLoader = createClassLoader("server", commonLoader);
- sharedLoader = createClassLoader("shared", commonLoader);
- } catch (Throwable t) {
- log.error("Class loader creation threw exception", t);
- System.exit(1);
- }
- }
下图是Tomcat用户手册上看到的。
Bootstrap
|
System
|
Common
/ \
Catalina Shared
(server) / \
Webapp1 Webapp2 ...
Bootstrap是JVM提供的
System是在classpath中提供的
Common包含配置文件/org/apache/catalina/startup/catalina.properties中指定的类库支持
Catalina和Shared都从Common中继承,包含的类库也在上面配置文件中指定。
WebappX在部署单个Tomcat5实例时指定。一个webapp下面的类库对另外一个是不可见的
Tomcat加载类的顺序和普通的不太一样,如下:
Bootstrap classes of your JVM
System class loader classses (described above)
/WEB-INF/classes of your web application
/WEB-INF/lib/*.jar of your web application
$CATALINA_HOME/common/classes
$CATALINA_HOME/common/endorsed/*.jar
$CATALINA_HOME/common/lib/*.jar
$CATALINA_BASE/shared/classes
$CATALINA_BASE/shared/lib/*.jar
注意,如果希望不使用JVM本身提供的类。这时可以使用jdk的endorsed特性
3. Catalina类的作用
如果要启动Tomcat,那么一个org.apache.catalina.startup.Catalina实例就生成,由它完成接下来的工作。
下面是它启动的代码
- public void start() {
- if (getServer() == null) {
- load();
- }
- if (getServer() == null) {
- log.fatal("Cannot start server. Server instance is not configured.");
- return;
- }
- long t1 = System.nanoTime();
- // Start the new server
- if (getServer() instanceof Lifecycle) {
- try {
- ((Lifecycle) getServer()).start();
- } catch (LifecycleException e) {
- log.error("Catalina.start: ", e);
- }
- }
- long t2 = System.nanoTime();
- if(log.isInfoEnabled())
- log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms");
- try {
- // Register shutdown hook
- if (useShutdownHook) {
- if (shutdownHook == null) {
- shutdownHook = new CatalinaShutdownHook();
- }
- Runtime.getRuntime().addShutdownHook(shutdownHook);
- // If JULI is being used, disable JULI's shutdown hook since
- // shutdown hooks run in parallel and log messages may be lost
- // if JULI's hook completes before the CatalinaShutdownHook()
- LogManager logManager = LogManager.getLogManager();
- if (logManager instanceof ClassLoaderLogManager) {
- ((ClassLoaderLogManager) logManager).setUseShutdownHook(
- false);
- }
- }
- } catch (Throwable t) {
- // This will fail on JDK 1.2. Ignoring, as Tomcat can run
- // fine without the shutdown hook.
- }
- if (await) {
- await();
- stop();
- }
- }
启动过程先载入配置文件,然后根据配置文件启动的Server实例启动实例
4. Server对象的生成
服务的生成就是根据配置文件server.xml,实例化的对象。对象实例化过程中,会做载入webapp,在特定端口等待客户连接等工作。
从server.xml到对象的映射是通过commons-digester.jar包完成的。这个包的一个主要功能就是映射xml到java对象。
catalina类的方法createStartDigester完成了这个工作。部分代码如下
- protected Digester createStartDigester() {
- long t1=System.currentTimeMillis();
- // Initialize the digester
- Digester digester = new Digester();
- digester.setValidating(false);
- digester.setRulesValidation(true);
- ------------- ------------- -------------
- digester.addObjectCreate("Server",
- "org.apache.catalina.core.StandardServer",
- "className");
- digester.addSetProperties("Server");
- digester.addSetNext("Server",
- "setServer",
- "org.apache.catalina.Server");
- ————————————————————————————
- // Add RuleSets for nested elements
- digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));
- digester.addRuleSet(new EngineRuleSet("Server/Service/"));
- digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
- digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));
- digester.addRuleSet(ClusterRuleSetFactory.getClusterRuleSet("Server/Service/Engine/Host/Cluster/"));
- digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Cont
- ——————————————————
- return (digester);
- }
digester会在解析之后,返回一个对象。
5. 服务的中止
org.apache.catalina.core.StandardServer.await是保持tomcat运行的秘密。方法启动一个ServerSocket,侦听发出停止的字符串。这是一个死循环。当有停止运行的字符发出,跳出此循环。
- public void await() {
- // Negative values - don't wait on port - tomcat is embedded or we just don't like ports
- if( port == -2 ) {
- // undocumented yet - for embedding apps that are around, alive.
- return;
- }
- if( port==-1 ) {
- while( true ) {
- try {
- Thread.sleep( 10000 );
- } catch( InterruptedException ex ) {
- }
- if( stopAwait ) return;
- }
- }
- // Set up a server socket to wait on
- ServerSocket serverSocket = null;
- try {
- serverSocket =
- new ServerSocket(port, 1,
- InetAddress.getByName("localhost"));
- } catch (IOException e) {
- log.error("StandardServer.await: create[" + port
- + "]: ", e);
- System.exit(1);
- }
- // Loop waiting for a connection and a valid command
- while (true) {
- // Wait for the next connection
- Socket socket = null;
- InputStream stream = null;
- try {
- socket = serverSocket.accept();
- socket.setSoTimeout(10 * 1000); // Ten seconds
- stream = socket.getInputStream();
- } catch (AccessControlException ace) {
- log.warn("StandardServer.accept security exception: "
- + ace.getMessage(), ace);
- continue;
- } catch (IOException e) {
- log.error("StandardServer.await: accept: ", e);
- System.exit(1);
- }
- // Read a set of characters from the socket
- StringBuffer command = new StringBuffer();
- int expected = 1024; // Cut off to avoid DoS attack
- while (expected < shutdown.length()) {
- if (random == null)
- random = new Random();
- expected += (random.nextInt() % 1024);
- }
- while (expected > 0) {
- int ch = -1;
- try {
- ch = stream.read();
- } catch (IOException e) {
- log.warn("StandardServer.await: read: ", e);
- ch = -1;
- }
- if (ch < 32) // Control character or EOF terminates loop
- break;
- command.append((char) ch);
- expected--;
- }
- // Close the socket now that we are done with it
- try {
- socket.close();
- } catch (IOException e) {
- ;
- }
- // Match against our command string
- boolean match = command.toString().equals(shutdown);
- if (match) {
- break;
- } else
- log.warn("StandardServer.await: Invalid command '" +
- command.toString() + "' received");
- }
- // Close the server socket and return
- try {
- serverSocket.close();
- } catch (IOException e) {
- ;
- }
- }
跳出循环后,系统执行关闭连接等资源的操作,服务就中止了。
Catalina.stopServer方法用于发出一个让服务停止的指令
- Socket socket = new Socket(hostAddress, getServer().getPort());
- OutputStream stream = socket.getOutputStream();
- String shutdown = getServer().getShutdown();
- for (int i = 0; i < shutdown.length(); i++)
- stream.write(shutdown.charAt(i));
- stream.flush();
- stream.close();
- socket.close();
- Tomcat 6 结构分析
- Tomcat结构分析
- Tomcat 总体结构分析
- tomcat目录结构分析
- Tomcat源码分析(一)--总体结构
- Tomcat分析(1)结构和启动
- Tomcat结构
- tomcat结构
- tomcat 结构
- tomcat分析
- tomcat分析
- Tomcat分析
- 04_Tomcat目录结构分析_在Tomcat中部署一个应用
- Tomcat 结构概述
- Tomcat基础结构
- Tomcat 结构概述
- Tomcat 结构概述
- Tomcat目录结构
- ASP.net和EasyUI后台管理系统
- 集群和分布式的区别
- HashMap
- HM编码器代码阅读(2)——框架以及主要流程
- BitMap、Drawable、InputStream、Byte[]互换
- Tomcat结构分析
- [PHP实例] PHP多文件上传实现
- 剑指offer系列之33:第一个只出现一次的字符
- 轨迹记忆
- lightoj1018 - Brush (IV)【状压dp】
- Java 多线程处理任务的封装
- 每天编程小题目(oneDay):求每个月兔子总数
- VirtualBOX 虚拟机安装 OS X 10.9 Mavericks 及 Xcode 5,本人X220亲测
- app审核提交 注意事项