日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Jetty 服務(wù)器架構(gòu)分析(中)

 java學(xué)習(xí)278 2012-03-17

Jetty 服務(wù)器架構(gòu)分析(中)

分類: Web Web Server Java Architecture 1782人閱讀 評(píng)論(3) 收藏 舉報(bào)

    接上一篇,說到XmlConfiguration ,XmlConfiguration 利用自己實(shí)現(xiàn)的 IOC 組裝 Server 的全過程如下圖所示:

 

 
 

這里可以看到 3 個(gè)關(guān)鍵的配置文件, jetty.xml 、 jetty-deploy.xml 、以及 contexts/xxx.xml

l  Jetty.xml 文件中定義了入口類 Server, 以及其所需要的線程池、 Connector 、 Handler 。

l  Jetty-deploy.xml 中則定義了部署 web 應(yīng)用用到部署工具,在其中指定了部署 web 應(yīng)用的兩種方式,類似于 tomcat, 如果采用 webappProvider ,則表示將 web 應(yīng)用放在 webapp下即可生效,如果采用 ContextProvider ,則需要定義 Contexts 目錄所在位置,只要在該目錄下放置任何應(yīng)用的 context 配置文件就可以生效。

l  Xxx.xml 這是一個(gè)用戶自定義文件,表示采用 ContextProvider 時(shí),在其中定義一個(gè)WebAppContext  handler, 它指定了我們應(yīng)用所在的位置,便于加載。

 

XmlConfiguration 解析裝配完畢之后,就開始啟動(dòng)服務(wù), Jetty 的啟動(dòng)是從 Server 開始的,我們來看一下服務(wù)器真正的啟動(dòng)過程。

 

 
 

 

 

 

 

 

