當前位置:編程學習大全網 - 源碼下載 - php怎麽處理高並發

php怎麽處理高並發

以下內容轉載自徐漢彬大牛的博客?億級Web系統搭建——單機到分布式集群?

當壹個Web系統從日訪問量10萬逐步增長到1000萬,甚至超過1億的過程中,Web系統承受的壓力會越來越大,在這個過程中,我們會遇到很多的問題。為了解決這些性能壓力帶來問題,我們需要在Web系統架構層面搭建多個層次的緩存機制。在不同的壓力階段,我們會遇到不同的問題,通過搭建不同的服務和架構來解決。

Web負載均衡?

Web負載均衡(Load Balancing),簡單地說就是給我們的服務器集群分配“工作任務”,而采用恰當的分配方式,對於保護處於後端的Web服務器來說,非常重要。

負載均衡的策略有很多,我們從簡單的講起哈。

1.?HTTP重定向

當用戶發來請求的時候,Web服務器通過修改HTTP響應頭中的Location標記來返回壹個新的url,然後瀏覽器再繼續請求這個新url,實際上就是頁面重定向。通過重定向,來達到“負載均衡”的目標。例如,我們在下載PHP源碼包的時候,點擊下載鏈接時,為了解決不同國家和地域下載速度的問題,它會返回壹個離我們近的下載地址。重定向的HTTP返回碼是302

這個重定向非常容易實現,並且可以自定義各種策略。但是,它在大規模訪問量下,性能不佳。而且,給用戶的體驗也不好,實際請求發生重定向,增加了網絡延時。

2. 反向代理負載均衡

反向代理服務的核心工作主要是轉發HTTP請求,扮演了瀏覽器端和後臺Web服務器中轉的角色。因為它工作在HTTP層(應用層),也就是網絡七層結構中的第七層,因此也被稱為“七層負載均衡”。可以做反向代理的軟件很多,比較常見的壹種是Nginx。

Nginx是壹種非常靈活的反向代理軟件,可以自由定制化轉發策略,分配服務器流量的權重等。反向代理中,常見的壹個問題,就是Web服務器存儲的session數據,因為壹般負載均衡的策略都是隨機分配請求的。同壹個登錄用戶的請求,無法保證壹定分配到相同的Web機器上,會導致無法找到session的問題。

解決方案主要有兩種:

1.?配置反向代理的轉發規則,讓同壹個用戶的請求壹定落到同壹臺機器上(通過分析cookie),復雜的轉發規則將會消耗更多的CPU,也增加了代理服務器的負擔。

2.?將session這類的信息,專門用某個獨立服務來存儲,例如redis/memchache,這個方案是比較推薦的。

反向代理服務,也是可以開啟緩存的,如果開啟了,會增加反向代理的負擔,需要謹慎使用。這種負載均衡策略實現和部署非常簡單,而且性能表現也比較好。但是,它有“單點故障”的問題,如果掛了,會帶來很多的麻煩。而且,到了後期Web服務器繼續增加,它本身可能成為系統的瓶頸。

3. IP負載均衡

IP負載均衡服務是工作在網絡層(修改IP)和傳輸層(修改端口,第四層),比起工作在應用層(第七層)性能要高出非常多。原理是,他是對IP層的數據包的IP地址和端口信息進行修改,達到負載均衡的目的。這種方式,也被稱為“四層負載均衡”。常見的負載均衡方式,是LVS(Linux Virtual Server,Linux虛擬服務),通過IPVS(IP Virtual Server,IP虛擬服務)來實現。

在負載均衡服務器收到客戶端的IP包的時候,會修改IP包的目標IP地址或端口,然後原封不動地投遞到內部網絡中,數據包會流入到實際Web服務器。實際服務器處理完成後,又會將數據包投遞回給負載均衡服務器,它再修改目標IP地址為用戶IP地址,最終回到客戶端。?

上述的方式叫LVS-NAT,除此之外,還有LVS-RD(直接路由),LVS-TUN(IP隧道),三者之間都屬於LVS的方式,但是有壹定的區別,篇幅問題,不贅敘。

