日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

servlet解析演进(2-1)

發(fā)布時(shí)間:2025/3/21 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 servlet解析演进(2-1) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>

上文說了簡(jiǎn)單的servlet解析過程。實(shí)際上,tomcat在解析servlet的 時(shí)候是吧連接器定位為滿足以下三個(gè)條件:

1、必須事先接口org.apache.catalina.Connector

2. 必須創(chuàng)建請(qǐng)求對(duì)象,該請(qǐng)求對(duì)象的類必須實(shí)現(xiàn)接口org.apache.catalina.Request。?

3. 必須創(chuàng)建響應(yīng)對(duì)象,該響應(yīng)對(duì)象的類必須實(shí)現(xiàn)接口org.apache.catalina.Response。

tomcat的連接器有很多種類:Coyote、mode_jk、mod_jk2和mode_webapp等。

來自瀏覽器的請(qǐng)求類型是有區(qū)別的http/0.9 http/1.0 http/1.1.

http/1.1又叫做持久連接,上文中一次請(qǐng)求處理完畢就關(guān)閉了socket。然而,在現(xiàn)實(shí)的頁面請(qǐng)求中需要加載多種資源(js、img css)。如果每次請(qǐng)求都開啟關(guān)閉連接那將是非常耗時(shí)的事情。http/1.1能夠讓瀏覽器和服務(wù)器保持一種持久化的連接,快速的相應(yīng)請(qǐng)求。這樣,請(qǐng)求的形式就和之前不同,他是一塊編碼的形式,并使用特殊頭部transfer-encoding感知發(fā)送過來的數(shù)據(jù)信息。同時(shí),如果瀏覽器有較大數(shù)據(jù)請(qǐng)求之前發(fā)送頭部信息Expect: 100-continue頭部到服務(wù)器,等待服務(wù)器的相應(yīng)。如果服務(wù)器響應(yīng)數(shù)據(jù)能夠接受大數(shù)據(jù)請(qǐng)求,才真正的發(fā)送數(shù)據(jù),避免先發(fā)送大數(shù)據(jù)而遭服務(wù)器拒絕而浪費(fèi)了傳輸數(shù)據(jù)的帶寬資源。

本文重點(diǎn)說明連接器的演進(jìn)。


連接器的演進(jìn)主要包括了以下幾個(gè)方面:

1、處理請(qǐng)求不再只是一次處理一次請(qǐng)求,而是生成Processor池,用于處理多個(gè)連接請(qǐng)求。同事Processor處理器也不再是每次請(qǐng)求新生成實(shí)例處理請(qǐng)求,而是從池子中獲取到一個(gè)處理器去完成請(qǐng)求。同時(shí),實(shí)現(xiàn)了Processor處理方法異步化,讓連接器線程能夠繼續(xù)接受其他的請(qǐng)求。

2、處理器線程和連接器線程通過wait() notifyAll()的方式進(jìn)行線程間通信。

3、Processor處理器中,增加了標(biāo)識(shí)符,KeepAlive、stopped和http11,為處理器在處理的過程中設(shè)定“路口”,及時(shí)相應(yīng)請(qǐng)求的變化。

4、socket緩沖區(qū)大小不再是像前文一樣設(shè)置為定值,而是通過獲取連接器傳遞過來的參數(shù)設(shè)置緩沖區(qū)大小。

5、處理器的職能更加的豐富。

連接處理 ?parseConnection,針對(duì)不同的連接協(xié)議做不同的處理。


解析請(qǐng)求 parseRequest


解析頭部 parseHeaders?


6、去掉了靜態(tài)處理器,暫時(shí)無法接受靜態(tài)資源請(qǐng)求。

------------------------

1、連接器啟動(dòng):

