WEB服務(wù)器如何管理及優(yōu)化內(nèi)存谍咆?

第三方文檔

本文參考鏈接窃肠,感謝作者

節(jié)選自上文鏈接的思路

  1. Ngnix+PHP-FPM的工作方式包个,似乎是最節(jié)省系統(tǒng)資源的web系統(tǒng)工作方式。
  2. 當然冤留,具體的技術(shù)選型更多的應(yīng)該參考自己想買的業(yè)務(wù)需求碧囊。

一 原因:越來越多的并發(fā)連接數(shù)

  1. 頁面的元素增多,交互復雜
  2. 主流瀏覽器的連接數(shù)在增加

二 輔助方案:通過WEB前端優(yōu)化纤怒,降低服務(wù)器的壓力

  1. 減少web請求
  2. 減輕web請求
  3. 合并頁面請求

三 推薦方案:節(jié)約web服務(wù)器的內(nèi)存

  1. prefork MPM(Apache服務(wù)器多道處理器模塊),多進程工作模式:
    1. 主進程生成后糯而,他先完成初始化的工作,通過fork的方式預(yù)先產(chǎn)生一批子進程(子進程復制父進程的內(nèi)存空間泊窘,不需要再做初始化的工作)
    2. 多進程的好處:進程之間的內(nèi)存數(shù)據(jù)是互不干擾的熄驼。
    3. 優(yōu)點:成熟穩(wěn)定,兼容新老版本州既,不用擔心線程安全的問題
    4. 缺點:不適合高并發(fā)的業(yè)務(wù)場景谜洽,一個服務(wù)進程占很多內(nèi)存
  2. worker MPM, 多線程和多進程的混合模式
    1. 和prework一樣,也預(yù)先fork了幾個子進程(數(shù)量少)吴叶,然后每個子進程創(chuàng)建幾個線程(包含一個監(jiān)聽線程)阐虚。每個請求過來,會交給一個線程來服務(wù)蚌卤。(線程比進程輕量級实束,所以內(nèi)存占用更少)。
    2. 注意:并沒有解決“keep-alive”長連接的問題逊彭,只是把對象編程了更輕量級的線程
    3. 疑問:既然多線程輕量級咸灿,為什么不完全采用多線程的方式呢?因為多進程能確保程序的穩(wěn)定性侮叮,如果采用單進程多線程的方式避矢,有一個線程掛了,那么該進程下的其他線程也掛了,會導致全軍覆沒审胸。
    4. 優(yōu)點:更優(yōu)秀的內(nèi)存管理亥宿,高并發(fā)場景下表現(xiàn)更優(yōu)秀。
    5. 缺點:需要考慮線程安全問題砂沛,需要引入鎖烫扼,加大cpu的消耗。
  3. event MPM
    1. 和worker的方式很像碍庵,最大的差別在于解決了“keep-alive”場景下映企,長期被占用的線程資源問題。
    2. 注意:event MPM遇到不兼容的模塊時會失效静浴,將回退到worker模式堰氓,一個工作線程處理一個請求。
    3. Apache的3種模式中马绝,event MPM是最節(jié)約內(nèi)存的豆赏。(需要Linux系統(tǒng)對Epoll的支持才能啟用)
  4. 使用輕量級的Ngnix作為web服務(wù)器
    1. Ngnix本身就是一個輕量級的web服務(wù)器,天生蘿莉富稻,比Apache要輕量掷邦。
    2. Ngnix通過一個進程來服務(wù)N個鏈接,采用的方式不同于Apache的方式椭赋。
  5. sendfile節(jié)約內(nèi)存(這個概念非常重要)
    1. sendfile可以減少數(shù)據(jù)到“用戶態(tài)內(nèi)存空間”(用戶緩存區(qū))的拷貝抚岗,進而減少對內(nèi)存的占用。
    2. 為了更好的理解上面所說的原理哪怔。筆者先引入下面的概念:內(nèi)核態(tài)和用戶態(tài)的區(qū)別宣蔚,內(nèi)核態(tài)的優(yōu)先級高Ring0,而用戶態(tài)(運行態(tài))的優(yōu)先級低Ring3;并且當執(zhí)行用戶程序是突然中斷认境,運行狀態(tài)會從“用戶態(tài)”切換到“內(nèi)核態(tài)”胚委。
    3. 一般情況下,用戶態(tài)(程序所在的內(nèi)存空間)不能直接操作(讀寫等)各種設(shè)備(磁盤叉信,網(wǎng)絡(luò)亩冬,終端等)的。需要使用內(nèi)核作為中間人來完成對設(shè)備的操作硼身。
    4. 來吃個栗子(例子)吧:以最簡單的磁盤讀寫為例硅急,從磁盤A讀取文件到磁盤B,其過程是這樣的:A文件數(shù)據(jù)從磁盤開始,然后載入到“內(nèi)核緩沖區(qū)”佳遂,然后拷貝到“用戶緩存區(qū)”营袜,這完成了讀操作。寫操作也是一樣的丑罪,從“用戶緩存區(qū)”拷貝到“內(nèi)核緩沖區(qū)”荚板,最后寫入到磁盤B中凤壁。
    5. 這樣讀寫文件很累吧。有大神提出了要刪繁就簡啸驯,取消“用戶緩存區(qū)”那部分拷貝工作客扎,引入了MMP(Memory-Mapping,內(nèi)存映射)的概念罚斗。實現(xiàn)原理是這樣的:建立一個磁盤空間和內(nèi)存的直接映射,數(shù)據(jù)不再拷貝到“用戶緩存區(qū)”宅楞,而是返回一個指向內(nèi)存空間的指針针姿。這樣我們之前的文件拷貝就變成了如下步驟:A磁盤中文件將數(shù)據(jù)載入到“內(nèi)核緩沖區(qū)”,B磁盤從“內(nèi)核緩沖區(qū)”拷貝寫入文件厌衙。減少了一次拷貝過程距淫,減少了內(nèi)存的占用。
    6. 回到正題:簡單來說婶希,sendfile的原理和mmp的方式類似榕暇,核心也是減少了“內(nèi)核緩沖區(qū)”到“用戶緩沖區(qū)”的拷貝。
    7. 優(yōu)點: 不僅節(jié)省了內(nèi)存喻杈,還節(jié)省了CPU的開銷彤枢。

