網(wǎng)站架構(gòu)方案全解析
1、HTML靜態(tài)化其實(shí)大家都知道,效率最高、消耗最小的就是純靜態(tài)化的html頁面,所以我們盡可能使我們的網(wǎng)站上的頁面采用靜態(tài)頁面來實(shí)現(xiàn),這個(gè)最簡(jiǎn)單的方法其實(shí)也是最有效的方法。但是對(duì)于大量?jī)?nèi)容并且頻繁更新的網(wǎng)站,我們無法全部手動(dòng)去挨個(gè)實(shí)現(xiàn),于是出現(xiàn)了我們常見的信息發(fā)布系統(tǒng)CMS,像我們常訪問的各個(gè)門戶站點(diǎn)的新聞?lì)l道,甚至他們的其他頻道,都是通過信息發(fā)布系統(tǒng)來管理和實(shí)現(xiàn)的,信息發(fā)布系統(tǒng)可以實(shí)現(xiàn)最簡(jiǎn)單的信息錄入自動(dòng)生成靜態(tài)頁面,還能具備頻道管理、權(quán)限管理、自動(dòng)抓取等功能,對(duì)于一個(gè)大型網(wǎng)站來說,擁有一套高效、可管理的CMS是必不可少的。除了門戶和信息發(fā)布類型的網(wǎng)站,對(duì)于交互性要求很高的社區(qū)類型網(wǎng)站來說,盡可能的靜態(tài)化也是提高性能的必要手段,將社區(qū)內(nèi)的帖子、文章進(jìn)行實(shí)時(shí)的靜態(tài)化,有更新的時(shí)候再重新靜態(tài)化也是大量使用的策略,像Mop的大雜燴就是使用了這樣的策略,網(wǎng)易社區(qū)等也是如此。同時(shí),html靜態(tài)化也是某些緩存策略使用的手段,對(duì)于系統(tǒng)中頻繁使用數(shù)據(jù)庫查詢但是內(nèi)容更新很小的應(yīng)用,可以考慮使用html靜態(tài)化來實(shí)現(xiàn),比如論壇中論壇的公用設(shè)置信息,這些信息目前的主流論壇都可以進(jìn)行后臺(tái)管理并且存儲(chǔ)再數(shù)據(jù)庫中,這些信息其實(shí)大量被前臺(tái)程序調(diào)用,但是更新頻率很小,可以考慮將這部分內(nèi)容進(jìn)行后臺(tái)更新的時(shí)候進(jìn)行靜態(tài)化,這樣避免了大量的數(shù)據(jù)庫訪問請(qǐng)求。
2、圖片服務(wù)器分離大家知道,對(duì)于Web服務(wù)器來說,不管是Apache、IIS還是其他容器,圖片是最消耗資源的,于是我們有必要將圖片與頁面進(jìn)行分離,這是基本上大型網(wǎng)站都會(huì)采用的策略,他們都有獨(dú)立的圖片服務(wù)器,甚至很多臺(tái)圖片服務(wù)器。這樣的架構(gòu)可以降低提供頁面訪問請(qǐng)求的服務(wù)器系統(tǒng)壓力,并且可以保證系統(tǒng)不會(huì)因?yàn)閳D片問題而崩潰,在應(yīng)用服務(wù)器和圖片服務(wù)器上,可以進(jìn)行不同的配置優(yōu)化,比如apache在配置ContentType的時(shí)候可以盡量少支持,盡可能少的LoadModule,保證更高的系統(tǒng)消耗和執(zhí)行效率。
3、數(shù)據(jù)庫集群和庫表散列大型網(wǎng)站都有復(fù)雜的應(yīng)用,這些應(yīng)用必須使用數(shù)據(jù)庫,那么在面對(duì)大量訪問的時(shí)候,數(shù)據(jù)庫的瓶頸很快就能顯現(xiàn)出來,這時(shí)一臺(tái)數(shù)據(jù)庫將很快無法滿足應(yīng)用,于是我們需要使用數(shù)據(jù)庫集群或者庫表散列。在數(shù)據(jù)庫集群方面,很多數(shù)據(jù)庫都有自己的解決方案,Oracle、Sybase等都有很好的方案,常用的MySQL提供的Master/Slave也是類似的方案,您使用了什么樣的DB,就參考相應(yīng)的解決方案來實(shí)施即可。上面提到的數(shù)據(jù)庫集群由于在架構(gòu)、成本、擴(kuò)張性方面都會(huì)受到所采用DB類型的限制,于是我們需要從應(yīng)用程序的角度來考慮改善系統(tǒng)架構(gòu),庫表散列是常用并且最有效的解決方案。我們?cè)趹?yīng)用程序中安裝業(yè)務(wù)和應(yīng)用或者功能模塊將數(shù)據(jù)庫進(jìn)行分離,不同的模塊對(duì)應(yīng)不同的數(shù)據(jù)庫或者表,再按照一定的策略對(duì)某個(gè)頁面或者功能進(jìn)行更小的數(shù)據(jù)庫散列,比如用戶表,按照用戶ID進(jìn)行表散列,這樣就能夠低成本的提升系統(tǒng)的性能并且有很好的擴(kuò)展性。sohu的論壇就是采用了這樣的架構(gòu),將論壇的用戶、設(shè)置、帖子等信息進(jìn)行數(shù)據(jù)庫分離,然后對(duì)帖子、用戶按照板塊和ID進(jìn)行散列數(shù)據(jù)庫和表,最終可以在配置文件中進(jìn)行簡(jiǎn)單的配置便能讓系統(tǒng)隨時(shí)增加一臺(tái)低成本的數(shù)據(jù)庫進(jìn)來補(bǔ)充系統(tǒng)性能。
4、緩存一詞搞技術(shù)的都接觸過,很多地方用到緩存。網(wǎng)站架構(gòu)和網(wǎng)站開發(fā)中的緩存也是非常重要。這里先講述最基本的兩種緩存。高級(jí)和分布式的緩存在后面講述。架構(gòu)方面的緩存,對(duì)Apache比較熟悉的人都能知道Apache提供了自己的緩存模塊,也可以使用外加的Squid模塊進(jìn)行緩存,這兩種方式均可以有效的提高Apache的訪問響應(yīng)能力。網(wǎng)站程序開發(fā)方面的緩存,Linux上提供的Memory Cache是常用的緩存接口,可以在web開發(fā)中使用,比如用Java開發(fā)的時(shí)候就可以調(diào)用MemoryCache對(duì)一些數(shù)據(jù)進(jìn)行緩存和通訊共享,一些大型社區(qū)使用了這樣的架構(gòu)。另外,在使用web語言開發(fā)的時(shí)候,各種語言基本都有自己的緩存模塊和方法,PHP有Pear的Cache模塊,Java就更多了,.net不是很熟悉,相信也肯定有。
5、鏡像是大型網(wǎng)站常采用的提高性能和數(shù)據(jù)安全性的方式,鏡像的技術(shù)可以解決不同網(wǎng)絡(luò)接入商和地域帶來的用戶訪問速度差異,比如 ChinaNet和EduNet之間的差異就促使了很多網(wǎng)站在教育網(wǎng)內(nèi)搭建鏡像站點(diǎn),數(shù)據(jù)進(jìn)行定時(shí)更新或者實(shí)時(shí)更新。在鏡像的細(xì)節(jié)技術(shù)方面,這里不闡述太深,有很多專業(yè)的現(xiàn)成的解決架構(gòu)和產(chǎn)品可選。也有廉價(jià)的通過軟件實(shí)現(xiàn)的思路,比如Linux上的rsync等工具。
6、負(fù)載均衡將是大型網(wǎng)站解決高負(fù)荷訪問和大量并發(fā)請(qǐng)求采用的終極解決辦法。負(fù)載均衡技術(shù)發(fā)展了多年,有很多專業(yè)的服務(wù)提供商和產(chǎn)品可以選擇,我個(gè)人接觸過一些解決方法,其中有兩個(gè)架構(gòu)可以給大家做參考。
7、硬件四層交換第四層交換使用第三層和第四層信息包的報(bào)頭信息,根據(jù)應(yīng)用區(qū)間識(shí)別業(yè)務(wù)流,將整個(gè)區(qū)間段的業(yè)務(wù)流分配到合適的應(yīng)用服務(wù)器進(jìn)行處理。第四層交換功能就象是虛 IP,指向物理服務(wù)器。它傳輸?shù)臉I(yè)務(wù)服從的協(xié)議多種多樣,有HTTP、FTP、NFS、Telnet或其他協(xié)議。這些業(yè)務(wù)在物理服務(wù)器基礎(chǔ)上,需要復(fù)雜的載量平衡算法。在IP世界,業(yè)務(wù)類型由終端TCP或UDP端口地址來決定,在第四層交換中的應(yīng)用區(qū)間則由源端和終端IP地址、TCP和UDP端口共同決定。在硬件四層交換產(chǎn)品領(lǐng)域,有一些知名的產(chǎn)品可以選擇,比如Alteon、F5等,這些產(chǎn)品很昂貴,但是物有所值,能夠提供非常優(yōu)秀的性能和很靈活的管理能力。Yahoo中國(guó)當(dāng)初接近2000臺(tái)服務(wù)器使用了三四臺(tái)Alteon就搞定了。
8、軟件四層交換大家知道了硬件四層交換機(jī)的原理后,基于OSI模型來實(shí)現(xiàn)的軟件四層交換也就應(yīng)運(yùn)而生,這樣的解決方案實(shí)現(xiàn)的原理一致,不過性能稍差。但是滿足一定量的壓力還是游刃有余的,有人說軟件實(shí)現(xiàn)方式其實(shí)更靈活,處理能力完全看你配置的熟悉能力。軟件四層交換我們可以使用Linux上常用的LVS來解決,LVS就是Linux Virtual Server,他提供了基于心跳線heartbeat的實(shí)時(shí)災(zāi)難應(yīng)對(duì)解決方案,提高系統(tǒng)的魯棒性,同時(shí)可供了靈活的虛擬VIP配置和管理功能,可以同時(shí)滿足多種應(yīng)用需求,這對(duì)于分布式的系統(tǒng)來說必不可少。一個(gè)典型的使用負(fù)載均衡的策略就是,在軟件或者硬件四層交換的基礎(chǔ)上搭建squid集群,這種思路在很多大型網(wǎng)站包括搜索引擎上被采用,這樣的架構(gòu)低成本、高性能還有很強(qiáng)的擴(kuò)張性,隨時(shí)往架構(gòu)里面增減節(jié)點(diǎn)都非常容易。這樣的架構(gòu)我準(zhǔn)備空了專門詳細(xì)整理一下和大家探討。對(duì)于大型網(wǎng)站來說,前面提到的每個(gè)方法可能都會(huì)被同時(shí)使用到,我這里介紹得比較淺顯,具體實(shí)現(xiàn)過程中很多細(xì)節(jié)還需要大家慢慢熟悉和體會(huì),有時(shí)一個(gè)很小的squid參數(shù)或者apache參數(shù)設(shè)置,對(duì)于系統(tǒng)性能的影響就會(huì)很大,希望大家一起討論,達(dá)到拋磚引玉之效。#p#
用squid做web cache server,而apache在squid的后面提供真正的web服務(wù)。當(dāng)然使用這樣的架構(gòu)必須要保證主頁上大部分都是靜態(tài)頁面。這就需要程序員的配合將頁面在反饋給客戶端之前將頁面全部轉(zhuǎn)換成靜態(tài)頁面。
基本看出sina和sohu對(duì)于頻道等欄目都用了相同的技術(shù),即squid來監(jiān)聽這些IP的80端口,而真正的web server來監(jiān)聽另外一個(gè)端口。從用戶的感覺上來說不會(huì)有任何的區(qū)別,而相對(duì)于將web server直接和客戶端連在一起的方式,這樣的方式明顯的節(jié)省的帶寬和服務(wù)器。用戶訪問的速度感覺也會(huì)更快。
實(shí)例:Yupoo! 的網(wǎng)站技術(shù)架構(gòu)
帶寬:4000M/S
服務(wù)器數(shù)量:60 臺(tái)左右
Web服務(wù)器:Lighttpd, Apache, nginx
應(yīng)用服務(wù)器:Tomcat
其他:Python, Java, MogileFS 、ImageMagick 等
首先看一下網(wǎng)站的架構(gòu)圖:

