上一篇咱們看了Tomcat
中各個組件的init
過程,初始化賦值好了,那麼接下來就該輪到start
了,話很少說,立刻進入主題~java
經過start
方法咱們能夠看到他是經過反射調用了 Catalina.start()
方法,按F7跳到這個類裏面看一下。web
public void start() throws Exception { if (catalinaDaemon == null) { init(); } // 經過反射調用 Catalina.start() 方法 Method method = catalinaDaemon.getClass().getMethod("start", (Class [])null); method.invoke(catalinaDaemon, (Object [])null); }
進來一看,又是熟悉的套娃風格,還得繼續往裏面跳轉多線程
仍是這個熟悉的組件生命週期類,看到這裏就彷彿看到告終局,確定是跟initInternal
這個方法同樣一層層嵌套進去,讓咱們走起~app
以前咱們有所過在一個Tomcat
中是能夠有多個service
的,因此這裏須要遍歷全部的service
分別讓各自啓動起來socket
在server.xml
文件中再給他配置一個<Service>
標籤便可,如圖所示:async
開始進入正題了,在這個方法中咱們能夠看到它分別作了如下操做:ide
engine.start()
connector.start()
protected void startInternal() throws LifecycleException { if(log.isInfoEnabled()) log.info(sm.getString("standardService.start.name", this.name)); setState(LifecycleState.STARTING); // 這裏首先啓動咱們定義的容器 engine if (engine != null) { synchronized (engine) { // 啓動 engine 子容器 engine.start(); } } synchronized (executors) { for (Executor executor: executors) { executor.start(); } } mapperListener.start(); // Start our defined Connectors second synchronized (connectorsLock) { for (Connector connector: connectors) { try { // If it has already failed, don't try and start it if (connector.getState() != LifecycleState.FAILED) { // 啓動鏈接器 connector.start(); } } catch (Exception e) { log.error(sm.getString( "standardService.connector.startFailed", connector), e); } } } }
這裏直接調用的ContainerBase.startInternal
方法實現下屬組件的啓動this
protected synchronized void startInternal() throws LifecycleException { // Log our server identification information if(log.isInfoEnabled()) log.info( "Starting Servlet Engine: " + ServerInfo.getServerInfo()); // Standard container startup super.startInternal(); }
這裏使用的是線程池的方式,若是有多個Host
,那麼就能夠多個線程並行實例化Host
,加快Tomcat
啓動速度spa
protected synchronized void startInternal() throws LifecycleException { // 啓動下屬容器 logger = null; getLogger(); Cluster cluster = getClusterInternal(); if (cluster instanceof Lifecycle) { ((Lifecycle) cluster).start(); } Realm realm = getRealmInternal(); if (realm instanceof Lifecycle) { ((Lifecycle) realm).start(); } // 查找並啓動子容器,Host 在初始化階段後仍是不完整的,須要繼續封裝,把容器關係維護完整 Container children[] = findChildren(); List<Future<Void>> results = new ArrayList<>(); for (Container child : children) { results.add(startStopExecutor.submit(new StartChild(child))); } MultiThrowable multiThrowable = null; for (Future<Void> result : results) { try { result.get(); } catch (Throwable e) { log.error(sm.getString("containerBase.threadedStartFailed"), e); if (multiThrowable == null) { multiThrowable = new MultiThrowable(); } multiThrowable.add(e); } } if (multiThrowable != null) { throw new LifecycleException(sm.getString("containerBase.threadedStartFailed"), multiThrowable.getThrowable()); } // Start the Valves in our pipeline (including the basic), if any if (pipeline instanceof Lifecycle) { ((Lifecycle) pipeline).start(); } // 設置容器生命週期狀態 setState(LifecycleState.STARTING); // Start our thread threadStart(); }
[圖片上傳失敗...(image-bc6c2d-1616772543941)]線程
protected synchronized void startInternal() throws LifecycleException { // Set error report valve String errorValve = getErrorReportValveClass(); if ((errorValve != null) && (!errorValve.equals(""))) { try { boolean found = false; Valve[] valves = getPipeline().getValves(); for (Valve valve : valves) { if (errorValve.equals(valve.getClass().getName())) { found = true; break; } } if(!found) { Valve valve = (Valve) Class.forName(errorValve).getConstructor().newInstance(); getPipeline().addValve(valve); } } catch (Throwable t) { ExceptionUtils.handleThrowable(t); log.error(sm.getString( "standardHost.invalidErrorReportValveClass", errorValve), t); } } super.startInternal(); }
Host
的實例化,是經過設置生命週期狀態來進行促發生命週期事件fireLifecycleEvent
來執行後續工做的。
deployApps
:處理 host
下多個應用deployDirectories
:處理host
下面以目錄方式部署的(results.add(),這裏也是以多線程的方式並行執行的)host.addChild()
:這時猜觸發context
實例核心內容context
:具體讀取web.xml
封裝wrapper
過程使用事件驅動交給ContextConfig
(它也是一個事件監聽器)public void startInternal() throws LifecycleException { setState(LifecycleState.STARTING); // 獲得 engine 容器 Engine engine = service.getContainer(); if (engine == null) { return; } // 找到默認主機 findDefaultHost(); // 爲當前容器以及子容器添加監聽器 addListeners(engine); // 註冊engine下全部的host Container[] conHosts = engine.findChildren(); for (Container conHost : conHosts) { Host host = (Host) conHost; if (!LifecycleState.NEW.equals(host.getState())) { // 註冊上下文和包裝器 registerHost(host); } } }
截至到這裏,容器的註冊與啓動已經完成了,接下來到鏈接器的啓動了
protected void startInternal() throws LifecycleException { // Validate settings before starting if (getPort() < 0) { throw new LifecycleException(sm.getString( "coyoteConnector.invalidPort", Integer.valueOf(getPort()))); } setState(LifecycleState.STARTING); try { protocolHandler.start(); } catch (Exception e) { throw new LifecycleException( sm.getString("coyoteConnector.protocolHandlerStartFailed"), e); } }
這裏對 EndPoint
進行初始化
public void start() throws Exception { if (getLog().isInfoEnabled()) { getLog().info(sm.getString("abstractProtocolHandler.start", getName())); } endpoint.start(); // Start timeout thread asyncTimeout = new AsyncTimeout(); Thread timeoutThread = new Thread(asyncTimeout, getNameInternal() + "-AsyncTimeout"); int priority = endpoint.getThreadPriority(); if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) { priority = Thread.NORM_PRIORITY; } timeoutThread.setPriority(priority); timeoutThread.setDaemon(true); timeoutThread.start(); }
public final void start() throws Exception { if (bindState == BindState.UNBOUND) { bind(); bindState = BindState.BOUND_ON_START; } startInternal(); }
public void bind() throws Exception { if (!getUseInheritedChannel()) { // 獲取 nio 通道 channel serverSock = ServerSocketChannel.open(); socketProperties.setProperties(serverSock.socket()); InetSocketAddress addr = (getAddress()!=null?new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort())); // 綁定端口,但還沒有使用 accept 獲取客戶端鏈接 serverSock.socket().bind(addr,getAcceptCount()); } else { // Retrieve the channel provided by the OS Channel ic = System.inheritedChannel(); if (ic instanceof ServerSocketChannel) { serverSock = (ServerSocketChannel) ic; } if (serverSock == null) { throw new IllegalArgumentException(sm.getString("endpoint.init.bind.inherited")); } } serverSock.configureBlocking(true); //mimic APR behavior // Initialize thread count defaults for acceptor, poller if (acceptorThreadCount == 0) { // FIXME: Doesn't seem to work that well with multiple accept threads acceptorThreadCount = 1; } if (pollerThreadCount <= 0) { //minimum one poller thread pollerThreadCount = 1; } setStopLatch(new CountDownLatch(pollerThreadCount)); // Initialize SSL if needed initialiseSsl(); selectorPool.open(); }
這裏經過startAcceptorThreads
啓動Accepter
線程,該線程用於接收新的Socket
鏈接