Tomcat源码系列2--Tomcat启动流程2
下面是standardEngine的启动和connector的启动
● standardEngine的启动 (1) 首先是StandardEngine.start()被调用
public void start() throws LifecycleException { // Standard container startup //进行logger,manager,cluster,realm,resource的启动 super.start(); }
(2) super.start()--->org.apache.catalina.core.ContainerBase#start()
public synchronized void start() throws LifecycleException { //(省略) server.xml中配置应用组件的启动 //StandardHost容器的启动, Container children[] = findChildren(); for (int i = 0; i < children.length; i++) { if (children[i] instanceof Lifecycle) ((Lifecycle) children[i]).start(); } //StandardPipeline的启动(容器与容器间的管道) if (pipeline instanceof Lifecycle) ((Lifecycle) pipeline).start(); }
(3) StandardHost.start()被调用
public synchronized void start() throws LifecycleException { //返回到以上的containerBase#start执行pipeline super.start(); }
(4) StandardPipeline#start
public synchronized void start() throws LifecycleException { // 将会调用HostConfig#start方法 lifecycle.fireLifecycleEvent(START_EVENT, null); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null); }
(5) HostConfig#start
public void start() { //部暑webapps deployApps(); }
(6) HostConfig#deployApps
protected void deployApps() { File appBase = appBase(); File configBase = configBase(); // Deploy XML descriptors from configBase deployDescriptors(configBase, configBase.list()); // Deploy WARs, and loop if additional descriptors are found deployWARs(appBase, appBase.list()); // Deploy expanded folders deployDirectories(appBase, appBase.list()); }
(7) deployWARs
protected void deployWARs(File appBase, String[] files) { …… deployWAR(contextPath, dir, file); }
(8) deployWAR
protected void deployWAR(String contextPath, File war, String file) { if (context instanceof Lifecycle) { // (省略) Class clazz = Class.forName(host.getConfigClass()); LifecycleListener listener = (LifecycleListener) clazz.newInstance(); ((Lifecycle) context).addLifecycleListener(listener); } context.setPath(contextPath); context.setDocBase(file); //以下这一步跟进去,,StandardContext的启动 host.addChild(context); }
(9)StandardContext#start
在Context的启动过程中,主要完成了以下任务。
----------------------------------------------------------------------------------------------------------------------
a)设置webapp的具体目录webappResources。
b)postWorkDirectory(),创建临时文件目录。Tomcat下面有一个work目录,用来存放临时文件。
c)触发START_EVENT事件监听,在这个事件监听里面会启动ContextConfig的start()事件,ContextConfig是用来配置web.xml的。
d)为context创建welcomefiles,通常是这三个启动文件:index.html、index.htm、index.jsp
e)配置filter
f)启动带有<load-on-startup>的Servlet。
g)注册JMX。
----------------------------------------------------------------------------------------------------------------------
至此,Container启动完毕,下面是connector的启动。
●connector的启动
(1) org.apache.catalina.connector.Connector.start()public void start() throws LifecycleException { // Http11Protocol的启动 protocolHandler.start(); }
(2) Http11Protocol#start
public void start() throws Exception { try { //到了终点的启动 endpoint.start(); } catch (Exception ex) { log.error(sm.getString("http11protocol.endpoint.starterror"), ex); throw ex; }
(3) JIoEndPoint#start
public void start() throws Exception { for (int i = 0; i < acceptorThreadCount; i++) { //这里的acceptor是一个线程,里面是一个serversocket的启动 Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i); acceptorThread.setPriority(threadPriority); acceptorThread.setDaemon(daemon); acceptorThread.start(); } }
(4) Acceptor#run
public void run() { // Accept the next incoming connection from the server socket try { //这里进行了accept(),等待客户端消息,进行接收 Socket socket = serverSocketFactory.acceptSocket(serverSocket); serverSocketFactory.initSocket(socket); // Hand this socket off to an appropriate processor if (!processSocket(socket)) { // Close socket right away try { socket.close(); } catch (IOException e) { // Ignore } } }catch ( IOException x ) { if ( running ) log.error(sm.getString("endpoint.accept.fail"), x); } catch (Throwable t) { log.error(sm.getString("endpoint.accept.fail"), t); } }
至此Connector.start方法调用完毕。整个server启动完毕。