真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Tomcat源碼分析(-)啟動(dòng)過(guò)程分析

前面幾篇文章分別介紹了Tomcat的安裝、優(yōu)化和框架,本文主要用于分析Tomcat源碼啟動(dòng)過(guò)程,研究一個(gè)框架最好的著手方式可能就是研究它的啟動(dòng)過(guò)程,因?yàn)樵谶@過(guò)程中我們可以看到它內(nèi)部的層次關(guān)系,模塊關(guān)系等,對(duì)整個(gè)框架有一個(gè)高層次的掌握,后續(xù)研究就可以得心應(yīng)手了。
研究Tomcat源碼啟動(dòng)過(guò)程的最簡(jiǎn)單方式是可以通過(guò)Tomcat的啟動(dòng)類Bootstrap著手。

目前成都創(chuàng)新互聯(lián)公司已為上千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、虛擬空間、網(wǎng)站運(yùn)營(yíng)、企業(yè)網(wǎng)站設(shè)計(jì)、雙鴨山網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。

Tomcat主要類分析

1) Catalina
Catalina負(fù)責(zé)Server的加載、啟動(dòng)和關(guān)閉,Bootstrap啟動(dòng)后將Server的加載、啟動(dòng)和關(guān)閉的操作全部委托到Catalina類。

2) Server
Server是Service的生存環(huán)境。一個(gè)Server中可以有多個(gè)Service。StandardServer是Server的標(biāo)準(zhǔn)實(shí)現(xiàn)類,StandardServer可以持有多個(gè)Service。

2) Service
Service將Connector和Container包裝在一起提供對(duì)外服務(wù),一個(gè)Service可以有多個(gè)Connector,但是只有一個(gè)Container。StandardService是Service的標(biāo)準(zhǔn)實(shí)現(xiàn),StandardService分別持有多個(gè)Connector和一個(gè)Engine,將兩者聯(lián)系起來(lái)對(duì)外工作。

3) Connector
Connector負(fù)責(zé)對(duì)外交流。它的主要任務(wù)是負(fù)責(zé)接收瀏覽器的發(fā)過(guò)來(lái)的tcp連接請(qǐng)求,創(chuàng)建一個(gè)Request和Response對(duì)象分別用于和請(qǐng)求端交換數(shù)據(jù),然后會(huì)產(chǎn)生一個(gè)線程來(lái)處理這個(gè)請(qǐng)求并把產(chǎn)生的Request 和Response對(duì)象傳給處理這個(gè)請(qǐng)求的線程,處理這個(gè)請(qǐng)求的線程就是Container組件要做的事了。
ProtocolHandler負(fù)責(zé)選擇底層運(yùn)行模式Bio或者Nio,監(jiān)聽(tīng)端口,創(chuàng)建線程以及數(shù)據(jù)的處理等,它是對(duì)AbstractEndPoint的輕度封裝。Http11NioProtocol代表Nio模式Protocol,Tomcat8以后默認(rèn)采用此協(xié)議。
AbstractEndPoint代表具體的底層通訊,它負(fù)責(zé)運(yùn)行模式Bio或者Nio,綁定端口,監(jiān)聽(tīng)端口,端口的事件處理等關(guān)于Socket的事情。JIoEndPoint代表Bio模式,NioEndPoint代表Nio模式,Tomcat8以后默認(rèn)都是使用Nio模式。

4) Engine
Engine是完整的容器,其下面擁有多個(gè)虛擬主機(jī),它的責(zé)任就是將Connector請(qǐng)求分配給虛擬機(jī)處理。StandardEngine是Engine的標(biāo)準(zhǔn)實(shí)現(xiàn)類。

5) Executor
Executor工作線程,用于處理Connector傳遞的請(qǐng)求。
Tomcat啟動(dòng)過(guò)程
1) Bootstrap啟動(dòng)程序,Bootstrap是Tomcat的入口,負(fù)責(zé)加載和啟動(dòng)Server