HttpConnector?connector?=?new?HttpConnector(); SimpleContainer?container?=?new?SimpleContainer(); connector.setContainer(container); try?{ //初始化連接器,打開socket連接 connector.initialize(); //開啟監(jiān)聽,開啟連接器線程、將處理器線程啟動(dòng)并入隊(duì)列。 connector.start();System.in.read(); } catch?(Exception?e)?{e.printStackTrace(); }

1.1 初始化連接、打開socket連接(使用工廠模式)

public?void?initialize() throws?LifecycleException?{ //初始化標(biāo)志,不能重復(fù)初始化 if?(initialized) throw?new?LifecycleException?( sm.getString("httpConnector.alreadyInitialized")); this.initialized=true;Exception?eRethrow?=?null; //?Establish?a?server?socket?on?the?specified?port try?{ //打開socket連接 serverSocket?=?open();}?catch?(IOException?ioe)?{log("httpConnector,?io?problem:?",?ioe);eRethrow?=?ioe;}?catch?(KeyStoreException?kse)?{log("httpConnector,?keystore?problem:?",?kse);eRethrow?=?kse;}?catch?(NoSuchAlgorithmException?nsae)?{log("httpConnector,?keystore?algorithm?problem:?",?nsae);eRethrow?=?nsae;}?catch?(CertificateException?ce)?{log("httpConnector,?certificate?problem:?",?ce);eRethrow?=?ce;}?catch?(UnrecoverableKeyException?uke)?{log("httpConnector,?unrecoverable?key:?",?uke);eRethrow?=?uke;}?catch?(KeyManagementException?kme)?{log("httpConnector,?key?management?problem:?",?kme);eRethrow?=?kme;} if?(?eRethrow?!=?null?) throw?new?LifecycleException(threadName?+?".open",?eRethrow); } private?ServerSocket?open() throws?IOException,?KeyStoreException,?NoSuchAlgorithmException,CertificateException,?UnrecoverableKeyException,KeyManagementException { //?Acquire?the?server?socket?factory?for?this?Connector//獲得服務(wù)器socket工廠實(shí)例 ServerSocketFactory?factory?=?getFactory(); //?If?no?address?is?specified,?open?a?connection?on?all?addresses//如果沒有指定地址,在所有地址上打開一個(gè)連接 if?(address?==?null)?{log(sm.getString("httpConnector.allAddresses")); try?{ return?(factory.createSocket(port,?acceptCount));}?catch?(BindException?be)?{ throw?new?BindException(be.getMessage()?+?":"?+?port);}}? //在指定地址上打開一個(gè)連接 try?{InetAddress?is?=?InetAddress.getByName(address);log(sm.getString("httpConnector.anAddress",?address)); try?{ return?(factory.createSocket(port,?acceptCount,?is));}?catch?(BindException?be)?{ throw?new?BindException(be.getMessage()?+?":"?+?address?+ ":"?+?port);}}?catch?(Exception?e)?{log(sm.getString("httpConnector.noAddress",?address)); try?{ return?(factory.createSocket(port,?acceptCount));}?catch?(BindException?be)?{ throw?new?BindException(be.getMessage()?+?":"?+?port);}} }

1.2、開啟監(jiān)聽,開啟連接器線程、將處理器線程啟動(dòng)并入隊(duì)列。

//為連接器綁定指定數(shù)量的處理器 public?void?start()?throws?LifecycleException?{???? //判斷該線程的connect開啟狀態(tài),避免重復(fù)開啟 if?(started) throw?new?LifecycleException(sm.getString("httpConnector.alreadyStarted")); threadName?=?"HttpConnector["?+?port?+?"]"; //打開監(jiān)聽 lifecycle.fireLifecycleEvent(START_EVENT,?null); started?=?true; //?Start?our?background?thread//開啟一個(gè)后臺(tái)連接器線程 threadStart(); //創(chuàng)建處理器,并調(diào)用recyle方法將其放置到棧隊(duì)列中 while?(curProcessors?<?minProcessors)?{ if?((maxProcessors?>?0)?&&?(curProcessors?>=?maxProcessors)) break;HttpProcessor?processor?=?newProcessor();recycle(processor);} }

2、連接器、容器之間的協(xié)作關(guān)系


2.1 容器派發(fā)socket到處理器線程

public?void?run()?{ //?Loop?until?we?receive?a?shutdown?command//開啟循環(huán),知道我們獲得了結(jié)束命令 while?(!stopped)?{ //?Accept?the?next?incoming?connection?from?the?server?socket Socket?socket?=?null; try?{//獲得socket請(qǐng)求 socket?=?serverSocket.accept();//??設(shè)置超時(shí)時(shí)間 if?(connectionTimeout?>?0)socket.setSoTimeout(connectionTimeout); //設(shè)置tcp?nodelay屬性 socket.setTcpNoDelay(tcpNoDelay);}?catch?(AccessControlException?ace)?{ //拋出連接安全錯(cuò)誤信息 log("socket?accept?security?exception",?ace); continue;}?catch?(IOException?e)?{ try?{ //?If?reopening?fails,?exit//如果再次開啟失敗,退出 synchronized?(threadSync)?{ if?(started?&&?!stopped)log("accept?error:?",?e); if?(!stopped)?{???????????????? //??關(guān)閉異常連接 serverSocket.close();?????????????//???重新開啟異常連接? serverSocket?=?open();}} //??異常處理,包括不限于秘鑰等錯(cuò)誤請(qǐng)求 }?catch?(Exception?ioe)?{log("socket?reopen,?io?problem:?",?ioe); break;} continue;}???//判斷處理器棧是否有可用處理器,沒有按規(guī)則生成,有則獲取棧中處理器 HttpProcessor?processor?=?createProcessor(); //獲取處理器為空,可能情況是請(qǐng)求數(shù)量過多,超過了承受的最大處理器個(gè)數(shù) if?(processor?==?null)?{ try?{log(sm.getString("httpConnector.noProcessor"));socket.close();}?catch?(IOException?e)?{;} continue;} //派發(fā)socket到處理器 processor.assign(socket); //?The?processor?will?recycle?itself?when?it?finishes } //獲取到了結(jié)束命令,通知其他線程 synchronized?(threadSync)?{ threadSync.notifyAll();} }

2.2處理器接收到派發(fā)socket

synchronized?void?assign(Socket?socket)?{ //?d等待該處理器的其它socket處理執(zhí)行完畢 while?(available)?{ try?{wait();}?catch?(InterruptedException?e)?{}} //?Store?the?newly?available?Socket?and?notify?our?thread//將新獲取的socket放置到處理器中,并發(fā)送線程通知 this.socket?=?socket; available?=?true;notifyAll(); if?((debug?>=?1)?&&?(socket?!=?null))log("?An?incoming?request?is?being?assigned"); }

2.3 ?處理器接收到了socket請(qǐng)求,準(zhǔn)備處理

public?void?run()?{ //?Process?requests?until?we?receive?a?shutdown?signal while?(!stopped)?{ //?Wait?for?the?next?socket?to?be?assigned//等待連接器的socket請(qǐng)求 Socket?socket?=?await(); if?(socket?==?null) continue; //?Process?the?request?from?this?socket try?{ //處理socket請(qǐng)求 process(socket);}?catch?(Throwable?t)?{log("process.invoke",?t);} //?Finish?up?this?request//處理完畢,將該processor線程歸還給Stack?processors?用來處理接下來的socket請(qǐng)求 connector.recycle(this);} //?Tell?threadStop()?we?have?shut?ourselves?down?successfully synchronized?(threadSync)?{ //該處理器線程退出,通知其他processor threadSync.notifyAll();} }

未完待續(xù)

轉(zhuǎn)載于:https://my.oschina.net/zjItLife/blog/608576

總結(jié)

以上是生活随笔為你收集整理的servlet解析演进(2-1)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。