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

Tomcat啟動

系統 2454 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
分別看看如何執行:
1、執行startup.bat,調用catalina.bat進行環境變量的設置,否則通過
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類解析catalina.properties文件,
org.apache.catalina.startup.ClassLoaderFactory?的createClassLoader()方法將.jar文件url放入set,并返回StandardClassLoader
Tomcat啟動
在ini方法中會
?
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()方法會初始化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();
實例化了startup實例。
?
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)
創建行為
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)
屬性設置
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)
對象引用
Server.xml的Digester
通過Catalina.java中的 createStartDigester ()方法創建,并設置規則
?
5、?在 Catalina.java中調用start()方法中調用getServer().initialize();
接著:services[i].initialize();
接著:connectors[i].initialize();
。。。(詳見最后的代碼跟蹤)
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.
使用類 CatalinaShutdownHook實現,它繼承Thread,run中進行清理
// 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 );
}
}
?
啟動tomat代碼跟蹤
View Code
1、Bootstrap.java中的main方法,啟動tomcat;
調用init()方法初始化,并用Catalina.load(),獲取server對象,并調用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對象是怎么來的??
往回看,在load方法中,
// ?Create?and?execute?our?Digester
Digester?digester?=?createStartDigester();?中創建了規則,如下:

// ?Configure?the?actions?we?will?be?using
digester.addObjectCreate("Server",
"org.apache.catalina.core.StandardServer",
"className");?
經過反射,到類ObjectCreateRule類的begin方法中
// ?Instantiate?the?new?object?and?push?it?on?the?context?stack
Class?clazz?=?digester.getClassLoader().loadClass(realClassName);
Object?instance?=?clazz.newInstance();?
利用反射創建對象,其中:realClassName?=org.apache.catalina.core.StandardServer
在類org.apache.catalina.core.StandardServer構造方法中調用ServerFactory.setServer( this );?
實現單例Server對象創建。

2、?
getServer().initialize();方法中調用service的ini方法:其中services為解析server.xml
// ?Initialize?our?defined?Services
???????? for ?( int ?i?=?0;?i?<?services.length;?i++)?{
????????????services[i].initialize();
????????}
在?initialize
執行connector的ini方法
for ?( int ?i?=?0;?i?<?connectors.length;?i++)?{
try ?{
connectors[i].initialize();?
connectors的來源也是server.xml配置文件,默認配置:
?<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、接下來分析connector,默認使用protocol="HTTP/1.1"協議
? // ?Initializa?adapter
????????adapter?=? new ?CoyoteAdapter( this );
????????protocolHandler.setAdapter(adapter);
生成CoyoteAdapter,并設置,調用ini方法
protocolHandler.init();
4、接下來調用
endpoint.init();?
我們了看看JIoEndpoint?類是做神馬的?
?*?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.
此類實現了簡單的server模型:一個監聽線程,接受socket并且為每一個到來的連接創建一個worker線程
真正干活的是這個!后面我們會分析它的start方法
接下來初始化其他conector

5、當以上初始化完成后,調用Catalina.start()方法,接著啟動server.start()方法:
((Lifecycle)?getServer()).start();?
接著調用service.start()方法
接下來是一系列的container的start,后續在分析(會部署所有的項目)

在service.start()中,調用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、直到調用protocolHandler.start();?接下來: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、此方法會創建一個線程(acceptorThreadCount默認=1),此線程Acceptor對象,看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并分配處理,最終關閉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 ;
}?
其中getWorkerThread()返回的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對象的run方法:
public ? void ?run()?{
// ?Process?requests?until?we?receive?a?shutdown?signal
while ?(running)?{
// ?Wait?for?the?next?socket?to?be?assigned
// 當沒有請求時,此線程一直處于等待狀態,直到被喚醒,也就是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 );
}
}?
最終執行在handler.process,我們之前分析的Http11Protocol類中的內部類實現了Handler,如下:
protected ? static ? class ?Http11ConnectionHandler? implements ?Handler?

對于我們的protocol="HTTP/1.1"?connector來說,此類執行了process方法,處理socket
調用processor.process()方法處理http請求,包括servlet、靜態資源等
/**
*?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;
}
}
// 以下設置了超時,如果沒有超時,那依然使用同一個socket請求資源,此時不用重建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啟動


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

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

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。。?/p>

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产在线一区视频 | 成人在线黄色 | 国产欧美一区二区三区视频 | 精品久久久久久亚洲 | 91一级片| 欧美日韩国产一区三区 | 国产无套免费网站 | 亚洲欧美二区三区久本道 | 国产精品91av | 九九视频在线看精品 | 久久国产热这里只有精品8 久久国产三级 | 精品美女 | 欧美v亚洲v国产v | 日本三级强在线观看 | 欧美理论片在线观看 | 国产激情一区二区三区成人91 | 久久亚洲欧美成人精品 | 国产一区二区精品久久岳 | 4hu在线观看| 久久精品资源站 | 亚洲夜色 | 欧美图片一区二区三区 | 国产成人黄色在线观看 | 久久综合中文字幕一区二区三区 | 人人澡人人澡人人看欧美 | 精品日本一区二区 | 色综合久久综合 | 精品久久久久久久一区二区手机版 | 中文字幕伦理聚合第一页 | 九九热在线免费观看 | 欧美久久影院 | 日韩毛片网| 97视频精品| 久久精品av77777 | 四虎成人影院网址 | 亚洲精品国产啊女成拍色拍 | 在线观看成人小视频 | 一本久道久久综合狠狠爱 | 天天做人人爱夜夜爽2020 | 国产成综合| 日本免费不卡视频一区二区三区 |