該架構(gòu)圖給出了很好的概覽(點(diǎn)擊可以查看在 Yupoo! 上的大圖和原圖,請(qǐng)注意該圖版權(quán)信息)。
關(guān)于 Squid 與 Tomcat
Squid 與 Tomcat 似乎在 Web 2.0 站點(diǎn)的架構(gòu)中較少看到。我首先是對(duì) Squid 有點(diǎn)疑問,對(duì)此阿華的解釋是"目前暫時(shí)還沒找到效率比 Squid 高的緩存系統(tǒng),原來命中率的確很差,后來在 Squid 前又裝了層 Lighttpd, 基于 url 做 hash, 同一個(gè)圖片始終會(huì)到同一臺(tái) squid 去,所以命中率徹底提高了"
對(duì)于應(yīng)用服務(wù)器層的 Tomcat,現(xiàn)在 Yupoo! 技術(shù)人員也在逐漸用其他輕量級(jí)的東西替代,而 YPWS/YPFS 現(xiàn)在已經(jīng)用 Python 進(jìn)行開發(fā)了。
名次解釋:
- YPWS--Yupoo Web Server YPWS 是用 Python開發(fā)的一個(gè)小型 Web 服務(wù)器,提供基本的 Web 服務(wù)外,可以增加針對(duì)用戶、圖片、外鏈網(wǎng)站顯示的邏輯判斷,可以安裝于任何有空閑資源的服務(wù)器中,遇到性能瓶頸時(shí)方便橫向擴(kuò)展。
- YPFS--Yupoo File System 與 YPWS 類似,YPFS 也是基于這個(gè) Web 服務(wù)器上開發(fā)的圖片上傳服務(wù)器。
【Updated: 有網(wǎng)友留言質(zhì)疑 Python 的效率,Yupoo 老大劉平陽在 del.icio.us 上寫到 "YPWS用Python自己寫的,每臺(tái)機(jī)器每秒可以處理294個(gè)請(qǐng)求, 現(xiàn)在壓力幾乎都在10%以下"】
圖片處理層
接下來的 Image Process Server 負(fù)責(zé)處理用戶上傳的圖片。使用的軟件包也是 ImageMagick,在上次存儲(chǔ)升級(jí)的同時(shí),對(duì)于銳化的比率也調(diào)整過了(我個(gè)人感覺,效果的確好了很多)。”Magickd“ 是圖像處理的一個(gè)遠(yuǎn)程接口服務(wù),可以安裝在任何有空閑 CPU資源的機(jī)器上,類似 Memcached的服務(wù)方式。
我們知道 Flickr 的縮略圖功能原來是用 ImageMagick 軟件包的,后來被雅虎收購(gòu)后出于版權(quán)原因而不用了(?);EXIF 與 IPTC Flicke 是用 Perl 抽取的,我是非常建議 Yupoo! 針對(duì) EXIF 做些文章,這也是潛在產(chǎn)生受益的一個(gè)重點(diǎn)。
圖片存儲(chǔ)層
原來 Yupoo! 的存儲(chǔ)采用了磁盤陣列柜,基于 NFS 方式的,隨著數(shù)據(jù)量的增大,”Yupoo! 開發(fā)部從07年6月份就開始著手研究一套大容量的、能滿足 Yupoo! 今后發(fā)展需要的、安全可靠的存儲(chǔ)系統(tǒng)“,看來 Yupoo! 系統(tǒng)比較有信心,也是滿懷期待的,畢竟這要支撐以 TB 計(jì)算的海量圖片的存儲(chǔ)和管理。我們知道,一張圖片除了原圖外,還有不同尺寸的,這些圖片統(tǒng)一存儲(chǔ)在 MogileFS 中。
對(duì)于其他部分,常見的 Web 2.0 網(wǎng)站必須軟件都能看到,如 MySQL、Memcached 、Lighttpd 等。Yupoo! 一方面采用不少相對(duì)比較成熟的開源軟件,一方面也在自行開發(fā)定制適合自己的架構(gòu)組件。這也是一個(gè) Web 2.0 公司所必需要走的一個(gè)途徑。
非常感謝一下 Yupoo! 阿華對(duì)于技術(shù)信息的分享,技術(shù)是共通的。下一個(gè)能爆料是哪家?
--EOF--#p#
lighttpd+squid這套緩存是放在另外一個(gè)機(jī)房作為cdn的一個(gè)節(jié)點(diǎn)使用的,圖中沒描繪清楚,給大家?guī)聿槐懔恕?/p>
squid前端用lighttpd沒用nginx,主要是用了這么久,沒出啥大問題,所以就沒想其他的了。
URL Hash的擴(kuò)展性的確不好,能做的就是不輕易去增減服務(wù)器,我們目前是5臺(tái)服務(wù)器做一組hash.
我們現(xiàn)在用Python寫的Web Server,在效率方面,我可以給個(gè)測(cè)試數(shù)據(jù),根據(jù)目前的訪問日志模擬訪問測(cè)試的結(jié)果是1臺(tái)ypws,平均每秒處理294個(gè)請(qǐng)求(加載所有的邏輯判斷)。
在可靠性上,還不沒具體的數(shù)據(jù),目前運(yùn)行1個(gè)多月還沒有任何異常。
lvs每個(gè)節(jié)點(diǎn)上都裝nginx,主要是為了反向代理及處理靜態(tài)內(nèi)容,不過apache已顯得不是那么必需,準(zhǔn)備逐漸去掉。
我們處理圖片都是即時(shí)的,我們目前半數(shù)以上的服務(wù)器都裝了magickd服務(wù),用來分擔(dān)圖片處理請(qǐng)求。
實(shí)例:Tailrank 網(wǎng)站架構(gòu)
每天數(shù)以千萬計(jì)的 Blog 內(nèi)容中,實(shí)時(shí)的熱點(diǎn)是什么? Tailrank 這個(gè) Web 2.0 Startup 致力于回答這個(gè)問題。
專門爆料網(wǎng)站架構(gòu)的 Todd Hoff 對(duì) Kevin Burton 進(jìn)行了采訪。于是我們能了解一下 Tailrank 架構(gòu)的一些信息。每小時(shí)索引 2400 萬的 Blog 與 Feed,內(nèi)容處理能力為 160-200Mbps,IO 寫入大約在10-15MBps。每個(gè)月要處理 52T 之多的原始數(shù)據(jù)。Tailrank 所用的爬蟲現(xiàn)在已經(jīng)成為一個(gè)獨(dú)立產(chǎn)品:spinn3r。#p#
服務(wù)器硬件
目前大約 15 臺(tái)服務(wù)器,CPU 是 64 位的 Opteron。每臺(tái)主機(jī)上掛兩個(gè) SATA 盤,做 RAID 0。據(jù)我所知,國(guó)內(nèi)很多 Web 2.0 公司也用的是類似的方式,SATA 盤容量達(dá),低廉價(jià)格,堪稱不二之選。操作系統(tǒng)用的是 Debian Linux 。Web 服務(wù)器用 Apache 2.0,Squid 做反向代理服務(wù)器。
數(shù)據(jù)庫
Tailrank 用 MySQL 數(shù)據(jù)庫,聯(lián)邦數(shù)據(jù)庫形式。存儲(chǔ)引擎用 InnoDB, 數(shù)據(jù)量 500GB。Kevin Burton 也指出了 MySQL 5 在修了一些 多核模式下互斥鎖的問題(This Bug?)。到數(shù)據(jù)庫的JDBC 驅(qū)動(dòng)連接池用 lbpool 做負(fù)載均衡。MySQL Slave 或者 Master的復(fù)制用 MySQLSlaveSync 來輕松完成。不過即使這樣,還要花費(fèi) 20%的時(shí)間來折騰 DB。
其他開放的軟件
任何一套系統(tǒng)都離不開合適的 Profiling 工具,Tailrank 也不利外,針對(duì) Java 程序的 Benchmark 用 Benchmark4j。Log 工具用 Log5j(不是 Log4j)。Tailrank 所用的大部分工具都是開放的。
Tailrank 的一個(gè)比較大的競(jìng)爭(zhēng)對(duì)手是 Techmeme,雖然二者暫時(shí)看面向內(nèi)容的側(cè)重點(diǎn)有所不同。其實(shí),最大的對(duì)手還是自己,當(dāng)需要挖掘的信息量越來越大,如果精準(zhǔn)并及時(shí)的呈現(xiàn)給用戶內(nèi)容的成本會(huì)越來越高。從現(xiàn)在來看,Tailrank 離預(yù)期目標(biāo)還差的很遠(yuǎn)。期待羅馬早日建成#p#
YouTube架構(gòu)學(xué)習(xí)
原文: YouTube Architecture
YouTube發(fā)展迅速,每天超過1億的視頻點(diǎn)擊量,但只有很少人在維護(hù)站點(diǎn)和確保伸縮性。
平臺(tái)
- Apache
- Python
- Linux(SuSe)
- MySQL
- psyco,一個(gè)動(dòng)態(tài)的Python到C的編譯器
- lighttpd代替Apache做視頻查看
狀態(tài)
- 支持每天超過1億的視頻點(diǎn)擊量
- 成立于2005年2月
- 于2006年3月達(dá)到每天3千萬的視頻點(diǎn)擊量
- 于2006年7月達(dá)到每天1億的視頻點(diǎn)擊量
- 2個(gè)系統(tǒng)管理員,2個(gè)伸縮性軟件架構(gòu)師
- 2個(gè)軟件開發(fā)工程師,2個(gè)網(wǎng)絡(luò)工程師,1個(gè)DBA
- 處理飛速增長(zhǎng)的流量
Java代碼
1. while (true) 2. { 3. identify_and_fix_bottlenecks(); 4. drink(); 5. sleep(); 6. notice_new_bottleneck(); 7. } while (true) { identify_and_fix_bottlenecks(); drink(); sleep(); notice_new_bottleneck(); }
每天運(yùn)行該循環(huán)多次
Web服務(wù)器
- NetScaler用于負(fù)載均衡和靜態(tài)內(nèi)容緩存
- 使用mod_fast_cgi運(yùn)行Apache
- 使用一個(gè)Python應(yīng)用服務(wù)器來處理請(qǐng)求的路由
- 應(yīng)用服務(wù)器與多個(gè)數(shù)據(jù)庫和其他信息源交互來獲取數(shù)據(jù)和格式化html頁面
- 一般可以通過添加更多的機(jī)器來在Web層提高伸縮性
- Python的Web層代碼通常不是性能瓶頸,大部分時(shí)間阻塞在RPC
- Python允許快速而靈活的開發(fā)和部署
- 通常每個(gè)頁面服務(wù)少于100毫秒的時(shí)間
- 使用psyco(一個(gè)類似于JIT編譯器的動(dòng)態(tài)的Python到C的編譯器)來優(yōu)化內(nèi)部循環(huán)
- 對(duì)于像加密等密集型CPU活動(dòng),使用C擴(kuò)展
- 對(duì)于一些開銷昂貴的塊使用預(yù)先生成并緩存的html
- 數(shù)據(jù)庫里使用行級(jí)緩存
- 緩存完整的Python對(duì)象
- 有些數(shù)據(jù)被計(jì)算出來并發(fā)送給各個(gè)程序,所以這些值緩存在本地內(nèi)存中。這是個(gè)使用不當(dāng)?shù)牟呗?。?yīng)用服務(wù)器里最快的緩存將預(yù)先計(jì)算的值發(fā)送給所有服務(wù)器也花不了多少時(shí)間。只需弄一個(gè)代理來監(jiān)聽更改,預(yù)計(jì)算,然后發(fā)送。
視頻服務(wù)
1,花費(fèi)包括帶寬,硬件和能源消耗
2,每個(gè)視頻由一個(gè)迷你集群來host,每個(gè)視頻被超過一臺(tái)機(jī)器持有
3,使用一個(gè)集群意味著:
-更多的硬盤來持有內(nèi)容意味著更快的速度
-failover。如果一臺(tái)機(jī)器出故障了,另外的機(jī)器可以繼續(xù)服務(wù)
-在線備份
4,使用lighttpd作為Web服務(wù)器來提供視頻服務(wù):
-Apache開銷太大
-使用epoll來等待多個(gè)fds
-從單進(jìn)程配置轉(zhuǎn)變?yōu)槎噙M(jìn)程配置來處理更多的連接
5,大部分流行的內(nèi)容移到CDN:
-CDN在多個(gè)地方備份內(nèi)容,這樣內(nèi)容離用戶更近的機(jī)會(huì)就會(huì)更高
-CDN機(jī)器經(jīng)常內(nèi)存不足,因?yàn)閮?nèi)容太流行以致很少有內(nèi)容進(jìn)出內(nèi)存的顛簸
6,不太流行的內(nèi)容(每天1-20瀏覽次數(shù))在許多colo站點(diǎn)使用YouTube服務(wù)器
-長(zhǎng)尾效應(yīng)。一個(gè)視頻可以有多個(gè)播放,但是許多視頻正在播放。隨機(jī)硬盤塊被訪問
-在這種情況下緩存不會(huì)很好,所以花錢在更多的緩存上可能沒太大意義。
-調(diào)節(jié)RAID控制并注意其他低級(jí)問題
-調(diào)節(jié)每臺(tái)機(jī)器上的內(nèi)存,不要太多也不要太少
視頻服務(wù)關(guān)鍵點(diǎn)
1,保持簡(jiǎn)單和廉價(jià)
2,保持簡(jiǎn)單網(wǎng)絡(luò)路徑,在內(nèi)容和用戶間不要有太多設(shè)備
3,使用常用硬件,昂貴的硬件很難找到幫助文檔
4,使用簡(jiǎn)單而常見的工具,使用構(gòu)建在Linux里或之上的大部分工具
5,很好的處理隨機(jī)查找(SATA,tweaks)
縮略圖服務(wù)
1,做到高效令人驚奇的難
2,每個(gè)視頻大概4張縮略圖,所以縮略圖比視頻多很多
3,縮略圖僅僅host在幾個(gè)機(jī)器上
4,持有一些小東西所遇到的問題:
-OS級(jí)別的大量的硬盤查找和inode和頁面緩存問題
-單目錄文件限制,特別是Ext3,后來移到多分層的結(jié)構(gòu)。內(nèi)核2.6的最近改進(jìn)可能讓Ext3允許大目錄,但在一個(gè)文件系統(tǒng)里存儲(chǔ)大量文件不是個(gè)好主意
-每秒大量的請(qǐng)求,因?yàn)閃eb頁面可能在頁面上顯示60個(gè)縮略圖
-在這種高負(fù)載下Apache表現(xiàn)的非常糟糕
-在Apache前端使用squid,這種方式工作了一段時(shí)間,但是由于負(fù)載繼續(xù)增加而以失敗告終。它讓每秒300個(gè)請(qǐng)求變?yōu)?0個(gè)
-嘗試使用lighttpd但是由于使用單線程它陷于困境。遇到多進(jìn)程的問題,因?yàn)樗鼈兏髯员3肿约簡(jiǎn)为?dú)的緩存
-如此多的圖片以致一臺(tái)新機(jī)器只能接管24小時(shí)
-重啟機(jī)器需要6-10小時(shí)來緩存
5,為了解決所有這些問題YouTube開始使用Google的BigTable,一個(gè)分布式數(shù)據(jù)存儲(chǔ):
-避免小文件問題,因?yàn)樗鼘⑽募占揭黄?/p>
-快,錯(cuò)誤容忍
-更低的延遲,因?yàn)樗褂梅植际蕉嗉?jí)緩存,該緩存與多個(gè)不同collocation站點(diǎn)工作
-更多信息參考Google Architecture,GoogleTalk Architecture和BigTable
數(shù)據(jù)庫
1,早期
-使用MySQL來存儲(chǔ)元數(shù)據(jù),如用戶,tags和描述
-使用一整個(gè)10硬盤的RAID 10來存儲(chǔ)數(shù)據(jù)
-依賴于信用卡所以YouTube租用硬件
-YouTube經(jīng)過一個(gè)常見的革命:?jiǎn)畏?wù)器,然后單master和多read slaves,然后數(shù)據(jù)庫分區(qū),然后sharding方式
-痛苦與備份延遲。master數(shù)據(jù)庫是多線程的并且運(yùn)行在一個(gè)大機(jī)器上所以它可以處理許多工作,slaves是單線程的并且通常運(yùn)行在小一些的服務(wù)器上并且備份是異步的,所以slaves會(huì)遠(yuǎn)遠(yuǎn)落后于master
-更新引起緩存失效,硬盤的慢I/O導(dǎo)致慢備份
-使用備份架構(gòu)需要花費(fèi)大量的money來獲得增加的寫性能
-YouTube的一個(gè)解決方案是通過把數(shù)據(jù)分成兩個(gè)集群來將傳輸分出優(yōu)先次序:一個(gè)視頻查看池和一個(gè)一般的集群
2,后期
-數(shù)據(jù)庫分區(qū)
-分成shards,不同的用戶指定到不同的shards
-擴(kuò)散讀寫
-更好的緩存位置意味著更少的IO
-導(dǎo)致硬件減少30%
-備份延遲降低到0
-現(xiàn)在可以任意提升數(shù)據(jù)庫的伸縮性
數(shù)據(jù)中心策略
1,依賴于信用卡,所以最初只能使用受管主機(jī)提供商
2,受管主機(jī)提供商不能提供伸縮性,不能控制硬件或使用良好的網(wǎng)絡(luò)協(xié)議
3,YouTube改為使用colocation arrangement。現(xiàn)在YouTube可以自定義所有東西并且協(xié)定自己的契約
4,使用5到6個(gè)數(shù)據(jù)中心加CDN
5,視頻來自任意的數(shù)據(jù)中心,不是最近的匹配或其他什么。如果一個(gè)視頻足夠流行則移到CDN
6,依賴于視頻帶寬而不是真正的延遲??梢詠碜匀魏蝐olo
7,圖片延遲很嚴(yán)重,特別是當(dāng)一個(gè)頁面有60張圖片時(shí)
8,使用BigTable將圖片備份到不同的數(shù)據(jù)中心,代碼查看誰是最近的
學(xué)到的東西
1,Stall for time。創(chuàng)造性和風(fēng)險(xiǎn)性的技巧讓你在短期內(nèi)解決問題而同時(shí)你會(huì)發(fā)現(xiàn)長(zhǎng)期的解決方案
2,Proioritize。找出你的服務(wù)中核心的東西并對(duì)你的資源分出優(yōu)先級(jí)別
3,Pick your battles。別怕將你的核心服務(wù)分出去。YouTube使用CDN來分布它們最流行的內(nèi)容。創(chuàng)建自己的網(wǎng)絡(luò)將花費(fèi)太多時(shí)間和太多money
4,Keep it simple!簡(jiǎn)單允許你更快的重新架構(gòu)來回應(yīng)問題
5,Shard。Sharding幫助隔離存儲(chǔ),CPU,內(nèi)存和IO,不僅僅是獲得更多的寫性能
6,Constant iteration on bottlenecks:
-軟件:DB,緩存
-OS:硬盤I/O
-硬件:內(nèi)存,RAID
7,You succeed as a team。擁有一個(gè)跨越條律的了解整個(gè)系統(tǒng)并知道系統(tǒng)內(nèi)部是什么樣的團(tuán)隊(duì),如安裝打印機(jī),安裝機(jī)器,安裝網(wǎng)絡(luò)等等的人。With a good team all things are possible。#p#
實(shí)例:Google架構(gòu)學(xué)習(xí)
Google是伸縮性的王者。Google一直的目標(biāo)就是構(gòu)建高性能高伸縮性的基礎(chǔ)組織來支持它們的產(chǎn)品。
平臺(tái)
Linux
大量語言:Python,Java,C++
狀態(tài)
在2006年大約有450,000臺(tái)廉價(jià)服務(wù)器
在2005年Google索引了80億Web頁面,現(xiàn)在沒有人知道數(shù)目
目前在Google有超過200個(gè)GFS集群。一個(gè)集群可以有1000或者甚至5000臺(tái)機(jī)器。成千上萬的機(jī)器從運(yùn)行著5000000000000000字節(jié)存儲(chǔ)的GFS集群獲取數(shù)據(jù),集群總的讀寫吞吐量可以達(dá)到每秒40兆字節(jié)
目前在Google有6000個(gè)MapReduce程序,而且每個(gè)月都寫成百個(gè)新程序
BigTable伸縮存儲(chǔ)幾十億的URL,幾百千千兆的衛(wèi)星圖片和幾億用戶的參數(shù)選擇
堆棧
Google形象化它們的基礎(chǔ)組織為三層架構(gòu):
1,產(chǎn)品:搜索,廣告,email,地圖,視頻,聊天,博客
2,分布式系統(tǒng)基礎(chǔ)組織:GFS,MapReduce和BigTable
3,計(jì)算平臺(tái):一群不同的數(shù)據(jù)中心里的機(jī)器
4,確保公司里的人們部署起來開銷很小
5,花費(fèi)更多的錢在避免丟失日志數(shù)據(jù)的硬件上,其他類型的數(shù)據(jù)則花費(fèi)較少
可信賴的存儲(chǔ)機(jī)制GFS(Google File System)
1,可信賴的伸縮性存儲(chǔ)是任何程序的核心需求。GFS就是Google的核心存儲(chǔ)平臺(tái)
2,Google File System - 大型分布式結(jié)構(gòu)化日志文件系統(tǒng),Google在里面扔了大量的數(shù)據(jù)
3,為什么構(gòu)建GFS而不是利用已有的東西?因?yàn)榭梢宰约嚎刂埔磺胁⑶疫@個(gè)平臺(tái)與別的不一樣,Google需要:
-跨數(shù)據(jù)中心的高可靠性
-成千上萬的網(wǎng)絡(luò)節(jié)點(diǎn)的伸縮性
-大讀寫帶寬的需求
-支持大塊的數(shù)據(jù),可能為上千兆字節(jié)
-高效的跨節(jié)點(diǎn)操作分發(fā)來減少瓶頸
4,系統(tǒng)有Master和Chunk服務(wù)器
-Master服務(wù)器在不同的數(shù)據(jù)文件里保持元數(shù)據(jù)。數(shù)據(jù)以64MB為單位存儲(chǔ)在文件系統(tǒng)中??蛻舳伺cMaster服務(wù)器交流來在文件上做元數(shù)據(jù)操作并且找到包含用戶需要數(shù)據(jù)的那些Chunk服務(wù)器
-Chunk服務(wù)器在硬盤上存儲(chǔ)實(shí)際數(shù)據(jù)。每個(gè)Chunk服務(wù)器跨越3個(gè)不同的Chunk服務(wù)器備份以創(chuàng)建冗余來避免服務(wù)器崩潰。一旦被Master服務(wù)器指明,客戶端程序就會(huì)直接從Chunk服務(wù)器讀取文件
6,一個(gè)上線的新程序可以使用已有的GFS集群或者可以制作自己的GFS集群
7,關(guān)鍵點(diǎn)在于有足夠的基礎(chǔ)組織來讓人們對(duì)自己的程序有所選擇,GFS可以調(diào)整來適應(yīng)個(gè)別程序的需求
使用MapReduce來處理數(shù)據(jù)
1,現(xiàn)在你已經(jīng)有了一個(gè)很好的存儲(chǔ)系統(tǒng),你該怎樣處理如此多的數(shù)據(jù)呢?比如你有許多TB的數(shù)據(jù)存儲(chǔ)在1000臺(tái)機(jī)器上。數(shù)據(jù)庫不能伸縮或者伸縮到這種級(jí)別花費(fèi)極大,這就是MapReduce出現(xiàn)的原因
2,MapReduce是一個(gè)處理和生成大量數(shù)據(jù)集的編程模型和相關(guān)實(shí)現(xiàn)。用戶指定一個(gè)map方法來處理一個(gè)鍵/值對(duì)來生成一個(gè)中間的鍵/值對(duì),還有一個(gè)reduce方法來合并所有關(guān)聯(lián)到同樣的中間鍵的中間值。許多真實(shí)世界的任務(wù)都可以使用這種模型來表現(xiàn)。以這種風(fēng)格來寫的程序會(huì)自動(dòng)并行的在一個(gè)大量機(jī)器的集群里運(yùn)行。運(yùn)行時(shí)系統(tǒng)照顧輸入數(shù)據(jù)劃分、程序在機(jī)器集之間執(zhí)行的調(diào)度、機(jī)器失敗處理和必需的內(nèi)部機(jī)器交流等細(xì)節(jié)。這允許程序員沒有多少并行和分布式系統(tǒng)的經(jīng)驗(yàn)就可以很容易使用一個(gè)大型分布式系統(tǒng)資源
3,為什么使用MapReduce?
-跨越大量機(jī)器分割任務(wù)的好方式
-處理機(jī)器失敗
-可以與不同類型的程序工作,例如搜索和廣告。幾乎任何程序都有map和reduce類型的操作。你可以預(yù)先計(jì)算有用的數(shù)據(jù)、查詢字?jǐn)?shù)統(tǒng)計(jì)、對(duì)TB的數(shù)據(jù)排序等等
4,MapReduce系統(tǒng)有三種不同類型的服務(wù)器
-Master服務(wù)器分配用戶任務(wù)到Map和Reduce服務(wù)器。它也跟蹤任務(wù)的狀態(tài)
-Map服務(wù)器接收用戶輸入并在其基礎(chǔ)上處理map操作。結(jié)果寫入中間文件
-Reduce服務(wù)器接收Map服務(wù)器產(chǎn)生的中間文件并在其基礎(chǔ)上處理reduce操作
5,例如,你想在所有Web頁面里的字?jǐn)?shù)。你將存儲(chǔ)在GFS里的所有頁面拋入MapReduce。這將在成千上萬臺(tái)機(jī)器上同時(shí)進(jìn)行并且所有的調(diào)整、工作調(diào)度、失敗處理和數(shù)據(jù)傳輸將自動(dòng)完成
-步驟類似于:GFS -> Map -> Shuffle -> Reduction -> Store Results back into GFS
-在MapReduce里一個(gè)map操作將一些數(shù)據(jù)映射到另一個(gè)中,產(chǎn)生一個(gè)鍵值對(duì),在我們的例子里就是字和字?jǐn)?shù)
-Shuffling操作聚集鍵類型
-Reduction操作計(jì)算所有鍵值對(duì)的綜合并產(chǎn)生最終的結(jié)果
6,Google索引操作管道有大約20個(gè)不同的map和reduction。
7,程序可以非常小,如20到50行代碼
8,一個(gè)問題是掉隊(duì)者。掉隊(duì)者是一個(gè)比其他程序慢的計(jì)算,它阻塞了其他程序。掉隊(duì)者可能因?yàn)榫徛腎O或者臨時(shí)的CPU不能使用而發(fā)生。解決方案是運(yùn)行多個(gè)同樣的計(jì)算并且當(dāng)一個(gè)完成后殺死所有其他的
9,數(shù)據(jù)在Map和Reduce服務(wù)器之間傳輸時(shí)被壓縮了。這可以節(jié)省帶寬和I/O。
在BigTable里存儲(chǔ)結(jié)構(gòu)化數(shù)據(jù)
1,BigTable是一個(gè)大伸縮性、錯(cuò)誤容忍、自管理的系統(tǒng),它包含千千兆的內(nèi)存和1000000000000000的存儲(chǔ)。它可以每秒鐘處理百萬的讀寫
2,BigTable是一個(gè)構(gòu)建于GFS之上的分布式哈希機(jī)制。它不是關(guān)系型數(shù)據(jù)庫。它不支持join或者SQL類型查詢
3,它提供查詢機(jī)制來通過鍵訪問結(jié)構(gòu)化數(shù)據(jù)。GFS存儲(chǔ)存儲(chǔ)不透明的數(shù)據(jù)而許多程序需求有結(jié)構(gòu)化數(shù)據(jù)
4,商業(yè)數(shù)據(jù)庫不能達(dá)到這種級(jí)別的伸縮性并且不能在成千上萬臺(tái)機(jī)器上工作
5,通過控制它們自己的低級(jí)存儲(chǔ)系統(tǒng)Google得到更多的控制權(quán)來改進(jìn)它們的系統(tǒng)。例如,如果它們想讓跨數(shù)據(jù)中心的操作更簡(jiǎn)單這個(gè)特性,它們可以內(nèi)建它
6,系統(tǒng)運(yùn)行時(shí)機(jī)器可以自由的增刪而整個(gè)系統(tǒng)保持工作
7,每個(gè)數(shù)據(jù)條目存儲(chǔ)在一個(gè)格子里,它可以通過一個(gè)行key和列key或者時(shí)間戳來訪問
8,每一行存儲(chǔ)在一個(gè)或多個(gè)tablet中。一個(gè)tablet是一個(gè)64KB塊的數(shù)據(jù)序列并且格式為SSTable
9,BigTable有三種類型的服務(wù)器:
-Master服務(wù)器分配tablet服務(wù)器,它跟蹤tablet在哪里并且如果需要?jiǎng)t重新分配任務(wù)
-Tablet服務(wù)器為tablet處理讀寫請(qǐng)求。當(dāng)tablet超過大小限制(通常是100MB-200MB)時(shí)它們拆開tablet。當(dāng)一個(gè)Tablet服務(wù)器失敗時(shí),則100個(gè)Tablet服務(wù)器各自挑選一個(gè)新的tablet然后系統(tǒng)恢復(fù)。
-Lock服務(wù)器形成一個(gè)分布式鎖服務(wù)。像打開一個(gè)tablet來寫、Master調(diào)整和訪問控制檢查等都需要互斥
10,一個(gè)locality組可以用來在物理上將相關(guān)的數(shù)據(jù)存儲(chǔ)在一起來得到更好的locality選擇
11,tablet盡可能的緩存在RAM里
硬件
1,當(dāng)你有很多機(jī)器時(shí)你怎樣組織它們來使得使用和花費(fèi)有效?
2,使用非常廉價(jià)的硬件
3,A 1,000-fold computer power increase can be had for a 33 times lower cost if you you use a failure-prone infrastructure rather than an infrastructure built on highly reliable components. You must build reliability on top of unreliability for this strategy to work.
4,Linux,in-house rack design,PC主板,低端存儲(chǔ)
5,Price per wattage on performance basis isn't getting better. Have huge power and cooling issues
6,使用一些collocation和Google自己的數(shù)據(jù)中心
其他
1,迅速更改而不是等待QA
2,庫是構(gòu)建程序的卓越方式
3,一些程序作為服務(wù)提供
4,一個(gè)基礎(chǔ)組織處理程序的版本,這樣它們可以發(fā)布而不用害怕會(huì)破壞什么東西
Google將來的方向
1,支持地理位置分布的集群
2,為所有數(shù)據(jù)創(chuàng)建一個(gè)單獨(dú)的全局名字空間。當(dāng)前的數(shù)據(jù)由集群分離
3,更多和更好的自動(dòng)化數(shù)據(jù)遷移和計(jì)算
4,解決當(dāng)使用網(wǎng)絡(luò)劃分來做廣闊區(qū)域的備份時(shí)的一致性問題(例如保持服務(wù)即使一個(gè)集群離線維護(hù)或由于一些損耗問題)
學(xué)到的東西
1,基礎(chǔ)組織是有競(jìng)爭(zhēng)性的優(yōu)勢(shì)。特別是對(duì)Google而言。Google可以很快很廉價(jià)的推出新服務(wù),并且伸縮性其他人很難達(dá)到。許多公司采取完全不同的方式。許多公司認(rèn)為基礎(chǔ)組織開銷太大。Google認(rèn)為自己是一個(gè)系統(tǒng)工程公司,這是一個(gè)新的看待軟件構(gòu)建的方式
2,跨越多個(gè)數(shù)據(jù)中心仍然是一個(gè)未解決的問題。大部分網(wǎng)站都是一個(gè)或者最多兩個(gè)數(shù)據(jù)中心。我們不得不承認(rèn)怎樣在一些數(shù)據(jù)中心之間完整的分布網(wǎng)站是很需要技巧的
3,如果你自己沒有時(shí)間從零開始重新構(gòu)建所有這些基礎(chǔ)組織你可以看看Hadoop。Hadoop是這里很多同樣的主意的一個(gè)開源實(shí)現(xiàn)
4,平臺(tái)的一個(gè)優(yōu)點(diǎn)是初級(jí)開發(fā)人員可以在平臺(tái)的基礎(chǔ)上快速并且放心的創(chuàng)建健全的程序。如果每個(gè)項(xiàng)目都需要發(fā)明同樣的分布式基礎(chǔ)組織的輪子,那么你將陷入困境因?yàn)橹涝鯓油瓿蛇@項(xiàng)工作的人相對(duì)較少
5,協(xié)同工作不一直是擲骰子。通過讓系統(tǒng)中的所有部分一起工作則一個(gè)部分的改進(jìn)將幫助所有的部分。改進(jìn)文件系統(tǒng)則每個(gè)人從中受益而且是透明的。如果每個(gè)項(xiàng)目使用不同的文件系統(tǒng)則在整個(gè)堆棧中享受不到持續(xù)增加的改進(jìn)
6,構(gòu)建自管理系統(tǒng)讓你沒必要讓系統(tǒng)關(guān)機(jī)。這允許你更容易在服務(wù)器之間平衡資源、動(dòng)態(tài)添加更大的容量、讓機(jī)器離線和優(yōu)雅的處理升級(jí)
7,創(chuàng)建可進(jìn)化的基礎(chǔ)組織,并行的執(zhí)行消耗時(shí)間的操作并采取較好的方案
8,不要忽略學(xué)院。學(xué)院有許多沒有轉(zhuǎn)變?yōu)楫a(chǎn)品的好主意。Most of what Google has done has prior art, just not prior large scale deployment.
9,考慮壓縮。當(dāng)你有許多CPU而IO有限時(shí)壓縮是一個(gè)好的選擇。#p#
實(shí)例:Lighttpd+Squid+Apache搭建高效率Web服務(wù)器
架構(gòu)原理
Apache通常是開源界的首選Web服務(wù)器,因?yàn)樗膹?qiáng)大和可靠,已經(jīng)具有了品牌效應(yīng),可以適用于絕大部分的應(yīng)用場(chǎng)合。但是它的強(qiáng)大有時(shí)候卻顯得笨重,配置文件得讓人望而生畏,高并發(fā)情況下效率不太高。而輕量級(jí)的Web服務(wù)器Lighttpd卻是后起之秀,其靜態(tài)文件的響應(yīng)能力遠(yuǎn)高于 Apache,據(jù)說是Apache的2-3倍。Lighttpd的高性能和易用性,足以打動(dòng)我們,在它能夠勝任的領(lǐng)域,盡量用它。Lighttpd對(duì) PHP的支持也很好,還可以通過Fastcgi方式支持其他的語言,比如Python。
畢竟Lighttpd是輕量級(jí)的服務(wù)器,功能上不能跟Apache比,某些應(yīng)用無法勝任。比如Lighttpd還不支持緩存,而現(xiàn)在的絕大部分站點(diǎn)都是用程序生成動(dòng)態(tài)內(nèi)容,沒有緩存的話即使程序的效率再高也很難滿足大訪問量的需求,而且讓程序不停的去做同一件事情也實(shí)在沒有意義。首先,Web程序是需要做緩存處理的,即把反復(fù)使用的數(shù)據(jù)做緩存。即使這樣也還不夠,單單是啟動(dòng)Web處理程序的代價(jià)就不少,緩存最后生成的靜態(tài)頁面是必不可少的。而做這個(gè)是 Squid的強(qiáng)項(xiàng),它本是做代理的,支持高效的緩存,可以用來給站點(diǎn)做反向代理加速。把Squid放在Apache或者Lighttpd的前端來緩存 Web服務(wù)器生成的動(dòng)態(tài)內(nèi)容,而Web應(yīng)用程序只需要適當(dāng)?shù)卦O(shè)置頁面實(shí)效時(shí)間即可。
即使是大部分內(nèi)容動(dòng)態(tài)生成的網(wǎng)站,仍免不了會(huì)有一些靜態(tài)元素,比如圖片、JS腳本、CSS等等,將Squid放在Apache或者Lighttp 前端后,反而會(huì)使性能下降,畢竟處理HTTP請(qǐng)求是Web服務(wù)器的強(qiáng)項(xiàng)。而且已經(jīng)存在于文件系統(tǒng)中的靜態(tài)內(nèi)容再在Squid中緩存一下,浪費(fèi)內(nèi)存和硬盤空間。因此可以考慮將Lighttpd再放在Squid的前面,構(gòu)成 Lighttpd+Squid+Apache的一條處理鏈,Lighttpd在最前面,專門用來處理靜態(tài)內(nèi)容的請(qǐng)求,把動(dòng)態(tài)內(nèi)容請(qǐng)求通過proxy模塊轉(zhuǎn)發(fā)給Squid,如果Squid中有該請(qǐng)求的內(nèi)容且沒有過期,則直接返回給Lighttpd。新請(qǐng)求或者過期的頁面請(qǐng)求交由Apache中Web程序來處理。經(jīng)過Lighttpd和Squid的兩級(jí)過濾,Apache需要處理的請(qǐng)求將大大減少,減少了Web應(yīng)用程序的壓力。同時(shí)這樣的構(gòu)架,便于把不同的處理分散到多臺(tái)計(jì)算機(jī)上進(jìn)行,由Lighttpd在前面統(tǒng)一把關(guān)。
在這種架構(gòu)下,每一級(jí)都是可以進(jìn)行單獨(dú)優(yōu)化的,比如Lighttpd可以采用異步IO方式,Squid可以啟用內(nèi)存來緩存,Apache可以啟用MPM 等,并且每一級(jí)都可以使用多臺(tái)機(jī)器來均衡負(fù)載,伸縮性很好。
原文:http://jythoner.iteye.com/blog/562567
【編輯推薦】