IP負載均衡的性能要高出Nginx的反向代理很多,它只處理到傳輸層為止的數據包,並不做進壹步的組包,然後直接轉發給實際服務器。不過,它的配置和搭建比較復雜。

4. DNS負載均衡

DNS(Domain Name System)負責域名解析的服務,域名url實際上是服務器的別名,實際映射是壹個IP地址,解析過程,就是DNS完成域名到IP的映射。而壹個域名是可以配置成對應多個IP的。因此,DNS也就可以作為負載均衡服務。

這種負載均衡策略,配置簡單,性能極佳。但是,不能自由定義規則,而且,變更被映射的IP或者機器故障時很麻煩,還存在DNS生效延遲的問題。?

5. DNS/GSLB負載均衡

我們常用的CDN(Content Delivery Network,內容分發網絡)實現方式,其實就是在同壹個域名映射為多IP的基礎上更進壹步,通過GSLB(Global Server Load Balance,全局負載均衡)按照指定規則映射域名的IP。壹般情況下都是按照地理位置,將離用戶近的IP返回給用戶,減少網絡傳輸中的路由節點之間的跳躍消耗。?

“向上尋找”,實際過程是LDNS(Local DNS)先向根域名服務(Root Name Server)獲取到頂級根的Name Server(例如.com的),然後得到指定域名的授權DNS,然後再獲得實際服務器IP。

CDN在Web系統中,壹般情況下是用來解決大小較大的靜態資源(html/Js/Css/圖片等)的加載問題,讓這些比較依賴網絡下載的內容,盡可能離用戶更近,提升用戶體驗。