public static void main(String args[]) { if (daemon == null) { // Don\'t set daemon until init() has completed Bootstrap bootstrap = new Bootstrap(); try { bootstrap.init(); } catch (Throwable t) { handleThrowable(t); t.printStackTrace(); return; } daemon = bootstrap; } else { // When running as a service the call to stop will be on a new // thread so make sure the correct class loader is used to prevent // a range of class not found exceptions. Thread.currentThread().setContextClassLoader(daemon.catalinaLoader); } try { String command = "start"; if (args.length > 0) { command = args[args.length - 1]; } if (command.equals("startd")) { args[args.length - 1] = "start"; daemon.load(args); daemon.start(); } else if (command.equals("stopd")) { args[args.length - 1] = "stop"; daemon.stop(); } else if (command.equals("start")) { daemon.setAwait(true); // bootstrap加載Server daemon.load(args); // bootstrap啟動(dòng)Server daemon.start(); } else if (command.equals("stop")) { daemon.stopServer(args); } else if (command.equals("configtest")) { daemon.load(args); if (null == daemon.getServer()) { System.exit(1); } System.exit(0); } else { log.warn("Bootstrap: command "" + command + "" does not exist."); } } catch (Throwable t) { // Unwrap the Exception for clearer error reporting if (t instanceof InvocationTargetException && t.getCause() != null) { t = t.getCause(); } handleThrowable(t); t.printStackTrace(); System.exit(1); } }
2) Bootstrap類load方法加載Server,Bootstrap加載Server最終委托給Catalina的load方法

private void load(String[] arguments) throws Exception { // Call the load() method String methodName = "load"; Object param[]; Class paramTypes[]; if (arguments == null || arguments.length == 0) { paramTypes = null; param = null; } else { paramTypes = new Class[1]; paramTypes[0] = arguments.getClass(); param = new Object[1]; param[0] = arguments; } // Catalina load方法調(diào)用 Method method = catalinaDaemon.getClass().getMethod(methodName, paramTypes); if (log.isDebugEnabled()) log.debug("Calling startup class " + method); method.invoke(catalinaDaemon, param); }
3) Catalina load方法負(fù)責(zé)加載Server

public void load() { long t1 = System.nanoTime(); initDirs(); initNaming(); // Create and execute our Digester Digester digester = createStartDigester(); InputSource inputSource = null; InputStream inputStream = null; File file = null; try { try { file = configFile(); inputStream = new FileInputStream(file); inputSource = new InputSource(file.toURI().toURL().toString()); } catch (Exception e) { if (log.isDebugEnabled()) { log.debug(sm.getString("catalina.configFail", file), e); } } if (inputStream == null) { try { inputStream = getClass().getClassLoader().getResourceAsStream(getConfigFile()); inputSource = new InputSource(getClass().getClassLoader().getResource(getConfigFile()).toString()); } catch (Exception e) { if (log.isDebugEnabled()) { log.debug(sm.getString("catalina.configFail", getConfigFile()), e); } } } // This should be included in catalina.jar // Alternative: don\'t bother with xml, just create it manually. if (inputStream == null) { try { inputStream = getClass().getClassLoader().getResourceAsStream("server-embed.xml"); inputSource = new InputSource(getClass().getClassLoader().getResource("server-embed.xml").toString()); } catch (Exception e) { if (log.isDebugEnabled()) { log.debug(sm.getString("catalina.configFail", "server-embed.xml"), e); } } } if (inputStream == null || inputSource == null) { if (file == null) { log.warn(sm.getString("catalina.configFail", getConfigFile() + "] or [server-embed.xml]")); } else { log.warn(sm.getString("catalina.configFail", file.getAbsolutePath())); if (file.exists() && !file.canRead()) { log.warn("Permissions incorrect, read permission is not allowed on the file."); } } return; } try { inputSource.setByteStream(inputStream); digester.push(this); digester.parse(inputSource); } catch (SAXParseException spe) { log.warn("Catalina.start using " + getConfigFile() + ": " + spe.getMessage()); return; } catch (Exception e) { log.warn("Catalina.start using " + getConfigFile() + ": " , e); return; } } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { // Ignore } } } // 設(shè)置Server屬性 getServer().setCatalina(this); getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile()); getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile()); // Stream redirection initStreams(); // Start the new server try { // Server初始化 getServer().init(); } catch (LifecycleException e) { if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE")) { throw new java.lang.Error(e); } else { log.error("Catalina.start", e); } } long t2 = System.nanoTime(); if(log.isInfoEnabled()) { log.info("Initialization processed in " + ((t2 - t1) / 1000000) + " ms"); } }
4) StandardServer初始化,StandardServer對(duì)應(yīng)的多個(gè)Service也會(huì)被一一初始化

protected void initInternal() throws LifecycleException { super.initInternal(); // Register global String cache // Note although the cache is global, if there are multiple Servers // present in the JVM (may happen when embedding) then the same cache // will be registered under multiple names onameStringCache = register(new StringCache(), "type=StringCache"); // Register the MBeanFactory MBeanFactory factory = new MBeanFactory(); factory.setContainer(this); onameMBeanFactory = register(factory, "type=MBeanFactory"); // Register the naming resources globalNamingResources.init(); // Populate the extension validator with JARs from common and shared // class loaders if (getCatalina() != null) { ClassLoader cl = getCatalina().getParentClassLoader(); // Walk the class loader hierarchy. Stop at the system class loader. // This will add the shared (if present) and common class loaders while (cl != null && cl != ClassLoader.getSystemClassLoader()) { if (cl instanceof URLClassLoader) { URL[] urls = ((URLClassLoader) cl).getURLs(); for (URL url : urls) { if (url.getProtocol().equals("file")) { try { File f = new File (url.toURI()); if (f.isFile() && f.getName().endsWith(".jar")) { ExtensionValidator.addSystemResource(f); } } catch (URISyntaxException e) { // Ignore } catch (IOException e) { // Ignore } } } } cl = cl.getParent(); } } // 初始化所有的service for (int i = 0; i < services.length; i++) { services[i].init(); } }
5) StandardService初始化,StandardService分別初始化Engine, Executor和Connector

protected void initInternal() throws LifecycleException { super.initInternal(); // 初始化Engine if (engine != null) { engine.init(); } // 初始化所有的Executor for (Executor executor : findExecutors()) { if (executor instanceof JmxEnabled) { ((JmxEnabled) executor).setDomain(getDomain()); } executor.init(); } // Initialize mapper listener mapperListener.init(); // 初始化所有的Connector synchronized (connectorsLock) { for (Connector connector : connectors) { try { connector.init(); } catch (Exception e) { String message = sm.getString("standardService.connector.initFailed", connector); log.error(message, e); if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE")) throw new LifecycleException(message); } } } }
6) Engine初始化

protected void initInternal() throws LifecycleException { // Ensure that a Realm is present before any attempt is made to start // one. This will create the default NullRealm if necessary. getRealm(); super.initInternal(); }
7) Connector初始化

protected void initInternal() throws LifecycleException { super.initInternal(); // Initialize adapter adapter = new CoyoteAdapter(this); protocolHandler.setAdapter(adapter); // Make sure parseBodyMethodsSet has a default if( null == parseBodyMethodsSet ) { setParseBodyMethods(getParseBodyMethods()); } if (protocolHandler.isAprRequired() && !AprLifecycleListener.isAprAvailable()) { throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoApr", getProtocolHandlerClassName())); } if (AprLifecycleListener.isAprAvailable() && AprLifecycleListener.getUseOpenSSL() && protocolHandler instanceof AbstractHttp11JsseProtocol) { AbstractHttp11JsseProtocol jsseProtocolHandler = (AbstractHttp11JsseProtocol) protocolHandler; if (jsseProtocolHandler.isSSLEnabled() && jsseProtocolHandler.getSslImplementationName() == null) { // OpenSSL is compatible with the JSSE configuration, so use it if APR is available jsseProtocolHandler.setSslImplementationName(OpenSSLImplementation.class.getName()); } } try { // 初始化Protocol,Bio或者Nio,開(kāi)啟監(jiān)聽(tīng)端口 protocolHandler.init(); } catch (Exception e) { throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e); } }
8) Bootstrap start方法啟動(dòng)Server,Bootstrap啟動(dòng)Server最終也委托給Catalina的start方法

public void start() throws Exception { if (catalinaDaemon == null) init(); // Cataline start方法調(diào)用 Method method = catalinaDaemon.getClass().getMethod("start", (Class[]) null); method.invoke(catalinaDaemon, (Object[]) null); }
9) Catalina start方法啟動(dòng)Server

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(); // 啟動(dòng)Server try { getServer().start(); } catch (LifecycleException e) { log.fatal(sm.getString("catalina.serverStartFail"), e); try { getServer().destroy(); } catch (LifecycleException e1) { log.debug("destroy() failed for failed Server ", e1); } return; } long t2 = System.nanoTime(); if(log.isInfoEnabled()) { log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms"); } // 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); } } if (await) { await(); stop(); } }
10) StandardServer啟動(dòng)

