亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Tomcat啟動(dòng)

系統(tǒng) 2884 0
Bootstrapping Tomcat
The bootstrapping process is actually rather simple. All we have to do is:
1、Set up the environment variables required by this Tomcat instance
2、Instantiate the general class loaders that will be used for our running? Tomcat instance
3、Initialize this Tomcat instance
4、Parse the main configuration file for a Tomcat instance, server.xml,?converting each configuration element into the appropriate Tomcat?component
5、Start up our outermost Top Level Element—the Server instance
6、Set up a shutdown hook
分別看看如何執(zhí)行:
1、執(zhí)行startup.bat,調(diào)用catalina.bat進(jìn)行環(huán)境變量的設(shè)置,否則通過(guò)
Bootstrap的ini()
// Set Catalina path
setCatalinaHome ();
setCatalinaBase();
2、 classloader
Our Bootstrap instance holds references to the following three class loaders:
1、commonLoader, which loads classes that are common across Tomcat, as well?
as all the web applications.
2、catalinaLoader, or serverLoader, which loads classes that are used just?
by Tomcat.
3、sharedLoader, which loads classes that are common just across all the web?
applications within a Tomcat instance.
其中:org.apache.catalina.startup.CatalinaProperties類(lèi)解析catalina.properties文件,
org.apache.catalina.startup.ClassLoaderFactory?的createClassLoader()方法將.jar文件url放入set,并返回StandardClassLoader
Tomcat啟動(dòng)
在ini方法中會(huì)
?
initClassLoaders();
Thread. currentThread ().setContextClassLoader( catalinaLoader );
SecurityClassLoad. securityClassLoad ( catalinaLoader );
// Load our startup class and call its process() method
if ( log .isDebugEnabled())
log .debug( "Loading startup class" );
Class startupClass =
catalinaLoader .loadClass
( "org.apache.catalina.startup.Catalina" );
Object startupInstance = startupClass.newInstance();
而其中的initClassLoaders()方法會(huì)初始化loaders,如下:
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);
}
}
上面代碼
Class startupClass = catalinaLoader .loadClass ( "org.apache.catalina.startup.Catalina" );
Object startupInstance = startupClass.newInstance();
實(shí)例化了startup實(shí)例。
?
4、解析Server.xml,使用了?Apache Commons Digester?
?It takes an XML document?and a RuleSet document as inputs, and generates a graph of Java objects that?
represents the structure that is defined in the XML instance document
The pattern:sax方式,例如:Server/Service/Connector
The rule:普通有4種
1、Creational actions (create an instance of a given class to represent this? XML element)
創(chuàng)建行為
2、Property setting actions (call setters on the Java object representing this? XML element, passing in the value of either a child element or an attribute)
屬性設(shè)置
3、Method invocation actions (call the specified method on the Java object?representing this element, passing in the specified parameters)
激活方法
4、Object linking actions (set an object reference by calling a setter on one? object while passing in the other as an argument)
對(duì)象引用
Server.xml的Digester
通過(guò)Catalina.java中的 createStartDigester ()方法創(chuàng)建,并設(shè)置規(guī)則
?
5、?在 Catalina.java中調(diào)用start()方法中調(diào)用getServer().initialize();
接著:services[i].initialize();
接著:connectors[i].initialize();
。。。(詳見(jiàn)最后的代碼跟蹤)
6、shutdown hook
A shutdown hook is a standard Thread that encapsulates cleanup actions that?should be taken before the Java runtime exits. All shutdown hooks are called by? the runtime when the JVM is shutting down.
Therefore, the last task that we perform is to install a shutdown hook, as?implemented by CatalinaShutdownHook. This hook is registered with the? Java Runtime by invoking its addShutdownHook() method:
Runtime.getRuntime().addShutdownHook(),
CatalinaShutdownHook is an inner class of Catalina and so has access to all the?data members of Catalina. Its run() method is very simple. It just ensures that?stop() is called on this instance of Catalina. This method invokes stop() on the?StandardServer instance, which in turn performs a cascaded invocation of stop()?on all its child components. Each child does the same for its children, until the entire?server has been cleanly stopped.
使用類(lèi) CatalinaShutdownHook實(shí)現(xiàn),它繼承Thread,run中進(jìn)行清理
// 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 );
}
}
?
啟動(dòng)tomat代碼跟蹤
View Code
1、Bootstrap.java中的main方法,啟動(dòng)tomcat;
調(diào)用init()方法初始化,并用Catalina.load(),獲取server對(duì)象,并調(diào)用ini方法
// ?Start?the?new?server
if ?(getServer()? instanceof ?Lifecycle)?{
try ?{
getServer().initialize();
}? 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);
}
}?
但是server對(duì)象是怎么來(lái)的??
往回看,在load方法中,
// ?Create?and?execute?our?Digester
Digester?digester?=?createStartDigester();?中創(chuàng)建了規(guī)則,如下:

