版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
Tomcat和Jetty中用到了大量的高性能、高并發(fā)的設(shè)計,我總結(jié)了幾點(diǎn):I/O和線程模I/O/O模型的本質(zhì)就是為了緩解CPU和外設(shè)之間的速度差。當(dāng)線程發(fā)起I/O請求時,比如讀寫網(wǎng)絡(luò)數(shù)據(jù),網(wǎng)卡數(shù)據(jù)還沒準(zhǔn)備好,這個線程就會被阻塞,讓出CPU,也就是說發(fā)生了線程切換。而線程切換是無用功,并且線程被阻塞后,它持有內(nèi)存資源并沒有釋放,阻塞的線程越多,消耗的內(nèi)存就越大,因此I/O模型的目標(biāo)就是盡量減少線程阻塞。Tomcat和Jety都已經(jīng)拋棄了傳統(tǒng)的同步阻塞I/O,采用了非阻塞/O或者異步/O,目的是業(yè)務(wù)線程不需要阻塞在/O等待上。除了I/O型,線程模型也是影響性能和并發(fā)的關(guān)鍵點(diǎn)。TomcatJetty體處理原則連接請求由專門的Acceptor線程組處理I/O偵測也由專門的Selector線程組來處理具體的協(xié)議解析和業(yè)務(wù)處理可能交給線程池(Tomcat),或者交給Selector程來處將這些事情分開的好處是解耦,并且可以根據(jù)實(shí)際情況合理設(shè)置各部分的線程數(shù)。這里請你注意,線程數(shù)并不是越多越好,因?yàn)镃PU核的個數(shù)有限,線程太多也處理不過來,會導(dǎo)致大量的線程上下文切換。其實(shí)系統(tǒng)調(diào)用是非常耗資源的一個過程,涉及CPU從用戶態(tài)切換到內(nèi)核態(tài)的過程,因此我們在編寫程序的時候要有意識盡量避免系統(tǒng)調(diào)用。比如在TomcatJetty,系統(tǒng)調(diào)用最多的就是網(wǎng)絡(luò)通信操作了,一個Channel上的write就是系統(tǒng)調(diào)用,為了降低系統(tǒng)調(diào)用的次數(shù),最直接的方法就是使用緩沖,當(dāng)輸出數(shù)據(jù)達(dá)到一定的大小才flush緩沖區(qū)。Tomcat和Jetty的Channel都帶有輸入輸出緩沖區(qū)。還有值得一提的是,TomcatJettyHTTP議數(shù)據(jù)時采取了延遲解析的策略,HTTP的請求體(HTTPBody)直到用的時候才解析。也就是說,當(dāng)Tomcat調(diào)用Servlet的service方法時,只是了和解析了HTTP請求頭,并沒有HTTP請求直到你的Web應(yīng)用序調(diào)用了ServletRequest對象的getInputStream方法或者getParameter方法時,Tomcat才會去和解析HTTP請求體中的數(shù)據(jù);這意味著如果你的應(yīng)用序沒有調(diào)用上面那兩個方法,HTTP請求體的數(shù)據(jù)就不會被和解析,這樣就省掉了一次I/O系統(tǒng)調(diào)用。關(guān)于池化和零拷貝,我在專欄前面已經(jīng)詳細(xì)講了它們的原理,你可以回過頭看看專欄第20期和第16期。其實(shí)池化的本質(zhì)就是用內(nèi)存換CPU;而零拷貝就是不做無用功,減少資源我們知道并發(fā)的過中為了同步多個線對共享變量的,需要加鎖來實(shí)現(xiàn)。而鎖的開銷要有意識的盡量避免鎖的使用,比如可以使用原子類CAS或者并發(fā)集合來代替。如果萬不得已需要用到鎖,也要盡量縮小鎖的范圍和鎖的強(qiáng)度。接下來我們來看看Tomcat和Jetty縮小鎖的范縮小鎖的范圍,其實(shí)就是不直接在方法上 synchronized,而是使用細(xì)粒度的對象鎖代1protectedvoidstartInternal()throwsLifecycleException2 4//鎖engine成員if(engine!=null)synchronized(engine) //鎖executors成員synchronized(executors)for(Executorexecutor:executors) //鎖connectors成員變synchronized(connectorsLock)for(Connectorconnector:connectors)//Ifithasalreadyfailed,don'ttryandstartif(connector.getState()!=LifecycleState.FAILED) 30比如上面的代碼是Tomcat的StandardService組件的啟動方法,這個啟動方法要啟動三組件:engine、executors和connectors。它沒有直接在方法上加鎖,而是用了三把細(xì)粒度的鎖,來分別用來鎖三個成員變量。如果直接在方法上加synchronized,多個線執(zhí)行到這個方法時需要排隊(duì);而在對象級別上加synchronized,多個線可以并行執(zhí)行這用原子變量和CAS取代下面的代碼是Jetty線池的啟動方法,它的主要功能就是根據(jù)傳入的參數(shù)啟動相應(yīng)個數(shù)的代privatebooleanstartThreads(int{while(threadsToStart>0&&{//獲取當(dāng)前已經(jīng)啟動的線數(shù),如果已經(jīng)夠了就不需要啟動intthreads=if(threads>=return9//用CAS方法將線數(shù)加一,請注意執(zhí)行失敗走continue,繼續(xù)嘗if pareAndSet(threads,threads+booleanstarted={Threadthread=thread.setName(_name+"-"+_threads.add(thread);//_threads并發(fā)集_lastShrink.set(System.nanoTime());//_lastShrink是原子變started=-- //如果最終線啟動失敗,還需要把線數(shù)減 if return35你可以看到整個函數(shù)的實(shí)現(xiàn)是一個while循環(huán),并且是無鎖的。_threadsStarted表示當(dāng)前線池已經(jīng)啟動了多少個線,它是一個原子變量AtomicInteger,首先通過它的get方法拿到值,如果線數(shù)已經(jīng)達(dá)到最大值,直接返回。否則嘗試用CAS操作將eStd的值加一,如果成功了意味著沒有其他線在改這個值,當(dāng)前線可以繼續(xù)往下執(zhí)行;否則走oie分支,也就是繼續(xù)重試,直到成功為止。在這里當(dāng)然你并發(fā)容器的使CopyOnWriteArrayList適用于讀多寫少的場景,比如Tomcat用它來“存放”器,這是因?yàn)槠饕话阍诔跏蓟^中確定后就基本不會改變,當(dāng)觸發(fā)時需要遍歷這個器列表,所以這個場景符合讀多寫少的特征。代1 classLifecycleBaseimplementsLifecycle23 privatefinalList<LifecycleListener>lifecycleListeners=35 7volatile關(guān)鍵字的使再拿Tomcat中的LifecycleBase作為例子,它里面的生命狀態(tài)就是用volatile關(guān)鍵字修飾的。volatile的目的是為了保證一個線修改了變量,另一個線能夠讀到這種變化。對于生命狀態(tài)來說,需要在各個線中保持是的值,因此采用了volatile修飾。代1 classLifecycleBaseimplementsLifecycle2//當(dāng)前組件的生命狀態(tài),用volatile修privatevolatileLifecycleStatestate=56高性能序能夠高效的利用系統(tǒng)資源,首先就是減少資源浪費(fèi),比如要減少線的阻塞,因?yàn)樽枞麜?dǎo)致資源閑置和線上下文切換,Tomcat和Jetty通過合理的I/O模型和線模另外系統(tǒng)調(diào)用會導(dǎo)致用戶態(tài)和內(nèi)核態(tài)切換的過,Tomcat和Jetty通過緩存和延遲解析盡 取另一種資源,比如Tomcat和Jetty中使用的對象池技術(shù),就是用內(nèi)存換取CPU,將數(shù)據(jù)壓縮后再傳輸就是用CPU換網(wǎng)絡(luò)。此我們在實(shí)際編過中要盡量避免使用鎖,比如可以用原子變量和CAS操作來代替鎖。如果實(shí)在避免不了用鎖,也要盡量減少鎖的范圍和強(qiáng)度,比如可以用細(xì)粒度的對象鎖或者強(qiáng)度的讀寫鎖。Tomcat和Jetty的代碼也很好的實(shí)踐了這一理念今天的文章提到我們要有意識盡量避免系統(tǒng)調(diào)用,那你知道有哪些JavaAPI致系統(tǒng)調(diào)不知道今天的內(nèi)容你消化得如何?如果還有疑問,請大膽的在留言區(qū)提問,也歡迎你的課后思考和心得記錄下來,與我和其他同學(xué)一起討論。如果你覺得今天有所收獲,歡迎你把它給你的朋友。?
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度漁船租賃與漁業(yè)政策研究服務(wù)合同4篇
- 2025年度租賃房屋租賃合同稅費(fèi)繳納指南4篇
- 2025年文化創(chuàng)意產(chǎn)業(yè)合伙人合作協(xié)議書模板3篇
- 2025年度專業(yè)賽車場車手雇傭合同3篇
- 2025年物產(chǎn)中大金屬集團(tuán)有限公司招聘筆試參考題庫含答案解析
- 《廉政風(fēng)險防控培訓(xùn)課件》
- 2025年貴州遵義金控集團(tuán)有限公司招聘筆試參考題庫含答案解析
- 二零二五年度米面油食品安全風(fēng)險評估與監(jiān)控合同4篇
- 2025年消防給排水系統(tǒng)管網(wǎng)優(yōu)化設(shè)計施工合同2篇
- 2025年度重型工業(yè)門采購安裝合同范本4篇
- 中國華能集團(tuán)公司風(fēng)力發(fā)電場運(yùn)行導(dǎo)則(馬晉輝20231.1.13)
- 中考語文非連續(xù)性文本閱讀10篇專項(xiàng)練習(xí)及答案
- 2022-2023學(xué)年度六年級數(shù)學(xué)(上冊)寒假作業(yè)【每日一練】
- 法人不承擔(dān)責(zé)任協(xié)議書(3篇)
- 電工工具報價單
- 反歧視程序文件
- 油氣藏類型、典型的相圖特征和識別實(shí)例
- 流體靜力學(xué)課件
- 顧客忠誠度論文
- 實(shí)驗(yàn)室安全檢查自查表
- 證券公司績效考核管理辦法
評論
0/150
提交評論