四 節(jié)約web服務(wù)器的CPU

  1. 對于web服務(wù)器而言,CPU是另一個非常核心的系統(tǒng)資源筒饰。就web服務(wù)器而言缴啡,除了業(yè)務(wù)程序消耗CPU外,多線程/多進程的上下文切換瓷们,也是比較消耗CPU資源的业栅。
  2. 一個進程/線程無法長時間占用CPU,當發(fā)生阻塞或者時間片用完時谬晕,就無法繼續(xù)占用CPU碘裕,這時會發(fā)生時間上下文的切換,即老的時間片切換到新的時間片攒钳,也是耗CPU的帮孔。
  3. 在并發(fā)連接數(shù)目很高的情況下,去輪詢檢測用戶建立的連接狀態(tài)(socket文件描述符)夕玩,也是消耗CPU的你弦。
  4. 筆者在這里只介紹一下終極問題及解決辦法:

多線程下的鎖對CPU的開銷

  1. Apache中的worker和event模式,都有采用多線程燎孟。多線程因為共享父進程的內(nèi)存空間禽作,在訪問共享數(shù)據(jù)的時候,就會產(chǎn)生競爭揩页,也就是線程安全問題旷偿。因此通常會引入鎖(Linux下比較常用的線程相關(guān)的鎖有互斥量metux,讀寫鎖rwlock等),成功獲取鎖的線程可以繼續(xù)執(zhí)行萍程,獲取失敗的通常選擇阻塞等待幢妄。引入鎖的機制,程序的復雜度往往增加不少茫负,同時還有線程“死鎖”或者“餓死”的風險(多進程在訪問進程間共享資源的時候蕉鸳,也有同樣的問題)。
  2. 死鎖現(xiàn)象(兩個線程彼此鎖住對方想要獲取的資源忍法,相互阻塞等待潮尝,永遠無法達不到滿足條件)
  3. 餓死現(xiàn)象(某個線程,一直獲取不到它想要鎖資源饿序,永遠無法執(zhí)行下一步)
  4. 為了避免這些鎖導致的問題勉失,就不得不加大程序的復雜度,解決方案一般有:
    1. 對資源的加鎖原探,根據(jù)約定好的順序乱凿,大家都先對共享資源X加鎖,加鎖成功之后才能加鎖共享資源Y咽弦。
    2. 如果線程占有資源X徒蟆,卻加鎖資源Y失敗,則放棄加鎖离唬,同時也釋放掉之前占有的資源X后专。
  5. 在使用PHP的時候,在Apache的worker和event模式下输莺,也必須兼容線程安全戚哎。通常,新版本的PHP官方庫是沒有線程安全方面的問題嫂用,需要關(guān)注的是第三方擴展型凳。PHP實現(xiàn)線程安全,不是通過鎖的方式實現(xiàn)的嘱函。而是為每個線程獨立申請一份全局變量的副本甘畅,相當于線程的私人內(nèi)存空間,但是這樣做相對多消耗一些內(nèi)存往弓。這樣的好處:不需要引入復雜的鎖機制實現(xiàn)疏唾,也避免了鎖機制對CPU的開銷。

