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
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.
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

在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
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(),
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 ;
}
調(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 ;
}
?
更多文章、技術(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ì)您有幫助就好】元
