從現(xiàn)在純網(wǎng)站技術(shù)來看,因?yàn)殚_源模式的發(fā)展,現(xiàn)在搭建一個(gè)小網(wǎng)站非常容易,成本也很低,所以很多人把自己的創(chuàng)業(yè)方向定位在了互聯(lián)網(wǎng)應(yīng)用上。這些人大多不是很懂技術(shù),或者不是很精通,而且網(wǎng)站開發(fā)和維護(hù)的知識(shí)很零散,學(xué)習(xí)成本太高,所以這篇文章結(jié)合了這些知識(shí)點(diǎn)。訪問量幾千的小網(wǎng)站,一天訪問量一兩百萬的小網(wǎng)站,中間可能會(huì)出現(xiàn)什么問題,一開始如何做足夠的工作,盡可能避免這些問題。
由于您的努力,您網(wǎng)站的訪問量逐漸增加。在增加的過程中,問題也可能開始出現(xiàn)。因?yàn)閹捲黾?、硬件擴(kuò)容、人員膨脹帶來的成本增加是顯而易見的,而且有相當(dāng)一部分成本是由代碼重構(gòu)、架構(gòu)重構(gòu),甚至是底層開發(fā)語言的更換造成的。最壞的情況是數(shù)據(jù)丟失,所有的努力都是徒勞的。這種成本支出,大部分在一開始是可以避免的,先打好基礎(chǔ),以后可以省心省力。
對(duì)于不同的初始投資成本,技術(shù)路線的選擇是不同的。這里假設(shè)網(wǎng)站只是一個(gè)想法,第一年計(jì)劃在服務(wù)器硬件帶寬上投入5萬左右。對(duì)于這筆錢,有很多選擇,比如租用虛擬主機(jī),租用單獨(dú)的服務(wù)器,或者現(xiàn)在流行的私有云,或者托管服務(wù)器。對(duì)于前兩種方案,當(dāng)網(wǎng)站發(fā)展到一定規(guī)模后,需要進(jìn)行遷移,然后重新規(guī)劃,顯然影響會(huì)更大。由于服務(wù)器托管是自行配置和完全可控的,具有一定規(guī)模的網(wǎng)站基本都是這種模式。對(duì)于使用自己托管服務(wù)器的網(wǎng)站,開頭要注意以下幾點(diǎn)——
一、開發(fā)語言
一般來說,技術(shù)人員(程序員)會(huì)根據(jù)自己的技術(shù)背景來選擇自己最熟悉的語言,但是靠自己寫程序是不可能永遠(yuǎn)的,所以在語言的選擇上還是要花點(diǎn)心思的。首先明確一點(diǎn),不管用什么語言,最終的代碼質(zhì)量還是要靠管理,所以我們從前期的開發(fā)成本來分析。目前國內(nèi)流行的適用于網(wǎng)站的語言大致分為五個(gè)陣營:java、php、net、python、ruby。因?yàn)閜ython和ruby在國內(nèi)流行的比較晚,所以招人還是比較困難的。net平臺(tái)的人比較多,但是后期需要解決性能問題的時(shí)候,對(duì)人員技能的要求比較高。剩下的java和php雇主可以說是最多的了。 Java和php從語言層面無法比較,但是對(duì)于起步階段,應(yīng)用幾乎都是前端網(wǎng)站支持的,php上手容易,編寫速度快,有比較大的優(yōu)勢。至于后端如行為分析、銀行接口、異步消息處理等,真正需要的時(shí)候,需要根據(jù)不同的業(yè)務(wù)需求選擇不同的語言。
二、代碼版本管理
稍大的網(wǎng)站需要使用代碼版本管理。代碼版本管理最大的好處有兩個(gè),一是方便協(xié)同工作,二是有歷史記錄可以查詢比較。代碼版本管理軟件有很多,比如vss/cvs/svn/hg等,目前國內(nèi)比較流行,svn的普及度還是很高的。
假設(shè)選擇了svn,則有幾個(gè)注意事項(xiàng)。一是使用什么樹結(jié)構(gòu)。前期可能只有一個(gè)trunk,后期需要建立分支,比如開發(fā)分支,live分支,再后來,可能每個(gè)團(tuán)隊(duì)都有一個(gè)分支。建議一開始人少的時(shí)候選擇兩個(gè)分支,development和online。各功能本地測試無誤后提交給開發(fā)分支。最后統(tǒng)一測試上線的時(shí)候可以合并到線上分支。如果每個(gè)人都建立自己的分支,合并的時(shí)候會(huì)浪費(fèi)很多精力。對(duì)于一天修改幾次的WEB應(yīng)用來說,會(huì)花費(fèi)太多的時(shí)間。
手動(dòng)或自動(dòng)將代碼部署到服務(wù)器。手動(dòng)部署相對(duì)簡單。一般可以在服務(wù)器上直接svn update,或者找一個(gè)新的目錄svn checkout,然后把web根目錄給ln -s。應(yīng)用程序越復(fù)雜,部署就越復(fù)雜。沒有統(tǒng)一的標(biāo)準(zhǔn)。只是不要使用ftp上傳。首先,上傳時(shí)文件引用不一致錯(cuò)誤率增加。第二,開發(fā)者的版本很容易和線上版本不一致,導(dǎo)致我本來想改個(gè)錯(cuò)別字變成回滾。如果有多臺(tái)服務(wù)器,還是建議自動(dòng)部署。換碼機(jī)暫時(shí)退出當(dāng)前服務(wù)池,更新完成后重新加入。
三、服務(wù)器硬件
在每個(gè)機(jī)房里,光是一臺(tái)服務(wù)器就支持了無數(shù)個(gè)網(wǎng)站,但是如果資金稍微充足一點(diǎn),建議至少三個(gè)標(biāo)準(zhǔn)配置,分別用于網(wǎng)頁處理、數(shù)據(jù)庫、備份。 web服務(wù)器至少需要8G內(nèi)存,double sata raid1,如果經(jīng)濟(jì)稍微寬松一點(diǎn),或者靜態(tài)文件或者圖片比較多,那就15k sas raid10。數(shù)據(jù)庫至少要有16G內(nèi)存和15k sas raid 10。備份服務(wù)器最好和數(shù)據(jù)庫服務(wù)器配置在同一級(jí)別。硬件可以是品牌整機(jī),也可以是兼容機(jī),也可以是半品牌半組裝,看經(jīng)濟(jì)能力。當(dāng)然,這是一個(gè)典型的組合。某些類型應(yīng)用的性能瓶頸最先出現(xiàn)在Web端,需要單獨(dú)分析。
Web服務(wù)器可以運(yùn)行程序并充當(dāng)內(nèi)存緩存,而數(shù)據(jù)庫服務(wù)器只運(yùn)行主數(shù)據(jù)庫(如果是MySQL),備份服務(wù)器承擔(dān)的更多。 Web配置、緩存配置、數(shù)據(jù)庫配置必須和前面兩者保持一致,所以如果WEB和數(shù)據(jù)庫哪一個(gè)出現(xiàn)問題,很容易切換備份服務(wù)器臨時(shí)替代,直到問題解決。需要注意的是,硬件隨時(shí)都有可能壞掉,尤其是硬盤,所以最好把WEB服務(wù)器和數(shù)據(jù)庫服務(wù)器放在一起,備份一定不能省略。備份必須是不同的和異步的,可能會(huì)出現(xiàn)斷電和誤操作。導(dǎo)致機(jī)器上的所有數(shù)據(jù)丟失。有許多開源備份解決方案可供選擇。最簡單的就是rsync,用crontab寫的,定時(shí)同步。對(duì)于備份和切換,建議多做測試,選擇最安全最適合業(yè)務(wù)的,盡量異地備份。
四、機(jī)房
盡量不要選擇三種機(jī)房:聯(lián)通訪問特別慢的聯(lián)通機(jī)房、電信訪問特別慢的聯(lián)通機(jī)房、電信機(jī)房
聯(lián)通訪問特別慢的移動(dòng)或鐵通機(jī)房。機(jī)房要盡可能多的實(shí)地參觀,多測試,找個(gè)網(wǎng)絡(luò)質(zhì)量好,管理嚴(yán)格的機(jī)房。機(jī)房可以說是非常重要,直接關(guān)系到網(wǎng)站訪問速度,網(wǎng)站訪問速度直接關(guān)系到用戶體驗(yàn),訪問速度很慢的網(wǎng)站,很難獲得用戶青睞。五、架構(gòu)
在大方向上,被熟知的架構(gòu)是web負(fù)載均衡+數(shù)據(jù)庫主從+緩存+分布式存儲(chǔ)+隊(duì)列。在一開始,按照可擴(kuò)展的原則設(shè)計(jì)和編程就可以。只是要多考慮緩存失效時(shí)的雪崩效應(yīng)、主從同步的數(shù)據(jù)一致性和時(shí)間差、隊(duì)列的穩(wěn)定性和失敗后的重試策略、文件存儲(chǔ)的效率和備份方式等等意外情況。緩存失效、數(shù)據(jù)庫復(fù)制中斷、隊(duì)列寫入錯(cuò)誤、電源損壞,在實(shí)際運(yùn)維中經(jīng)常發(fā)生,如果不注意這些,出現(xiàn)問題時(shí)恢復(fù)期可能會(huì)超出預(yù)期很長時(shí)間。
六、服務(wù)器軟件
操作系統(tǒng)Linux很流行。在沒有專業(yè)運(yùn)維人員的情況下,應(yīng)傾向于擇使用的人多、社區(qū)活躍、配置方便、升級(jí)方便的發(fā)行版,例如RH系列、debian、ubuntu server等,硬件和操作系統(tǒng)要一起選擇,看是否有適合的驅(qū)動(dòng),如果確定用某種商業(yè)軟件或解決方案,也要提前知曉其對(duì)哪種操作系統(tǒng)支持最佳。web服務(wù)器方面,apache、nginx、lighttpd三大系列中,apache占有量還是最大,但是想把性能調(diào)教好還是需要很專業(yè)的,nginx和lighttpd在不需要太多調(diào)整的情況下可以達(dá)到一個(gè)比較不錯(cuò)的性能。無論選擇什么軟件,除非改過這些軟件或你的程序真的不兼容新版本,否則盡量版本越新越好,版本新,意味著新特性增多、BUG減少、性能增加。一個(gè)典型的php網(wǎng)站,基本上大多數(shù)人都沒改過任何服務(wù)器軟件源代碼,絕大多數(shù)情況是能平穩(wěn)的升級(jí)到新版本的。類似于jdk5到 jdk6,python2到python3這類變動(dòng)比較大的升級(jí)還是比較少見的??纯碈hangeLog,看看升級(jí)說明,結(jié)合自己情況評(píng)估測試一下,越早升級(jí)越好,升級(jí)的越晚,所花費(fèi)的成本越高。對(duì)于軟件包,盡量使用發(fā)行版內(nèi)置的包管理工具,沒有特殊要求時(shí)不建議自己編譯,那樣對(duì)將來運(yùn)維不利。
七、數(shù)據(jù)庫
幾乎所有操作最后都要落到數(shù)據(jù)庫身上,它又最難擴(kuò)展(存儲(chǔ)也挺難)。數(shù)據(jù)庫常見的擴(kuò)展方法有復(fù)制、分片,設(shè)計(jì)時(shí)要考慮到每種應(yīng)用的數(shù)據(jù)如何復(fù)制、分片,當(dāng)然這種考慮一般會(huì)推遲到技術(shù)設(shè)計(jì)時(shí)期。在初期進(jìn)行數(shù)據(jù)庫結(jié)構(gòu)設(shè)計(jì)時(shí),要根據(jù)不同的業(yè)務(wù)類型和增長量預(yù)期來考慮是否要分庫、分區(qū),并且盡量不要使用聯(lián)合查詢、不使用自增ID以方便分片。復(fù)制延時(shí)問題、主從數(shù)據(jù)庫數(shù)據(jù)一致性問題,可以自己寫或者用已有的運(yùn)維工具進(jìn)行檢測。
用存儲(chǔ)過程是比較難擴(kuò)展的,這種情形多發(fā)生于傳統(tǒng)C/S,特別是OA系統(tǒng)轉(zhuǎn)換過來的開發(fā)人員。低成本網(wǎng)站不是一兩臺(tái)小型機(jī)跑一個(gè)數(shù)據(jù)庫處理所有業(yè)務(wù)的模式,是機(jī)海作戰(zhàn)。方便水平擴(kuò)展比那點(diǎn)預(yù)分析時(shí)間和網(wǎng)絡(luò)傳輸流量要重要的多的多。
另外,現(xiàn)在流行一種概念叫NoSQL,可以理解為非傳統(tǒng)關(guān)系型數(shù)據(jù)庫。實(shí)際應(yīng)用中,網(wǎng)站有著越來越多的密集寫操作、上億的簡單關(guān)系數(shù)據(jù)讀取、熱備等,這都不是傳統(tǒng)關(guān)系數(shù)據(jù)庫所擅長的,于是就產(chǎn)生了很多非關(guān)系型數(shù)據(jù)庫,比如Redis/TC&TT/MongoDB/Memcachedb等,在測試中,這些幾乎都達(dá)到了每秒至少一萬次的寫操作,內(nèi)存型的甚至5萬以上。在設(shè)計(jì)時(shí),可根據(jù)業(yè)務(wù)特點(diǎn)和性能要求來選擇是否使用這類數(shù)據(jù)庫。例如MongoDB,幾句配置就可以組建一個(gè)復(fù)制+自動(dòng)分片+failover的環(huán)境,文檔化的存儲(chǔ)也簡化了傳統(tǒng)設(shè)計(jì)庫結(jié)構(gòu)再開發(fā)的模式。但是當(dāng)你決定采用一項(xiàng)技術(shù)時(shí),一定要真正了解其優(yōu)劣,例如可能你所選擇的技術(shù)并不能支持你所需要的事務(wù)和數(shù)據(jù)一致性要求。
八、文件存儲(chǔ)
存儲(chǔ)的分布幾乎跟數(shù)據(jù)庫擴(kuò)展一樣困難,不過只有百萬的PV的情況下,磁盤IO方面一般不會(huì)成大問題,一兩臺(tái)采用SATA做條帶RAID的機(jī)器可以應(yīng)付,反而是自己做異步備份比較復(fù)雜,因?yàn)樾∥募唷H绻挥幸慌_(tái)機(jī)器做存儲(chǔ),可以做簡單的優(yōu)化,例如放最小縮略圖的分區(qū)和放中等縮略圖的分區(qū),根據(jù)平均大小調(diào)整一下塊大小。存儲(chǔ)要規(guī)劃好目錄結(jié)構(gòu),否則文件增多后維護(hù)起來復(fù)雜,也不利于擴(kuò)展。同時(shí)還要考慮將來擴(kuò)容,例如采用LVM,或者把文件根據(jù)不同規(guī)則散列到不同機(jī)器。磁盤IO繁重的情況下更容易出現(xiàn)故障,所以要做好備份,若發(fā)現(xiàn)有盤壞掉,要馬上行動(dòng)更換,很多人的硬盤都是壞了一塊之后,接二連三的壞下去。
為了將來圖片走cdn做準(zhǔn)備,一開始最好就將圖片的域名分開,且不用主域名。因?yàn)楹芏嗑W(wǎng)站都將cookie設(shè)置到了.domain.ltd,如果圖片也在這個(gè)域名下,很可能因?yàn)閏ookie而造成緩存失效,并且占多余流量,還可能因?yàn)闉g覽器并發(fā)線程限制造成訪問緩慢。
九、程序
一定硬件條件下,應(yīng)用能承載多少訪問量,很大一部分也取決于程序如何寫。程序?qū)懙牟缓茫赡芤蝗f的訪問都承載不了,寫的好,可能一兩臺(tái)機(jī)器就能承擔(dān)幾百萬PV。越是復(fù)雜、數(shù)據(jù)實(shí)時(shí)性要求越高的應(yīng)用,優(yōu)化起來越難,但對(duì)普通網(wǎng)站有一個(gè)統(tǒng)一的思路,就是盡量向前端優(yōu)化、減少數(shù)據(jù)庫操作、減少磁盤IO。向前端優(yōu)化指的是,在不影響功能和體驗(yàn)的情況下,能在瀏覽器執(zhí)行的不要在服務(wù)端執(zhí)行,能在緩存服務(wù)器上直接返回的不要到應(yīng)用服務(wù)器,程序能直接取得的結(jié)果不要到外部取得,本機(jī)內(nèi)能取得的數(shù)據(jù)不要到遠(yuǎn)程取,內(nèi)存能取到的不要到磁盤取,緩存中有的不要去數(shù)據(jù)庫查詢。減少數(shù)據(jù)庫操作指減少更新次數(shù)、緩存結(jié)果減少查詢次數(shù)、將數(shù)據(jù)庫執(zhí)行的操作盡可能的讓你的程序完成(例如join查詢),減少磁盤IO指盡量不使用文件系統(tǒng)作為緩存、減少讀寫文件次數(shù)等。程序優(yōu)化永遠(yuǎn)要優(yōu)化慢的部分,換語法是無法“優(yōu)化”的。
然而編程時(shí)不應(yīng)該把重點(diǎn)放在優(yōu)化上,應(yīng)該關(guān)注擴(kuò)展性。當(dāng)今的WEB應(yīng)用,需求變化非常之快,適應(yīng)多種需求的架構(gòu)是不存在的,我們的擴(kuò)展性就要把要點(diǎn)放在跟底層交互的架構(gòu)上,例如持久化數(shù)據(jù)的存取規(guī)則、緩存的存取規(guī)則等,還有一些共用服務(wù),例如用戶信息等。先把不變的部分做完善,剩下的部分就很容易將精力放在業(yè)務(wù)邏輯上面了。
關(guān)于作者
劉志一,從1999年做個(gè)人網(wǎng)站開始一直專注于互聯(lián)網(wǎng),目前就職于一家垂直行業(yè)C2C網(wǎng)站,做產(chǎn)品和開發(fā)方面工作。
我們專注高端建站,小程序開發(fā)、軟件系統(tǒng)定制開發(fā)、BUG修復(fù)、物聯(lián)網(wǎng)開發(fā)、各類API接口對(duì)接開發(fā)等。十余年開發(fā)經(jīng)驗(yàn),每一個(gè)項(xiàng)目承諾做到滿意為止,多一次對(duì)比,一定讓您多一份收獲!