這里順便提到一下函似,經(jīng)常和Nginx搭配工作的PHP-FPM(FastCGI)使用的是多進程槐脏,因此不會有線程安全的問題。


筆者:王中陽 
微信(QQ):425772719
公司:北京麥芽田網(wǎng)絡(luò)科技有限公司
郵箱:wangzhong.yang@foxmail.com
本篇文章整理自==徐漢彬==老師的《高并發(fā)Web服務(wù)的演變——節(jié)約系統(tǒng)內(nèi)存和CPU》
本篇文稿初步整理,如有不妥之處敬請諒解
歡迎在下方評論處交流討論撇寞,歡迎糾正問題

一個敲代碼顿天,愛分享的人堂氯,我在這里!

來玩啊
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末牌废,一起剝皮案震驚了整個濱河市咽白,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鸟缕,老刑警劉巖晶框,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異叁扫,居然都是意外死亡三妈,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門莫绣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人悠鞍,你說我怎么就攤上這事对室。” “怎么了咖祭?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵掩宜,是天一觀的道長。 經(jīng)常有香客問我么翰,道長牺汤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任浩嫌,我火速辦了婚禮檐迟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘码耐。我一直安慰自己追迟,他們只是感情好,可當我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布骚腥。 她就那樣靜靜地躺著敦间,像睡著了一般。 火紅的嫁衣襯著肌膚如雪束铭。 梳的紋絲不亂的頭發(fā)上廓块,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天,我揣著相機與錄音契沫,去河邊找鬼带猴。 笑死,一個胖子當著我的面吹牛埠褪,可吹牛的內(nèi)容都是我干的浓利。 我是一名探鬼主播挤庇,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼贷掖!你這毒婦竟也來了嫡秕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤苹威,失蹤者是張志新(化名)和其女友劉穎昆咽,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體牙甫,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡掷酗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了窟哺。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泻轰。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖且轨,靈堂內(nèi)的尸體忽然破棺而出浮声,到底是詐尸還是另有隱情,我是刑警寧澤旋奢,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布泳挥,位于F島的核電站,受9級特大地震影響至朗,放射性物質(zhì)發(fā)生泄漏屉符。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一锹引、第九天 我趴在偏房一處隱蔽的房頂上張望矗钟。 院中可真熱鬧,春花似錦粤蝎、人聲如沸真仲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽秸应。三九已至,卻和暖如春碑宴,著一層夾襖步出監(jiān)牢的瞬間软啼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工延柠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留祸挪,地道東北人。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓贞间,卻偏偏與公主長得像贿条,于是被迫代替她去往敵國和親雹仿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,047評論 2 355

推薦閱讀更多精彩內(nèi)容