// ?Configure?the?actions?we?will?be?using
digester.addObjectCreate("Server",
"org.apache.catalina.core.StandardServer",
"className");?
經(jīng)過(guò)反射,到類(lèi)ObjectCreateRule類(lèi)的begin方法中
// ?Instantiate?the?new?object?and?push?it?on?the?context?stack
Class?clazz?=?digester.getClassLoader().loadClass(realClassName);
Object?instance?=?clazz.newInstance();?
利用反射創(chuàng)建對(duì)象,其中:realClassName?=org.apache.catalina.core.StandardServer
在類(lèi)org.apache.catalina.core.StandardServer構(gòu)造方法中調(diào)用ServerFactory.setServer( this );?
實(shí)現(xiàn)單例Server對(duì)象創(chuàng)建。

2、?
getServer().initialize();方法中調(diào)用service的ini方法:其中services為解析server.xml
// ?Initialize?our?defined?Services
???????? for ?( int ?i?=?0;?i?<?services.length;?i++)?{
????????????services[i].initialize();
????????}
在?initialize
執(zhí)行connector的ini方法
for ?( int ?i?=?0;?i?<?connectors.length;?i++)?{
try ?{
connectors[i].initialize();?
connectors的來(lái)源也是server.xml配置文件,默認(rèn)配置:
?<Connector?connectionTimeout="20000"?port="80"?protocol="HTTP/1.1"?redirectPort="8443"/>
???????<!--?Define?an?AJP?1.3?Connector?on?port?8009?-->
????<Connector?port="8009"?protocol="AJP/1.3"?redirectPort="8443"/>


3、接下來(lái)分析connector,默認(rèn)使用protocol="HTTP/1.1"協(xié)議
? // ?Initializa?adapter
????????adapter?=? new ?CoyoteAdapter( this );
????????protocolHandler.setAdapter(adapter);
生成CoyoteAdapter,并設(shè)置,調(diào)用ini方法
protocolHandler.init();
4、接下來(lái)調(diào)用
endpoint.init();?
我們了看看JIoEndpoint?類(lèi)是做神馬的?
?*?Handle?incoming?TCP?connections.
?*
?*?This? class ?implement?a?simple?server?model:?one?listener?thread?accepts?on?a?socket?and
?*?creates?a? new ?worker?thread? for ?each?incoming?connection.
此類(lèi)實(shí)現(xiàn)了簡(jiǎn)單的server模型:一個(gè)監(jiān)聽(tīng)線程,接受socket并且為每一個(gè)到來(lái)的連接創(chuàng)建一個(gè)worker線程
真正干活的是這個(gè)!后面我們會(huì)分析它的start方法
接下來(lái)初始化其他conector

5、當(dāng)以上初始化完成后,調(diào)用Catalina.start()方法,接著啟動(dòng)server.start()方法:
((Lifecycle)?getServer()).start();?
接著調(diào)用service.start()方法
接下來(lái)是一系列的container的start,后續(xù)在分析(會(huì)部署所有的項(xiàng)目)

在service.start()中,調(diào)用executors,connectors的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);
}
}
}?
6、直到調(diào)用protocolHandler.start();?接下來(lái):JIoEndpoint.start();
public ? void ?start()
throws ?Exception?{
// ?Initialize?socket?if?not?done?before
if ?(!initialized)?{
init();
}
if ?(!running)?{
running?=? true ;
paused?=? false ;
// ?Create?worker?collection
if ?(executor?==? null )?{
workers?=? new ?WorkerStack(maxThreads);
}
// ?Start?acceptor?threads
for ?( int ?i?=?0;?i?<?acceptorThreadCount;?i++)?{
Thread?acceptorThread?=? new ?Thread( new ?Acceptor(),?getName()?+?"-Acceptor-"?+?i);
acceptorThread.setPriority(threadPriority);
acceptorThread.setDaemon(daemon);
acceptorThread.start();
}
}
}?
7、此方法會(huì)創(chuàng)建一個(gè)線程(acceptorThreadCount默認(rèn)=1),此線程Acceptor對(duì)象,看run方法
/**
*?The?background?thread?that?listens?for?incoming?TCP/IP?connections?and
*?hands?them?off?to?an?appropriate?processor.
*/
public ? void ?run()?{
// ?Loop?until?we?receive?a?shutdown?command
while ?(running)?{
// ?Loop?if?endpoint?is?paused
while ?(paused)?{
try ?{
Thread.sleep(1000);
}? catch ?(InterruptedException?e)?{
// ?Ignore
}
}
// ?Accept?the?next?incoming?connection?from?the?server?socket
try ?{
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);
}
// ?The?processor?will?recycle?itself?when?it?finishes
}
}?
這就是前面介紹的作用:接受socket并分配處理,最終關(guān)閉socket
方法:
/**
*?Process?given?socket.
*/
protected ? boolean ?processSocket(Socket?socket)?{
try ?{
if ?(executor?==? null )?{
getWorkerThread().assign(socket);
}? else ?{
executor.execute( new ?SocketProcessor(socket));
}
}? catch ?(Throwable?t)?{
// ?This?means?we?got?an?OOM?or?similar?creating?a?thread,?or?that
// ?the?pool?and?its?queue?are?full
log.error(sm.getString("endpoint.process.fail"),?t);
return ? false ;
}
return ? true ;
}?
其中g(shù)etWorkerThread()返回的worker?thread
/**
*?Return?a?new?worker?thread,?and?block?while?to?worker?is?available.
*/
protected ?Worker?getWorkerThread()?{
// ?Allocate?a?new?worker?thread
synchronized ?(workers)?{
Worker?workerThread;
while ?((workerThread?=?createWorkerThread())?==? null )?{
try ?{
workers.wait();
}? catch ?(InterruptedException?e)?{
// ?Ignore
}
}
return ?workerThread;
}
}
在看worker對(duì)象的run方法:
public ? void ?run()?{
// ?Process?requests?until?we?receive?a?shutdown?signal
while ?(running)?{
// ?Wait?for?the?next?socket?to?be?assigned
// 當(dāng)沒(méi)有請(qǐng)求時(shí),此線程一直處于等待狀態(tài),直到被喚醒,也就是notifyAll(),在之前的getWorkerThread().assign(socket)被喚醒
Socket?socket?=?await();
if ?(socket?==? null )
continue ;
// ?Process?the?request?from?this?socket
if ?(!setSocketOptions(socket)?||?!handler.process(socket))?{
// ?Close?socket
try ?{
socket.close();
}? catch ?(IOException?e)?{
}
}
// ?Finish?up?this?request
socket?=? null ;
recycleWorkerThread( this );
}
}?
最終執(zhí)行在handler.process,我們之前分析的Http11Protocol類(lèi)中的內(nèi)部類(lèi)實(shí)現(xiàn)了Handler,如下:
protected ? static ? class ?Http11ConnectionHandler? implements ?Handler?