protected void startInternal() throws LifecycleException { fireLifecycleEvent(CONFIGURE_START_EVENT, null); setState(LifecycleState.STARTING); globalNamingResources.start(); // 啟動(dòng)所有的Service synchronized (servicesLock) { for (int i = 0; i < services.length; i++) { services[i].start(); } } }
11) StandardService啟動(dòng)

protected void startInternal() throws LifecycleException { if(log.isInfoEnabled()) log.info(sm.getString("standardService.start.name", this.name)); setState(LifecycleState.STARTING); // 啟動(dòng)Engine if (engine != null) { synchronized (engine) { engine.start(); } } // 啟動(dòng)所有的Executor synchronized (executors) { for (Executor executor: executors) { executor.start(); } } mapperListener.start(); // 啟動(dòng)所有的Connector 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); } } } }
12) StandardEngine啟動(dòng)

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(); }
13) Connector啟動(dòng)

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 { // 啟動(dòng)Protocol, Bio或者Nio,開(kāi)始接受請(qǐng)求 protocolHandler.start(); } catch (Exception e) { String errPrefix = ""; if(this.service != null) { errPrefix += "service.getName(): "" + this.service.getName() + ""; "; } throw new LifecycleException (errPrefix + " " + sm.getString ("coyoteConnector.protocolHandlerStartFailed"), e); } }
總結(jié)
從Tomcat啟動(dòng)過(guò)程來(lái)看,Bootstrap是Tomcat的啟動(dòng)入口,而Tomcat只是對(duì)Catalina的調(diào)用,所有的加載、啟動(dòng)和關(guān)閉操作最終都由Catalina完成,Catalina負(fù)責(zé)控制Server的啟動(dòng)、加載和關(guān)閉,Server的加載、啟動(dòng)和關(guān)閉內(nèi)部都是依次對(duì)Engine, Executor和Connector的調(diào)用。通過(guò)Tomcat啟動(dòng)過(guò)程,我們可以清楚地了解Tomcat內(nèi)部架構(gòu),后面可以更好地了解Tomcat內(nèi)部機(jī)制。


標(biāo)題名稱:Tomcat源碼分析(-)啟動(dòng)過(guò)程分析
本文來(lái)源:http://weahome.cn/article/cgcoei.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部