例如,我訪問了壹張imgcache.gtimg.cn上的圖片(騰訊的自建CDN,不使用qq.com域名的原因是防止mit來調整寫入磁盤的策略。如果機器成本允許,從硬件層面解決問題,可以選擇老壹點的RAID(Redundant Arrays of independent Disks,磁盤列陣)或者比較新的SSD(Solid State Drives,固態硬盤)。

5. NoSQL存儲

不管數據庫的讀還是寫,當流量再進壹步上漲,終會達到“人力有窮時”的場景。繼續加機器的成本比較高,並且不壹定可以真正解決問題的時候。這個時候,部分核心數據,就可以考慮使用NoSQL的數據庫。NoSQL存儲,大部分都是采用key-value的方式,這裏比較推薦使用上面介紹過Redis,Redis本身是壹個內存cache,同時也可以當做壹個存儲來使用,讓它直接將數據落地到磁盤。

這樣的話,我們就將數據庫中某些被頻繁讀寫的數據,分離出來,放在我們新搭建的Redis存儲集群中,又進壹步減輕原來MySQL數據庫的壓力,同時因為Redis本身是個內存級別的Cache,讀寫的性能都會大幅度提升。?

國內壹線互聯網公司,架構上采用的解決方案很多是類似於上述方案,不過,使用的cache服務卻不壹定是Redis,他們會有更豐富的其他選擇,甚至根據自身業務特點開發出自己的NoSQL服務。

6. 空節點查詢問題

當我們搭建完前面所說的全部服務,認為Web系統已經很強的時候。我們還是那句話,新的問題還是會來的。空節點查詢,是指那些數據庫中根本不存在的數據請求。例如,我請求查詢壹個不存在人員信息,系統會從各級緩存逐級查找,最後查到到數據庫本身,然後才得出查找不到的結論,返回給前端。因為各級cache對它無效,這個請求是非常消耗系統資源的,而如果大量的空節點查詢,是可以沖擊到系統服務的。

在我曾經的工作經歷中,曾深受其害。因此,為了維護Web系統的穩定性,設計適當的空節點過濾機制,非常有必要。

我們當時采用的方式,就是設計壹張簡單的記錄映射表。將存在的記錄存儲起來,放入到壹臺內存cache中,這樣的話,如果還有空節點查詢,則在緩存這壹層就被阻擋了。?

異地部署(地理分布式)

完成了上述架構建設之後,我們的系統是否就已經足夠強大了呢?答案當然是否定的哈,優化是無極限的。Web系統雖然表面上看,似乎比較強大了,但是給予用戶的體驗卻不壹定是最好的。因為東北的同學,訪問深圳的壹個網站服務,他還是會感到壹些網絡距離上的慢。這個時候,我們就需要做異地部署,讓Web系統離用戶更近。

壹、 核心集中與節點分散

有玩過大型網遊的同學都會知道,網遊是有很多個區的,壹般都是按照地域來分,例如廣東專區,北京專區。如果壹個在廣東的玩家,去北京專區玩,那麽他會感覺明顯比在廣東專區卡。實際上,這些大區的名稱就已經說明了,它的服務器所在地,所以,廣東的玩家去連接地處北京的服務器,網絡當然會比較慢。

當壹個系統和服務足夠大的時候,就必須開始考慮異地部署的問題了。讓妳的服務,盡可能離用戶更近。我們前面已經提到了Web的靜態資源,可以存放在CDN上,然後通過DNS/GSLB的方式,讓靜態資源的分散“全國各地”。但是,CDN只解決的靜態資源的問題,沒有解決後端龐大的系統服務還只集中在某個固定城市的問題。

這個時候,異地部署就開始了。異地部署壹般遵循:核心集中,節點分散。

·?核心集中:實際部署過程中,總有壹部分的數據和服務存在不可部署多套,或者部署多套成本巨大。而對於這些服務和數據,就仍然維持壹套,而部署地點選擇壹個地域比較中心的地方,通過網絡內部專線來和各個節點通訊。

·?節點分散:將壹些服務部署為多套,分布在各個城市節點,讓用戶請求盡可能選擇近的節點訪問服務。

例如,我們選擇在上海部署為核心節點,北京,深圳,武漢,上海為分散節點(上海自己本身也是壹個分散節點)。我們的服務架構如圖:?

需要補充壹下的是,上圖中上海節點和核心節點是同處於壹個機房的,其他分散節點各自獨立機房。?

國內有很多大型網遊,都是大致遵循上述架構。它們會把數據量不大的用戶核心賬號等放在核心節點,而大部分的網遊數據,例如裝備、任務等數據和服務放在地區節點裏。當然,核心節點和地域節點之間,也有緩存機制。?

二、 節點容災和過載保護

節點容災是指,某個節點如果發生故障時,我們需要建立壹個機制去保證服務仍然可用。毫無疑問,這裏比較常見的容災方式,是切換到附近城市節點。假如系統的天津節點發生故障,那麽我們就將網絡流量切換到附近的北京節點上。考慮到負載均衡,可能需要同時將流量切換到附近的幾個地域節點。另壹方面,核心節點自身也是需要自己做好容災和備份的,核心節點壹旦故障,就會影響全國服務。

過載保護,指的是壹個節點已經達到最大容量,無法繼續接接受更多請求了,系統必須有壹個保護的機制。壹個服務已經滿負載,還繼續接受新的請求,結果很可能就是宕機,影響整個節點的服務,為了至少保障大部分用戶的正常使用,過載保護是必要的。

解決過載保護,壹般2個方向:

·?拒絕服務,檢測到滿負載之後,就不再接受新的連接請求。例如網遊登入中的排隊。

·?分流到其他節點。這種的話,系統實現更為復雜,又涉及到負載均衡的問題。

小結

Web系統會隨著訪問規模的增長,漸漸地從1臺服務器可以滿足需求,壹直成長為“龐然大物”的大集群。而這個Web系統變大的過程,實際上就是我們解決問題的過程。在不同的階段,解決不同的問題,而新的問題又誕生在舊的解決方案之上。

系統的優化是沒有極限的,軟件和系統架構也壹直在快速發展,新的方案解決了老的問題,同時也帶來新的挑戰。

  • 上一篇:雨後天晴和雨後天晴有什麽區別?
  • 下一篇:正向代理源代碼
  • copyright 2024編程學習大全網