從上圖中我們能大概看出服務(wù)器啟動(dòng)過程,先是由用戶設(shè)置好需要的核心組件,然后調(diào)用 Server.start() 開始啟動(dòng)服務(wù),其中會(huì)首先啟動(dòng) handler 處理器,之后啟動(dòng)用戶自定義組件,這個(gè)自定義組件需要實(shí)現(xiàn) LifeCyle 接口,最后才啟動(dòng) Connector 接受請(qǐng)求??梢韵氲剑P(guān)閉過程恰好是反過來,首先關(guān)閉接受請(qǐng)求的 connector ,然后再關(guān)閉用戶自定義組件,最后關(guān)閉 handler.

         我們?cè)賮碓敿?xì)看一下 Server 源代碼的核心實(shí)現(xiàn)過程,當(dāng)調(diào)用 start 方法時(shí),其實(shí)是調(diào)用其祖先類 AbstractLifeCycle 中方法,該方法在這里有一個(gè)模板實(shí)現(xiàn),如下:

  1. public final void start() throws Exception  
  2.    {  
  3.        synchronized (_lock)  
  4.        {  
  5.            try  
  6.            {  
  7.                if (_state == __STARTED || _state == __STARTING)  
  8.                    return;  
  9.                setStarting();  
  10.                doStart();  
  11.                setStarted();  
  12.            }  
  13.            catch (Exception e)  
  14.            {  
  15.                setFailed(e);  
  16.                throw e;  
  17.            }  
  18.            catch (Error e)  
  19.            {  
  20.                setFailed(e);  
  21.                throw e;  
  22.            }  
  23.        }  

 

  • Connector 啟動(dòng)過程

 

看下 Connector 的詳細(xì)啟動(dòng)過程: (  NIO 為例 )

 
 

 

NIOConnector 啟動(dòng)過程中,先創(chuàng)建了多個(gè) SelectSet 對(duì)象,每個(gè) SelectSet 負(fù)責(zé)一個(gè) NIO  Selector ,專門用于監(jiān)聽 read 事件 ( 這里利用的多線程 Reactor 模式, http://gee.cs./dl/cpjslides/nio.pdf ) ,當(dāng)然這里僅僅是創(chuàng)建了對(duì)象,并沒有啟動(dòng),后面會(huì)提到。

SelectorManager 

 

 

然后再調(diào)用 open 創(chuàng)建了一個(gè) blocking 的阻塞 channel ,專門用于接受用戶的新連接,我們看下:

 

  1. public void open() throws IOException  
  2.    {  
  3.        synchronized(this)  
  4.        {  
  5.            if (_acceptChannel == null)  
  6.            {  
  7.                // Create a new server socket  
  8.                _acceptChannel = ServerSocketChannel.open();  
  9.                // Set to blocking mode  
  10.                _acceptChannel.configureBlocking(true);  
  11.                // Bind the server socket to the local host and port  
  12.                _acceptChannel.socket().setReuseAddress(getReuseAddress());  
  13.                InetSocketAddress addr = getHost()==null?new InetSocketAddress(getPort()):new InetSocketAddress(getHost(),getPort());  
  14.          _acceptChannel.socket().bind(addr,getAcceptQueueSize());  
  15.                _localPort=_acceptChannel.socket().getLocalPort();  
  16.                if (_localPort<=0)  
  17.                    throw new IOException("Server channel not bound");  
  18.            }  
  19.        }  

 

隨后從線程池中分配了 N 個(gè) ( 可以在配置文件中配置 ) 線程用于啟動(dòng) SelectSet 監(jiān)聽 read 事件。

 

 

 

 

 

 

 

 

  1. synchronized (this)  
  2.         {  
  3.             _acceptorThread = new Thread[getAcceptors()];  
  4.             for (int i = 0; i < _acceptorThread.length; i++)  
  5.                 _threadPool.dispatch(new Acceptor(i));  
  6.             if (_threadPool.isLowOnThreads())  
  7.                 Log.warn("insufficient threads configured for {}",this);  
  8.         }  

 

 
 

最后再分配 1 個(gè)線程用于 accept 用戶的新連接,新連接來之后,會(huì)將其設(shè)置為 nonblocking 模式,之后就將其 Register給某個(gè) SelectSet 去監(jiān)聽 read 事件,然后又返回來繼續(xù)監(jiān)聽新連接:

 

  1. _manager.dispatch(new Runnable()  
  2.         {  
  3.             public void run()  
  4.             {  
  5.                 final ServerSocketChannel server=_acceptChannel;  
  6.                 while (isRunning() && _acceptChannel==server && server.isOpen())  
  7.                 {  
  8.                     try  
  9.                     {  
  10.                         SocketChannel channel = server.accept();  
  11.                         channel.configureBlocking(false);  
  12.                         Socket socket = channel.socket();  
  13.                         configure(socket);  
  14.                         _manager.register(channel);  
  15.                     }  
  16.                     catch(IOException e)  
  17.                     {  
  18.                         Log.ignore(e);  
  19.                     }  
  20.                 }  
  21.             }  
  22.         });  

 

 

 

  • Handler 啟動(dòng)過程

 

 
 

Jetty 將所有的真正處理請(qǐng)求的動(dòng)作都抽象成了 Handler ,因此做事情的組件都是實(shí)現(xiàn)了這個(gè)接口的,包括上圖所示的 WebAppContext 等等,需要做什么樣的工作,那么就添加什么樣的 Handler ,這里 SessionHandler 不是必須的,但是默認(rèn)是創(chuàng)建好的。 ServletHandler 主要負(fù)責(zé)處理 web 應(yīng)用的 Servlet 、 Filter 等工作,最后將請(qǐng)求直接交給 Servlet 、 Filter 都是在這里完成。

   這里展示的 Handler 的啟動(dòng)過程其實(shí)是在準(zhǔn)備 web 應(yīng)用環(huán)境,例如解析 web 應(yīng)用的web.xml 等等工作,做好一切準(zhǔn)備工作。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多