cmd

          Jetty 源碼分析

          一、 總括
          ? ???你了解Jetty 嗎,就像我們所熟知的Tomcat一樣, Jetty是一個(gè)免費(fèi)的開放源碼的100%純Java的Http服務(wù)器和Servlet容器。

          ? ???Jetty具備以下特點(diǎn):

          ? ???快速高效

          ? ???。Jetty是最快的Servlet服務(wù)器之一

          ? ???。Jetty可以處理上千個(gè)并發(fā)連接
          ? ???小巧嵌入
          ? ???。Jetty的jar只有600多K
          ? ???。可動(dòng)態(tài)嵌入到應(yīng)用程序,適合開發(fā)web2.0等應(yīng)用

          ? ???應(yīng)用廣泛

          ? ???。開源項(xiàng)目有Geronimo, JBoss, JOnAS

          ? ???。商業(yè)項(xiàng)目有IBM Tivoli, Sonic MQ and Cisco SESM等

          ? ???可到Jetty網(wǎng)站 http://jetty.mortbay.org/jetty/ 查看最新信息

          ? ???本文將通過對(duì)Jetty最新穩(wěn)定版 Jetty5.1.5RC2 源碼的研究,向讀者展示Jetty在設(shè)計(jì)方面使用的不同設(shè)計(jì)理念, 希望對(duì)廣大開發(fā)者在設(shè)計(jì)自己的系統(tǒng)時(shí)有所幫助。

          ? ???Jetty按照功能可以分為四個(gè)主個(gè)主要的部分,HttpServer,HttpContext,HttpHandler,HttpListener,詳見如下類圖:

          <圖 1-1>

          ?

          二、HttpServer及配置
          ? ???對(duì)于初次接觸Jetty的人一定會(huì)對(duì)上圖感到迷惑,其實(shí)在Jetty中HttpServer是一個(gè)服務(wù)器的核心控制類, 我們可以看到,其它的組件類都是由該類擴(kuò)展開來,HttpServer的作用就是在一系列的監(jiān)聽器類和處理器類之間搭起了一個(gè)橋梁,有效的控制著消息在系 統(tǒng)內(nèi)的傳遞,如下圖:
          <圖 1-2 >
          ? ???HttpServer職責(zé)是接受從HttpListener傳遞過來的request(請(qǐng)求),HttpServer通過對(duì)request的 Host(主機(jī))或Path(路徑)進(jìn)行匹配,然后分發(fā)給相應(yīng)的HttpContext(可以理解為一個(gè)web application)。
          ? ???這里舉個(gè)例子,假設(shè)我們現(xiàn)在要建立一個(gè)提供靜態(tài)頁面web服務(wù),頁面內(nèi)容在c:\root\下,可以通過如此配置HttpServer:
          ? ???HttpServer server = new HttpServer(); // 創(chuàng)建一個(gè)新的HttpServer
          ? ???SocketListener listener = new SocketListener(); // 創(chuàng)建一個(gè)新監(jiān)聽器
          ? ???listener.setPort(8080);// 設(shè)置監(jiān)聽端口為8080
          ? ???server.addListener(listener);// 將監(jiān)聽類注冊(cè)到server中
          ? ???HttpContext context = new HttpContext(); // 創(chuàng)建一個(gè)新HttpContext
          ? ???context.setContextPath("/app/*"); // 設(shè)置訪問路徑
          ? ???context.setResourceBase("c:/root/"); // 設(shè)置靜態(tài)資源路徑
          ? ???context.addHandler(new ResourceHandler()); // 為這個(gè)HttpContext添加一個(gè)靜態(tài)資源處理器
          ? ???server.addContext(context); // 將這個(gè)HttpContext注冊(cè)到server中
          ? ???server.start();// 最后啟動(dòng)這個(gè)server
          ? ???當(dāng)我們要建立一個(gè)提供動(dòng)態(tài)頁面web服務(wù)時(shí), 假設(shè)我們自己的 web 應(yīng)用放在Jetty目錄下的webapps下并打好包文件名為myapp.war, 可以通過如此配置HttpServer:
          ? ???Server server = new Server(); // 創(chuàng)建一個(gè)新的HttpServer
          ? ???SocketListener listener = new SocketListener();// 創(chuàng)建一個(gè)新監(jiān)聽器
          ? ???listener.setPort(8080); // 設(shè)置監(jiān)聽端口為8080
          ? ???server.addListener(listener ); // 將監(jiān)聽類注冊(cè)到server中
          ? ???server.addWebApplication("myapp","./webapps/myapp/"); // 將這個(gè)web應(yīng)用注冊(cè)到這個(gè)Server中
          ? ???server.start(); // 最后啟動(dòng)這個(gè)server
          ? ???短短數(shù)行代碼就可創(chuàng)建一個(gè)web服務(wù)器并啟動(dòng)它,這有點(diǎn)類似于我們windows中的即插即用的概念,需要什么就添加什么,把這些類以HttpServer為核心組合在一起,就可以完成強(qiáng)大的功能。
          ?
          三、Jetty Server
          ? ???1.上面我們探討了HttpServer的啟動(dòng),讀者一定還存在這樣疑問,整個(gè)Jetty服務(wù)器是怎樣啟動(dòng)的?
          ? ???首先我們可以在圖 1-1 看到左下角有一個(gè)Server類,這個(gè)類實(shí)際上繼承了HttpServer,當(dāng)啟動(dòng)Jetty服務(wù)器時(shí),具體來說,在Jetty根目錄下命令行下如輸入 java?-jar?start.jar?etc/demo.xml,注意這里有一個(gè)配置文件demo.xml做為運(yùn)行參數(shù),這個(gè)參數(shù)也可以是其它的配置 文件,也可是多個(gè)xml配置文件,其實(shí)這個(gè)配置文件好比我們使用struts時(shí)的struts-config.xml文件,將運(yùn)行Server需要用到的 組件寫在里面,比如上一節(jié)中HttpServer的配置需要的組件類都可以寫在這個(gè)配置文件中。
          ? ???2.我們自己部署到Jetty的webapps目錄下的web application,Jetty如何運(yùn)行我們自己的web application?
          ? ???首先當(dāng)我們按上述方法啟動(dòng)Jetty Server時(shí),就會(huì)調(diào)用Server類里面的main方法,這個(gè)入口方法首先會(huì)構(gòu)造一個(gè)Server類實(shí)例(其實(shí)也就構(gòu)造了一個(gè) HttpServer),創(chuàng)建實(shí)例過程中就會(huì)構(gòu)造XmlConfiguration類的對(duì)象來讀取參數(shù)配置文件,之后再由這個(gè)配置文件產(chǎn)生的 XmlConfiguration對(duì)象來配置這個(gè)Server,配置過程其實(shí)是運(yùn)用Java的反射機(jī)制調(diào)用Server的方法并傳入配置文件中所寫的參數(shù) 來向這個(gè)Server添加HttpListener,HttpContext,HttpHandler,web application(對(duì)應(yīng)我們自己部署的web應(yīng)用)。
          ? ???添加我們自己的web application過程中相應(yīng)的就會(huì)讀取我們所熟知的/WEB-INF/web.xml來創(chuàng)建一個(gè)WebApplicationContext(這個(gè) 類繼承了HttpContext)的實(shí)例,同時(shí)也會(huì)創(chuàng)建WebApplicationContext自身的ServletHandler(實(shí)現(xiàn)了 HttpHandler接口),注意到ServletHandler中包含一組ServletHolder指向?qū)嶋H的Servlet,譬如說我們?cè)? web.xml文件中配置了兩個(gè)Filter和一個(gè)Servlet,這里就會(huì)有三個(gè)ServletHolder,實(shí)際處理請(qǐng)求時(shí) ServeletHandler就會(huì)依次調(diào)用這三個(gè)ServletHolder傳入request,response處理(實(shí)際最后交給這兩個(gè) Filter和Servlet處理),這樣我們自己做好的一個(gè) web應(yīng)用就掛載到這個(gè)Server上了,可以接受客戶端相應(yīng)的request(請(qǐng)求)。
          ?
          四、運(yùn)行原理(請(qǐng)參考如下時(shí)序圖)

          <圖 1-7 >

          ? ???上圖展示了一個(gè)request的處理過程,首先HttpListener監(jiān)聽到客戶端發(fā)來的請(qǐng)求創(chuàng)建一個(gè)HttpConnection實(shí)例(封裝了 連接細(xì)節(jié),比如從Socket連接中獲取的輸入流和輸出流), HttpConnection對(duì)象構(gòu)建過程中會(huì)創(chuàng)建Jetty內(nèi)部自定義的HttpRequest和HttpResponse對(duì)象,接著 HttpListener會(huì)調(diào)用這個(gè)HttpConnection實(shí)例的handle方法, HttpConnection實(shí)例就調(diào)用HttpRequest對(duì)象的read()方法讀取信息,調(diào)用HttpServer的service方法以 HttpRequest,HttpResponse為參數(shù)傳給HttpServer,HttpServer又將HttpRequest和 HttpResponse分發(fā)給相應(yīng)的HttpCotext,HttpContext最后將HttpRequest和HttpResponse交給自身的 HttpHandler 處理,在這里HttpRequest,HttpResponse被再次封裝為ServletHttpRequest和 ServletHttpResponse,其實(shí)這兩個(gè)類實(shí)現(xiàn)了我們所熟知的HttpServletRequest和 HttpServletResponse接口。

          ?
          五、高級(jí)性能

          ? ???1.HttpHandler:

          ? ???該接口的實(shí)現(xiàn)類用于處理HttpContext分發(fā)過來的reqeust,不同的實(shí)現(xiàn)類的有不同的處理功能,這里介紹幾常用的HttpHandler實(shí)現(xiàn)類:
          ? ???ReourceHandler:用于處理靜態(tài)內(nèi)容,如以擴(kuò)展名為.html的文件

          ? ???SecurityHandler:提供基本的安全驗(yàn)證

          ? ???ForwardHandler:轉(zhuǎn)發(fā)一個(gè)request到另一個(gè)url

          ? ???ServletHandler:用于將request交由具體的Servlet類進(jìn)行處理
          ? ???2.當(dāng)你在看圖 1-2 時(shí)候會(huì)注意到HttpServer和HttpListener,HttpServer與HttpContext,HttpContext與 HttpHandler存在一對(duì)多的關(guān)系,下面就介紹一下它們之間的這種關(guān)系如何通過程序來配置.

          ? ???HttpListener & HttpServer:

          ? ???HttpListener是所有監(jiān)聽器類的接口,如圖中的SocketListener(基于傳統(tǒng)的Socket技術(shù))就實(shí)現(xiàn)了該接口,Jetty 還有其它的實(shí)現(xiàn)該接口類,如SocketChannelListener(基于NIO技術(shù))類等,HttpListener職責(zé)主要是在服務(wù)器啟動(dòng)后監(jiān)聽 相應(yīng)端口的來自客戶端請(qǐng)求并建立連接(圖 1-1 中所示用HttpConnection封裝連接細(xì)節(jié)),監(jiān)聽器可在同個(gè)IP上開啟多個(gè)端口為同一個(gè)HttpServer 進(jìn)行監(jiān)聽,所以HttpListener和HttpServer是多對(duì)一的關(guān)系,如下圖:

          <圖 1-3 >

          ? ???配置代碼:
          ? ???HttpServer server = new HttpServer();
          ? ???HttpListenrer listener1 = new SocketChanneListener();
          ? ???Listener1.setPort(8080);
          ? ?? HttpListenrer listener1 = new SocketListener();
          ? ???Listener1.setPort(8443);
          ? ???server.addListener(listener1);
          ? ???server.addListener(listener2);
          ?

          ? ???HttpContext & HttpHandler:

          ? ???HttpContext相當(dāng)于對(duì)應(yīng)客戶端請(qǐng)求的URL或某個(gè)虛擬機(jī), 其子類中包含若干個(gè)HttpHandler, 當(dāng)接受到request(請(qǐng)求)時(shí),HttpContext會(huì)依次(按某個(gè)預(yù)定的次序)把request交給這些HttpHandler處理,直到這個(gè) request被標(biāo)示處理過為止, 需要注意的是這個(gè)request可能被多個(gè)HttpHandler處理,但只能有一個(gè)HttpHandler能標(biāo)示這個(gè)request已被處理過.

          ? ???一個(gè)典型的HttpContext有用于安全處理、靜態(tài)資源處理及Servlet類的HttpHandler,如下圖:
          <圖 1-4>
          ? ???配置代碼:
          ? ???HttpContext context = new HttpContext();
          ? ???context.setContextPath(“/myapp/*”);
          ? ???HttpHandler securitHandler = new SecurityHandler();
          ? ???HttpHandler resourceHandler = new ResourceHandler();
          ? ???HttpHandler servletHandler = new ServletHandler();
          ? ???context.addHandler(securitHandler);
          ? ???context.addHandler(resourceHandler);
          ? ???context.addHandler(servletHandler);
          ?
          ? ???HttpServer & HttpContext:
          ? ???一般的HTTP服務(wù)器軟件可以同時(shí)處理多個(gè)web application,同樣一個(gè)HttpServer可以包含多個(gè)HttpContext,如下圖可以通過同一個(gè)端口的監(jiān)聽類來映射多個(gè)HttpContext:

          <圖 1-5 >

          ? ???配置代碼:
          ? ???HttpServer server = new HttpServer();
          ? ???HttpContext context1 = new HttpContext();
          ? ???context1.setContextPath(“/app1/*”);
          ? ???HttpContext context2 = new HttpContext();
          ? ???context2.setContextPath(“/app2/*”);
          ? ???server.addContext(context1);
          ?
          ? ???HttpServer & HttpLister & HttpContext:

          ? ???另外Jetty對(duì)多網(wǎng)卡(多個(gè)IP地址,不同的主機(jī)名)的服務(wù)器也提供了很好的支持,每個(gè)HttpContext都有自身的HttpServer:

          <圖 1-6 >

          ? ???配置代碼:
          ? ???HttpServer server1 = new HttpServer();
          ? ???SocketListener listener1 = new SocketListener();

          ? ???listener1.setHost(“www.app1.com”);//orListener1.setHost(“www.app2.com”)

          ? ???listener2.setPort(80);

          ? ???HttpContext context1 = new HttpContext();

          ? ???context1.setContextPath(“/”);

          ? ???server1.addListener(listener1);

          ? ???server1.addContext(context1);

          ?
          ? ???3.Jetty對(duì)高并發(fā)的支持
          <圖 1-8>
          ? ???如果多用戶請(qǐng)求服務(wù)就會(huì)涉及到多線程的管理,如圖 1-8,Jetty中主要由ThreadPool負(fù)責(zé)管理多線程,注意其中Pool.PondLife是Pool的一個(gè)內(nèi)部接口, ThreadPool.PoolThread是ThreadPool的一個(gè)內(nèi)部線程類,我們看到Pool.PondLife和Pool存在一個(gè)聚集的關(guān) 系,實(shí)際上Pool對(duì)象中存放在是一個(gè)個(gè)ThreadPool.PoolThread線程對(duì)象,當(dāng)有新用戶連接上Server時(shí),ThreadPool就 從Pool中取一個(gè)空閑的線程為當(dāng)前用戶連接服務(wù)。
          ?
          六、小結(jié)

          ? ???本文通過圖示簡(jiǎn)要介紹了Jetty整個(gè)體系架構(gòu)和主要的組件類及服務(wù)器的啟動(dòng)執(zhí)行過程,其實(shí)Jetty 通常被用來做為內(nèi)嵌的Web Server來使用,一些常見的服務(wù)器軟件,如Apache Cocoon、JBoss ,JOnAs等都會(huì)采用Jetty作為Web解決方案;另外由于Jetty在性能及穩(wěn)定性要優(yōu)于同類HTTP Server的原因,Jetty已在國(guó)外已很流行,鑒于這一點(diǎn),本文作者可以預(yù)測(cè)在不久的將來Jetty同樣也會(huì)在國(guó)內(nèi)流行開來。

          ?
          附:
          作者聯(lián)系方式:陳應(yīng)剛 dycyg@yahoo.com 熊紅陽 eastbear@126.com

          posted on 2006-04-20 20:06 靜夜思 閱讀(1350) 評(píng)論(1)  編輯  收藏 所屬分類: server

          評(píng)論

          # re: Jetty 源碼分析[未登錄] 2011-07-29 16:45 Super

          樓主有做Jetty 虛擬主機(jī)經(jīng)驗(yàn)嗎?  回復(fù)  更多評(píng)論   


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 康保县| 新建县| 沧州市| 漯河市| 邯郸县| 巴东县| 隆子县| 乌兰察布市| 榆树市| 慈溪市| 珠海市| 西畴县| 潞西市| 冕宁县| 德钦县| 保靖县| 延寿县| 法库县| 青铜峡市| 德格县| 金溪县| 沽源县| 浦县| 垦利县| 通道| 永新县| 皮山县| 宁都县| 府谷县| 呼玛县| 南丹县| 临夏市| 河津市| 广汉市| 西宁市| 黔南| 英超| 印江| 高青县| 习水县| 德阳市|