對(duì)于我們的protocol="HTTP/1.1"?connector來(lái)說(shuō),此類(lèi)執(zhí)行了process方法,處理socket
調(diào)用processor.process()方法處理http請(qǐng)求,包括servlet、靜態(tài)資源等
/**
*?Process?pipelined?HTTP?requests?on?the?specified?socket.
*
*?
@param ?socket?Socket?from?which?the?HTTP?requests?will?be?read
*?and?the?HTTP?responses?will?be?written.
*?
*?
@throws ?IOException?error?during?an?I/O?operation
*/
public ? void ?process(Socket?theSocket)
throws ?IOException?{
RequestInfo?rp?=?request.getRequestProcessor();
rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
// ?Set?the?remote?address
remoteAddr?=? null ;
remoteHost?=? null ;
localAddr?=? null ;
localName?=? null ;
remotePort?=?-1;
localPort?=?-1;
// ?Setting?up?the?I/O
this .socket?=?theSocket;
inputBuffer.setInputStream(socket.getInputStream());
outputBuffer.setOutputStream(socket.getOutputStream());
// ?Error?flag
error?=? false ;
keepAlive?=? true ;
int ?keepAliveLeft?=?maxKeepAliveRequests;
int ?soTimeout?=?endpoint.getSoTimeout();
// ?When?using?an?executor,?these?values?may?return?non-positive?values
int ?curThreads?=?endpoint.getCurrentThreadsBusy();
int ?maxThreads?=?endpoint.getMaxThreads();
if ?(curThreads?>?0?&&?maxThreads?>?0)?{
// ?Only?auto-disable?keep-alive?if?the?current?thread?usage?%?can?be
// ?calculated?correctly
if ?((curThreads*100)/maxThreads?>?75)?{
keepAliveLeft?=?1;
}
}
// 以下設(shè)置了超時(shí),如果沒(méi)有超時(shí),那依然使用同一個(gè)socket請(qǐng)求資源,此時(shí)不用重建socket,效率高
try ?{
socket.setSoTimeout(soTimeout);
}? catch ?(Throwable?t)?{
log.debug(sm.getString("http11processor.socket.timeout"),?t);
error?=? true ;
}
boolean ?keptAlive?=? false ;
while ?(started?&&?!error?&&?keepAlive?&&?!endpoint.isPaused())?{
// ?Parsing?the?request?header
try ?{
if ?(keptAlive)?{
if ?(keepAliveTimeout?>?0)?{
socket.setSoTimeout(keepAliveTimeout);
}
else ? if ?(soTimeout?>?0)?{
socket.setSoTimeout(soTimeout);
}
}
inputBuffer.parseRequestLine();
request.setStartTime(System.currentTimeMillis());
keptAlive?=? true ;
if ?(disableUploadTimeout)?{
socket.setSoTimeout(soTimeout);
}? else ?{
socket.setSoTimeout(timeout);
}
inputBuffer.parseHeaders();
}? catch ?(IOException?e)?{
error?=? true ;
break ;
}? catch ?(Throwable?t)?{
if ?(log.isDebugEnabled())?{
log.debug(sm.getString("http11processor.header.parse"),?t);
}
// ?400?-?Bad?Request
response.setStatus(400);
adapter.log(request,?response,?0);
error?=? true ;
}
if ?(!error)?{
// ?Setting?up?filters,?and?parse?some?request?headers
rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
try ?{
prepareRequest();
}? catch ?(Throwable?t)?{
if ?(log.isDebugEnabled())?{
log.debug(sm.getString("http11processor.request.prepare"),?t);
}
// ?400?-?Internal?Server?Error
response.setStatus(400);
adapter.log(request,?response,?0);
error?=? true ;
}
}
if ?(maxKeepAliveRequests?>?0?&&?--keepAliveLeft?==?0)
keepAlive?=? false ;
// ?Process?the?request?in?the?adapter
if ?(!error)?{
try ?{
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
adapter.service(request,?response);
// ?Handle?when?the?response?was?committed?before?a?serious
// ?error?occurred.?Throwing?a?ServletException?should?both
// ?set?the?status?to?500?and?set?the?errorException.
// ?If?we?fail?here,?then?the?response?is?likely?already
// ?committed,?so?we?can't?try?and?set?headers.
if (keepAlive?&&?!error)?{? // ?Avoid?checking?twice.
error?=?response.getErrorException()?!=? null ?||
statusDropsConnection(response.getStatus());
}
}? catch ?(InterruptedIOException?e)?{
error?=? true ;
}? catch ?(Throwable?t)?{
log.error(sm.getString("http11processor.request.process"),?t);
// ?500?-?Internal?Server?Error
response.setStatus(500);
adapter.log(request,?response,?0);
error?=? true ;
}
}
// ?Finish?the?handling?of?the?request
try ?{
rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
// ?If?we?know?we?are?closing?the?connection,?don't?drain?input.
// ?This?way?uploading?a?100GB?file?doesn't?tie?up?the?thread?
// ?if?the?servlet?has?rejected?it.
if (error)
inputBuffer.setSwallowInput( false );
inputBuffer.endRequest();
}? catch ?(IOException?e)?{
error?=? true ;
}? catch ?(Throwable?t)?{
log.error(sm.getString("http11processor.request.finish"),?t);
// ?500?-?Internal?Server?Error
response.setStatus(500);
adapter.log(request,?response,?0);
error?=? true ;
}
try ?{
rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
outputBuffer.endRequest();
}? catch ?(IOException?e)?{
error?=? true ;
}? catch ?(Throwable?t)?{
log.error(sm.getString("http11processor.response.finish"),?t);
error?=? true ;
}
// ?If?there?was?an?error,?make?sure?the?request?is?counted?as
// ?and?error,?and?update?the?statistics?counter
if ?(error)?{
response.setStatus(500);
}
request.updateCounters();
rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
// ?Don't?reset?the?param?-?we'll?see?it?as?ended.?Next?request
// ?will?reset?it
// ?thrA.setParam(null);
// ?Next?request
inputBuffer.nextRequest();
outputBuffer.nextRequest();
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
// ?Recycle
inputBuffer.recycle();
outputBuffer.recycle();
this .socket?=? null ;
// ?Recycle?ssl?info
sslSupport?=? null ;
}
?

Tomcat啟動(dòng)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 日韩精品一区二区三区乱码 | 国产成人久久综合热 | 成人午夜在线 | 久久精品国产99国产精品澳门 | 欧美成人丝袜视频在线观看 | 国产精品久久在线观看 | 日本爱爱片 | 久久久噜噜噜 | 国内精品久久久久影 | 欧美激情久久欧美激情 | 青青99| 狠狠色丁香久久综合五月 | 一级做a爱片久久蜜桃 | 国产精品香蕉一区二区三区 | 国产呦精品系列在线 | 久久福利影院 | 在线日本妇人成熟免费观看 | 80岁色老头69av | 亚洲区在线播放 | 亚洲欧美中文日韩综合 | 毛片免费永久不卡视频观看 | 成人短视频视频在线观看网站 | 女性一级全黄生活片 | 日韩欧美印度一级毛片 | 久久久久久久免费视频 | 99精品视频在线 | www久久久| 婷婷色九月 | 中文字幕在线精品 | 亚洲视频在线观看免费视频 | 国产精品福利一区二区久久 | a免费视频 | 一区二区三区在线播放视频 | 日韩欧美成末人一区二区三区 | 国产视频在线一区 | 看大片全色黄大色黄 | 亚洲婷婷网 | 亚洲综合激情另类图片专区 | 国产欧美日韩网站 | 奇米激情 | 亚洲成人欧美 |