在tomcat6中connector包括三种不同的connector: 1、Http Connector 基于HTTP协议,负责建立HTTP连接。它又分为BIO Http Connector与NIO Http Connector两种,后者提供非阻塞IO与长连接Comet支持。 2、AJP Connector, 基于AJP协议,AJP是专门设计用来为tomcat与http服务器之间通信专门定制的协议,能提供较高的通信速度和效率。如与Apache服务器集成时,采用这个协议。 3、APR HTTP Connector, 用C实现,通过JNI调用的。主要提升对静态资源(如HTML、图片、CSS、JS等)的访问性能。现在这个库已独立出来可用在任何项目中。Tomcat在配置APR之后性能非常强劲
Container 是容器的父接口,所有子容器都必须实现这个接口,Container 容器的设计最能体现责任链的设计模式;它有四个子容器组件构成,分别是:Engine、Host、Context、Wrapper。这四个组件不是平行的,而是父子关系, Engine 包含 Host,Host 包含 Context,Context 包含 Wrapper, 通常一个 Servlet class 对应一个 Wrapper,如果有多个 Servlet 就可以定义多个 Wrapper
在启动的过程中service责任链的下一个节点是Engine,再下一个节点是Host、然后context。
等所有的容器都初始化完成了,tomcat也就启动完成
然而贯穿整个启动过程的责任链由一个简单的接口来实现:lifecycle
lifecycle实际上就是观察者模式中的被观察者 规范了生命周期组件的状态和操作方法
lifecycleListener 监听接口 实际上就是观察者模式中的观察者 监听在生命周期组件的各种状态变化
LifecycleEvent 事件定义接口 可以通过构造函数构造生命周期中的任何一个状态
1、bootstrap.main
启动的入口
2、catalina.init
加载类库 初始化守护线程
if (daemon == null) { daemon = new Bootstrap(); try { daemon.init(); } catch (Throwable t) { t.printStackTrace(); return; } }
3、catalina.load
catalina就是tomcat的守护线程 load方法加载server.xml配置文档 加载责任链相关的监听信息
daemon.setAwait(true); daemon.load(args); daemon.start();
4、catalina.start
启动StandardServer.start方法
// Start the new server if (getServer() instanceof Lifecycle) { try { ((Lifecycle) getServer()).start(); } catch (LifecycleException e) { log.error("Catalina.start: ", e); } }
5、StandardServer.start
从这里开始 启动责任链 启动的之前先触发before_start动作、然后触发start动作、接着启动下级容器standardService、然后触发after_start动作
// Validate and update our current component state if (started) { log.debug(sm.getString("standardServer.start.started")); return; } // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null); lifecycle.fireLifecycleEvent(START_EVENT, null); started = true; // Start our defined Services synchronized (services) { for (int i = 0; i < services.length; i++) { if (services[i] instanceof Lifecycle) ((Lifecycle) services[i]).start(); } } // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
6、standardService.start
先触发before_start动作、然后触发start动作、接着启动下级容器StandardEngine、启动连接器[Connector[HTTP/1.1-8080], Connector[AJP/1.3-8009]]、然后触发after_start动作
// Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null); if(log.isInfoEnabled()) log.info(sm.getString("standardService.start.name", this.name)); lifecycle.fireLifecycleEvent(START_EVENT, null); started = true; // Start our defined Container first if (container != null) { synchronized (container) { if (container instanceof Lifecycle) { ((Lifecycle) container).start(); } } } synchronized (executors) { for ( int i=0; i<executors.size(); i++ ) { executors.get(i).start(); } } // Start our defined Connectors second synchronized (connectors) { for (int i = 0; i < connectors.length; i++) { try { ((Lifecycle) connectors[i]).start(); } catch (Exception e) { log.error(sm.getString( "standardService.connector.startFailed", connectors[i]), e); } } } // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
7、standardEngine.start
补充说明一下standardEngine、StandardHost、StandardContext都继承了ContainerBase类 ContainerBase类中重写了start方法 standardEngine只要调用super.start() 。容器ContainerBase会递归启动standardEngine下的所有子容器
// Standard container startup super.start();
8、containerBase.start
containerBase.start方法里面除了启动下级子容器外还做了不少动作 例如日志组件、集群功能加载、启动容器后台守护线程
// Validate and update our current component state if (started) { if(log.isInfoEnabled()) log.info(sm.getString("containerBase.alreadyStarted", logName())); return; } // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null); started = true; // Start our subordinate components, if any if ((loader != null) && (loader instanceof Lifecycle)) ((Lifecycle) loader).start(); logger = null; getLogger(); if ((logger != null) && (logger instanceof Lifecycle)) ((Lifecycle) logger).start(); if ((manager != null) && (manager instanceof Lifecycle)) ((Lifecycle) manager).start(); if ((cluster != null) && (cluster instanceof Lifecycle)) ((Lifecycle) cluster).start(); if ((realm != null) && (realm instanceof Lifecycle)) ((Lifecycle) realm).start(); if ((resources != null) && (resources instanceof Lifecycle)) ((Lifecycle) resources).start(); // Start our child containers, if any Container children[] = findChildren(); for (int i = 0; i < children.length; i++) { if (children[i] instanceof Lifecycle) ((Lifecycle) children[i]).start(); } // Start the Valves in our pipeline (including the basic), if any if (pipeline instanceof Lifecycle) ((Lifecycle) pipeline).start(); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(START_EVENT, null); // Start our thread threadStart(); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
StandardHost.start
StandardContext.start