天天看點

必看!網際網路開發模式的經驗之談

網際網路開發的核心問題

當我1999年進入網際網路行業工作的時候,華為剛剛通過了著名的CMM認證。當時作為一個小程式員,非常向往業界經典的軟體開發模式。因為看上去,如果企業實行了CMM,我們程式員就不用再天天為了老闆一個拍腦袋的主意而加班開發了,各種各樣的奇葩需求和無理變更,也會煙消雲散。但是,在接下來的十幾年,幾乎沒有那個網際網路公司再去通過CMM認證。

是否CMM這種軟體開發模式,就根本不适合網際網路行業呢?這是一直以來我都在思考的問題。反而是跟随着網際網路企業的一步步長大,我無意識的體驗了很多現在流行概念的早期實踐:靈活、重構、持續內建、DevOps,這些實踐一開始都非常的幼稚粗糙,但是卻真正的伴随着網際網路業務的逐漸成長。是以,在讨論網際網路服務的開發模式時,我認為必須要先搞清楚網際網路服務開發的核心問題是什麼。

必看!網際網路開發模式的經驗之談

本質:服務,而不是産品

軟體到底是“服務”還是“産品”,這個話題一直都非常具有争議。作為程式開發者,實際上是非常希望軟體能夠是一個産品,因為軟體的後續維護和修改,往往是“導緻”項目失敗的最常見原因。然而事與願違的是,在網際網路企業中,打多數的軟體項目,表現出來的是典型的“服務”特征:

沒有明确的需求合同。這導緻了沒有辦法為軟體設計固定的開發方案,也難以确定長期目标。

沒有預付款和客戶驗收。網際網路服務使用者來了就用,爽了就給錢,不爽了就走,連溝通的機會都不會有。

甚至連明顯的銷售環節都沒有。很多網際網路公司隻有市場推廣部門,而沒有所謂“銷售”部門,因為推廣就幾乎等于銷售,在推廣的同僚,就必須把銷售的事情一起做了。

是以,在網際網路行業中,軟體開發更多的是以一種服務的形式存在。這種特征,在對需求的分析管理;開發技術的選擇;內建與測試;營運和客服四個方面,都導緻了不同于“産品”型軟體的巨大差異:

對于一項服務來說,需求是持續變化的,你可以找到一些通用的模式,但是必須保持變化。

開發效率是第一重要的,因為市場競争中,應對需求變化快的機關将獲得更多的客戶。

由于服務必須保持長期的穩定可用,又要具備快速的更新部署能力,是以系統內建的效率和品質要求非常高。所幸的是系統運作的環境大多數都是在可控制的空間裡(比如開發公司自己的機房内)。

服務是公司和客戶的一種持續溝通和互動的過程,并非一個單向的發售行為,是以網際網路服務需要更多細緻的營運和維護的工具,否則難以做到迅速而細緻的滿足海量的網際網路使用者的需求。

必看!網際網路開發模式的經驗之談

小米的MIUI開發節奏

管理:手段.vs.工具

在各種項目管理的課程裡面,陳述了大量針對人去工作的方法。各種會議、報告、表格、評估、測量多不勝數,然而軟體項目進度的控制,依然是一個難度堪比登月的事情。——對于很多項目經理來說,程式員們基本是一個黑盒子,他們自己都不知道一個事情需要多長時間幹完,就更别提别人怎麼去預估和控制。這裡最大的問題,我覺得是:我們往往總是想着怎樣“控制”住軟體項目的進度,而忽視了如何減少不利于項目進度的因數。實際上影響軟體開發進度的主要因數,一般有一下幾個:

程式員的能力水準。有一些項目其中的技術,是程式員完全沒接觸過的類型,這裡包含了學習、調試的時間。

開發過程中的各種修改變更。由于對可行性、需求确認等方面的因數,開發往往會走“回頭路”。有些項目做到一般會發現技術上不可行,需要修改需求;而另外一些項目是在項目做到一半甚至快完成的時候,需求方發現需要修改産品設計,因為在産品可體驗之前,完全無法想象到最後會是現在的樣子。

各種和開發無關的過程中的事務。這裡包括開會、寫報告、溝通、等待開發電腦編譯、處理開發伺服器故障、各種開發環境和測試環境的問題處理等等……這些事情往往都看起來不是非常“有技術含量”,但是實際上會嚴重影響開發進度。因為開發工作需要一個穩定、專心的工作環境,頻頻的被各種事務打斷,會讓程式員反複的花費時間去“進入”工作狀态——面對成千上萬行程式代碼,要找到之前寫到哪個部分,其實不是那麼簡單。

針對上面說的幾個問題,很多都可以通過應用更好的開發工具來解決。比如一些新的需求類型,我們可以求助于網際網路上豐富的開源軟體和開源庫;面對需求變更,我們可以使用設計模式、單元測試等工具;開發中的事務問題,更是可以有大量業界先進工具可用:SVN,Git,Jira,Project,IDE,Chef,Docker……

與其我們拿着鞭子抽打程式員,還不如給程式員更好的開發工具,這樣對于項目進度的推動,其實更有好處。

資産:代碼.vs.流程

網際網路公司是由人組成的,人是會流動的,有一些小型的公司,往往會因為一兩個核心員工的離職,造成整個系統的代碼無法看懂,無法修改,進而最後導緻公司完蛋。這種糟糕的情況,不止一次的出現過。然而,如果我們能有一套完善的開發流程,或者是習慣,以及配合良好的開發環境,加上有一定品質的代碼,是完全能做到把項目代碼,在不同程式員之間順利交接的。可惜我們很多公司管理者,并不重視程式員用什麼工具開發軟體,也不知道如何去提高代碼的可讀性,是以造成我們的項目特别害怕人員變動。如果我們把人員變動看成是一個必然會發生的事情,那麼我們就會更重視整個代碼的開發環境和開發過程,從一開始就把開發規範确定下來,規定使用什麼環境,應用何種工具,并且堅持執行,同時在實踐過程中不斷的改進。隻有這樣有預備的去做,最後才會保留的住公司真正的資産。

必看!網際網路開發模式的經驗之談

一家網際網路公司,我們在評估其開發資産的時候,并不應看他“擁有”多少行代碼,因為這些代碼是無法直接賣錢的。而網際網路公司的開發速度,以及這個速度背後的能力才是最重要的。

靈活開發的意義和實踐

靈活開發是我們現在最常見的一個“開發模式”,然而很多時候,我們看到“靈活”兩個字,似乎就是讓程式員多加點班,或者忽略一些過程加快把代碼弄出來,而真正了解“靈活”含義的并不多。實際上,靈活并不會加快機關代碼的開發速度!靈活最主要的目标,是應對需求不明确和需求變更,而這兩者正式網際網路服務中最常見的情況。

需求變更的原因

在網際網路服務中,由于沒有直接的“客戶”下單要求,是以很多需求,都是由公司内部的人“代表”的,最典型的就是我們的“老闆”們了。正式因為沒有明确的“下訂單”的過程,是以很多傳統的需求分析變得沒法做了,因為不管是老闆還是産品經理,都是面對着成千上萬的客戶去猜測他們的需求,如果他們自己能代表客戶還好,如果猜錯了,項目的代碼肯定要修改。很多網際網路公司都非常重視“資料”,原因就是這些“資料”往往代表了使用者對産品的看法,而這些看法成了網際網路産品設計的唯一客觀标準。然而這些資料本身,會包含了大量複雜性,由于統計方式、産品形态、季節時間等等,都會産生偏差。我們的項目需求,往往就是在這些偏差中确定。這就難免産生需求的變更了。

網際網路的客戶個體多,服務内容豐富,功能變化快,是網際網路項目中需求變更很多的主要原因。是以這也讓靈活開發,成為網際網路項目開發中最重要的方法。——靈活強調的是用原型來驗證需求,在網際網路服務裡就是,盡快推出服務,通過資料來驗證想法。如果我們能越頻繁的修正原型,就能越快的接近真正的需求,也就是說,如果我們的網際網路服務能越快的修正各種問題,同時越快的推出新的版本,就能讓使用者越牢固的“黏在”這個服務上。

架構設計實體化:單元測試

靈活開發講究要快速的修改代碼,我們往往會發現,代碼修改的越頻繁,BUG越多,這似乎是一個無法解決的沖突。然而,在靈活開發方法論中,有一個重要的措施,就是用來防止這種修改造成的BUG增加的。這就是——單元測試。 單元測試本質上,充當着自動的QA人員的角色,如果我們把所有的設計和需求,都先按單元測試的形式“固化”編寫下來,那麼我們在修改代碼後,就能快速的、自動的、反複的去驗證我們的代碼有沒有問題。如果這些測試足夠全面和詳細,那麼我們是不會擔心代碼修改導緻大量的BUG的,因為單元測試會自動幫我們支出問題所在。一旦我們知道了問題,修正起來反而變成是最簡單的事情了。

假如一個項目的代碼丢失了,但全面的單元測試都還在,那麼要重建這個項目并不困難,因為所有的需求,都被蘊含在這些測試代碼中,程式員們幾乎不需要去重新啃文檔,談需求,他們隻要把代碼弄成能通過單元測試就好了。這種需求的“代表物”不但是程式員開發的概念和目标,而且還可以自動的幫程式員去驗證他們的實作。是以,如果你要使用靈活開發,要嘗試頻繁修改原型,就一定要使用TDD(測試驅動開發),特别是高度重視單元測試的作用。

統一軟體設計思路的重要性

曾幾何時,我們認為,使用什麼語言開發,用結構化程式設計,還是面向對象程式設計……這些一般人難以深入了解的事情,都是程式員這夥頑固的家夥的怪癖,基本屬于私人喜好的範疇。外人既不應該深入幹預,也沒辦法去影響,因為如果你不識好歹去在這些事情上冒犯程式員,他們随時可能一言不合就辭職。既然我們隻需要可以運作的代碼,我們為什麼冒風險去激怒程式員呢?然而,在網際網路服務的開發過程中,代碼本身并不是某一個固定的、靜态的東西,它需要不斷的與時俱進,需要跟随這業務的發展而變化,同時也會從某一個程式員手裡,流向整個開發團隊。在這種情況下,軟體開發習慣、代碼的風格、程式的設計思路,就變成一個非常重要的事情了。

代碼交流:面向對象

必看!網際網路開發模式的經驗之談

确實作在還存在大量的讨論,說“面向對象不是萬能的”。說得對,但是,世界上有什麼東西是萬能的呢?我隻能說,在需求變更非常快的情況下,面向對象思想,是現在我們能選擇的最好工具了。在“資料結構+算法=程式”的時代,軟體主要是以計算任務為主,電腦是為了代替人腦進行超乎想像的運算任務而存在。而在網際網路時代,軟體主要的任務已經變成了處理這個真實世界的資訊了。資訊的存儲、交換的任務,已經遠遠超過了“計算”的任務數量。雖然我們知道,所謂的資訊處理,最底層還是依賴大量的“計算”,然而,我們的程式員們,早已不再需要編寫大量“計算”的代碼,我們面臨的挑戰,是如何用代碼準确而快速的表達這個世界。

面向對象思想包括分析、設計、編碼三個部分(OOA/OOD/OOP)。這些思想看起來繁文缛節,似乎非常啰嗦。然而,其核心思想卻非常簡單:從表達過程,轉向表達對象。人類的思維中,對象、或物體,是一個個具備自己的資訊特征的個體,而行為和過程,往往是依附于這些個體的。比如鳥會飛、賬号會鎖定、汽車會死火等等。是以如果我們的代碼,是以表達對象,把資訊和行為統一起來,是最接近于我們的認識規律的。

在網際網路開發領域,由于網絡無處不在,涉及到的領域異常廣泛,如果我們沒有一個能把代碼世界和現實世界聯系的紐帶,我們的項目将非常難以了解。——難以了解的項目,就難以變化,進而就失去了網際網路最顯著的特征。是以我認為,面向對象的思想,是每一個網際網路開發人員都應該了解的,并且應該是面對大部分業務時,首先考慮選擇的。

代碼架構與重構

我見過無數的代碼架構圖,裡面畫滿了程序和伺服器的拓撲,各種線條上标注了通訊協定,編碼格式,還有各種流程圖和協作圖,然而,這些架構設計,無一例外的對于需求變更毫無幫助。因為它們描述的是一種現狀,甚至連現狀都不是,隻是一種猜測,一種關于現狀的猜測。随着項目代碼的不斷變化,代碼數量和關系都會膨脹,這種程序、通訊級别的結構,除了越來越複雜以外,根本對于指導項目如何應對各種“代碼腐化”毫無用處。

是以我們想到了流行的“重構”,然而,如果我們隻是重構程序的關系,通信的層次,那些錯綜複雜的代碼調用關系一樣存在。各種回調、事件、耦合還是讓代碼無法了解。我們隻是在試圖把混亂塞到一些瓶子裡面,并沒有解決混亂本身。是以,我們需要的另外一個思想武器:代碼結構。隻有我們從另外一個角度,另外一個視圖去觀察代碼,才能把握代碼之間耦合的情況。正如建築裡的平面圖和立面圖,都是不可或缺的。

是以我們應該高度重視“代碼架構”,也就是描述代碼之間的關系的架構,而不是程序之間的關系的架構。在關注代碼互相調用、耦合的關系上,我們能把混亂複雜的代碼關系理清,整理出一個便于了解,便于修改的代碼外觀。這些工作看起來完全是針對開發人員的,但是實際上,這些工作是能提高整個開發效率的。它能讓代碼從難以修改,變得容易修改,進而得以支援快速的業務需求變化,這是對業務、對産品最重要的支援能力。

持續內建的意義和實踐

不管是靈活開發的快速疊代,還是重構系統,我們都将頻繁的編譯代碼、部署、測試,也就是所謂的內建。如果我們的系統內建效率太低,那麼快速的疊代可能變成慢速的疊代,重構系統的頻率也會大大降低。有一些項目,每一次內建,都要最少經曆兩三個小時,如果不順利的話,搞一個通宵都未必能完成。“發版本”是很多程式員和運維管理人員的常見加班原因。對于這個問題,很多小型公司開始的時候,并沒有給與足夠的重視,認為這些事情不過是程式員或者運維的本分工作之一,也是最日常的工作。真正得到出問題了,才發現重要性。

在任何一個網際網路應用業務中,我們都會需要“發版”:出新功能、修改BUG、啟動營運活動、甚至是機房搬遷。所有的這些,如果沒有一套合适的工具來保障,每次發版都會是一場噩夢。是以持續內建(CI),很自然的成為網際網路企業中最流行的、研究最廣泛的技術之一。

所有資産納入版本管理

持續內建的所有東西,都應該來源于版本管理系統(SVN/Git)。除此之外,軟體資産不應該存放在任何其他地方。版本管理系統應該是開發團隊的保險箱和金庫,除了代碼以外,所有的資料檔案,配置,腳本,文檔,都應該放入這個保險庫。由于版本管理系統可以追溯到任何一個是時間點,這可以讓故障恢複,問題回溯有良好的支援。

關于源代碼使用版本管理系統,已經有很長曆史了。但是網際網路服務中,除了代碼,還有很多其他的資源,比如圖檔、資料、腳本等等。除了産品項目外,我們的很多額外系統,比如運維工具、産品文檔等等,都是需要妥善保管的,這些也都應該存放到版本管理系統中。

一般現在的版本管理系統,都有“分支”的功能,簡單來說就是類似于“拷貝”了一份新的資源出來,在這之上的修改,可以由我們選擇合并到其他分支或者放棄。是以SVN的常用方案,是啟動三個類型的分支:trunk/branch/tag,專門針對“測試”、“開發”、“營運”。如果我們按預定的分支模型來設計版本管理系統的使用,那麼我們的持續內建就可以很細緻的選擇內建哪一個版本的内容。

而在Git裡面,每個使用者,都可以擁有自己的資源庫,這對于開發測試可以更加的靈活,但是對于使用者的要求更高一些:在不同的資源庫合并的過程中,需要更好的版本管理政策。持續內建系統可以自己擁有一個或者多個Git資源庫,這樣他們可以完全脫離版本管理伺服器來獨立運作。

自動化部署

我們曾經無數次的登入伺服器,無數次的拷貝檔案,無數次的修改配置,無數次的導入資料到資料庫,無數次的……如果我們對這些重複,而且容易出錯的工作熟視無睹,我們将永遠的被這些本該機器去做的事情困住。 自動化部署,是整個持續內建工作中最重要的步驟。當我們每次發版都要很仔細的修改很多檔案的時候,我們是無法避免在某次倒黴的事故後被挨批的。隻有我們能把部署工作,也用我們的開發能力去解決,編寫自動部署工具之後,我們才真正的能提升部署這個事情到一個新的台階————我們終于可不再擔心發版。

必看!網際網路開發模式的經驗之談

和自動化測試一樣,自動部署腳本,也是把一系列的技術需求,從紙面文檔+人手處理,改成用代碼實體化,并且可積累改善的方法。自動化部署工具在開源界也非常熱門,比如jekins,還有chef等等,都是為了解決部署問題而發明的軟體工具。也許對于你來說,自己用bash開發一套腳本才是合乎你的品味,但是不管怎樣,一定要有這樣的工具。就算要花費較長的開發時間,調動項目開發的程式員,一起來認真的開發一段時間自動部署功能,都是非常值得的。因為從今以後,你就可以擁有一個自己的部署系統,這個系統不但可以積累你的營運部署經驗,還能加入很多錯誤、故障的自動檢查,讓你不再需要導出找“永遠不出錯的”運維人員。

自動化部署系統中,最核心的部分就是配置管理。擁有一個對現有環境資源集中管理的資料倉庫是非常重要的。如果每個你的腳本可以識别自己所在的環境,以主動的方式去“申請”自己的配置檔案和安裝任務,是非常好的一個模式。因為從一個節點主動去分發程式,比不上多個節點向中心叢集請求部署任務,來的更容易穩定。因為在節點上的部署代理程式,能更準确的知道自己環境的情況,也可以做本地的測試。

自動化內建測試

前面曾經說過,靈活開發非常依賴于自動化的單元測試。實際上持續內建,也非常依賴于自動化的內建測試。內建測試可以把自動化部署的結果進行檢驗,避免手工進行反複驗證。如果隻有自動化部署,而沒有自動化測試,那麼內建工作,其實還是非常浪費人力的。更重要的是,我們在每次“發版本”之後,總會擔心新的修改,導緻一些舊的功能失效。這種問題實際上是很常見的,如果無法自動化的做這種回歸性的測試,那麼我們每次發版還是要忍受漫長的測試工作進度。

必看!網際網路開發模式的經驗之談

自動化內建測試也有很多開源的工具可供選擇,特别是基于B/S模式開發的WEB程式,但如果是手機APP的項目,或者用戶端C/S程式(比如網絡遊戲),對于這類伺服器系統的內建測試,往往需要我們自己根據業務來編寫測試程式。對于伺服器系統來說,一般我們針對其通信協定編寫測試程式即可,而對于用戶端系統,如果是GUI系統的,我們還可以根據GUI的内部排程指令(安卓就有這樣的套件)來測試,但如果是類似遊戲這類業務,就隻能用圖形識别技術了。

在持續內建的流程中,內建測試往往是最後一步的檢驗關口。如果內建測試失敗,應該給所有關注內建的人員發送警報(實際上,如果成功也應該報告)。現在企業往往會用郵件、IM、微信、短信或者别的一些東西接收這種消息。

DevOps的意義和實踐

在網際網路企業初始的階段,運維工作往往是伺服器端開發人員兼任的。當我在承擔這種既是開發又是運維的工作時,往往非常羨慕那些“開發、運維分離”的公司。因為作為開發人員,沒有三班倒的值班備份人力,往往是7X24小時的待命狀态,工作壓力非常大。然而,當我自己參與到一些真正開發、運維分離的項目的時候,卻發現,項目營運事故中,最少有70%的事故,是由運維的原因造成的。

除了常見的硬體、網絡故障,作業系統配置出錯,日志清理出問題,部署配置搞錯,程序不小心殺掉等等都出現過。看來伺服器端開發和運維還真是難解難分,而DevOps的思想,就是為了努力解決這種沖突。我們不應該再把開發和運維對立起來,而應該認識到,運維是開發的一種延續,運維的需求也是伺服器端系統的功能需求;運維是開發的目地,便利的、通用的運維工具,本身是能提高開發效率的一種專業産品。

運維與開發的一體性:運維、營運、QA

可以把DevOps看作開發(軟體工程)、技術營運和品質保障(QA)三者的交集。

一個網際網路軟體的上線營運,往往是由開發人員編寫出來,然後經過QA人員測試,最後放在營運環境裡進行營運。這個過程并非是單向的過程,基于前文說的,網際網路服務都是在反複修改疊代中完善的,是以項目本身,一定是由多個版本,反複在開發、QA、運維之間循環交接。舉例來說,一個網絡遊戲,在第一次開發出來後,都會經過比較仔細的QA測試,然後通過運維人員進行上線部署,最後由營運推廣人員進行宣傳,同時也要配合這些宣傳開啟遊戲内部的一些功能,客服人員也會在開始營運後參與進來,除了提供客戶咨詢外,抓作弊玩家和封帳号也會持續進行。而作為開發人員的遊戲策劃,立刻會關注遊戲系統的各種統計資料,以期在下一個版本中改善遊戲設計。這個過程,可以看到在産品開發出來之後,整個團隊幾乎都還是需要以各種方式“使用”此伺服器端系統的。是以我們在開發網際網路服務的時候,不能僅僅面向網際網路上的一般使用者,同時也需要考慮整個開發團隊的使用需求。

現代的網際網路軟體系統往往都帶有伺服器端部分。而這些伺服器程式需要7X24運作,是以産生了兩類非常明顯的需求:

運維需求:這類需求往往表現為非功能性需求,它要求伺服器程式能夠适應大規模使用者通路和持續穩定運作。

營運需求:這裡需求通常是功能性需求,因為産品上線後,産品和營運、客服、測試人員,還需要持續不斷的使用這個系統,和網際網路的海量使用者進行互動。

營運:客服、活動

在網際網路服務中,營運是一個非常重要的環節。客戶除了直接使用網際網路軟體的功能外,背後其實往往還有大量的從業人員在通過這個軟體提供服務。

其中最常見的就是客服服務。客服往往最需要的是查詢功能————能夠查到系統中特定使用者的使用資料,進而協助客戶解決問題。客服的另外一個主要工作,是封帳号和封IP。現在網際網路黑色産業鍊非常龐大,網際網路企業保護自己的手段其實不多,而客服是其中一個重要的環節,避免黑色産業侵襲自己的利益,就需要網際網路服務系統有人工幹預其資料的能力。

營運網際網路服務另外一個常見的行為就是“活動”,也就是開放一些限時的服務。就和超市一樣,網際網路服務也要定時或不定時的加入或關閉一些特别的服務。這些工作非常細緻和瑣碎,需要伺服器系統能夠提供人工參與或者機器定時啟動的一些功能。在《魔獸世界》這個網遊中,大部分的活動都是自動的和定時的,可以從遊戲裡的一個月曆功能查到。而在國産的網際網路産品中,的很多是臨時加入,需要人工維護的,如“雙十一購物節”這種。這些對于伺服器系統的版本更新,功能修改,都提出了更高的要求。

是以一般我們在設計網際網路服務系統的時候,就應該一開始就把營運需求,也作為版本目标納入開發計劃中。一些比較好的團隊,會抽象和總結同類網際網路項目(比如遊戲、電商類型)在客服、營運活動上的共性,形成一套标準的服務規範以及實作這個規範的接口。由網際網路服務開發團隊去實作這些規範的接口,提供功能上的支援,而另外一個營運開發小組,則負責根據這個接口,開發供營運團隊人員使用的界面、内部管理系統等。比如遊戲的營運規範會要求遊戲提供查詢角色區服、帳号的名字、等級等資料,提供接口在遊戲中釋出任務;電商系統的營運規範會要求網店提供本店銷售排行查詢、優惠券折扣接口等等。

運維:部署(虛拟機)、監控、統計

作為非功能性的需求來說,部署需求是第一位的。頻繁的部署是網際網路服務快速演變的基礎能力。另外,網際網路使用者的增加(和消退)也是非常迅速的,這導緻了我們可能需要快速的進行伺服器擴容,或者縮容。這種情況都需要涉及到部署。是以我們在開發伺服器系統的時候,部署需求是第一個需要考慮。加上如果我們希望實行持續內建,那麼就更加需要重視部署的能力。作為伺服器端系統,如果被設計成帶有非常複雜的程序種類和程序通訊關系的話,要做好部署就會變得更加複雜。加上可能部署的環境還不統一,可能出現的問題就更複雜了。是以現在有大量的技術嘗試改善這個方面。首先被大家廣泛接受的是虛拟機技術,也就是所謂雲伺服器(IAAS),這種技術能讓你無需直接操作硬體,不用扛機器到機房來進行部署,是一種巨大的進步。

而後現在我們有了Docker這種基于Linux容器技術的工具,這可以把伺服器作業系統層的差異環境,都統一成一個個image檔案,部署的時候隻要運作image檔案即可。但是這些依然無法簡化錯綜複雜的伺服器程序關系,是以現在有了各種“隊列服務”技術,比如Kafka,RabbitMQ, ActiveMQ等等,這些隊列服務把程序間通訊簡化成專門的服務,減少了部署的複雜性。而ZooKeeper的廣泛使用,讓我們在多程序間協調和監控有了更多的手段。在具體部署工具方面,Chef這一類軟體做了各種有益的嘗試,這些都是能讓我們優化部署需求功能的工具。

網際網路服務的24X7持續服務能力,實際上會收到各種挑戰,除了版本釋出可能導緻的問題外,在大量機器硬體裡面,硬體故障率是一個固定的比例。網絡抖動,機房線路故障也常常會出現。更容易出現的是異常的使用者通路波動:一大波使用者洶湧而來,但是也有可能是DDOS攻擊。不管怎樣,你都需要随時掌握伺服器系統的工作狀态。這時你就需要一個監控系統,但如果産品上線才發現要做,那往往已經很遲了。因為一個系統是否有問題,并不是簡單的從記憶體、CPU、網卡流量就能看出端倪的,我們往往需要在服務開發之初,就定義好各種需要監控的名額,傳統常見的名額有:每秒主循環的次數、每秒處理業務包的次數、伺服器中緩存的會話數等等……一些做的好的系統,還會有很多業務層面的監控名額,比如某個特定服務的處理效率、處理成功率等等。

既然一個系統有大量的監控名額,就涉及如何生成和管理這些資料的問題。傳統的做法是在系統中“埋入”這些監控程式,系統一邊運作一邊統計這些名額,然後定時生成日志或者通過網絡上報給某個監控系統。但是這種做法的缺點是:如果你需要更多的名額,或者修改名額的統計方法,你就被迫要修改代碼,重新開機服務,這樣會影響正在運作的服務。現在另外一個做法是,由系統把運作的原始資訊記錄成日志,然後把日志集中上報到一個監控系統中,這個監控系統一般都帶有分布式的檔案存儲系統和分布式計算統計能力。在搜集到大量實時日志的同時,這個系統根據預設的名額統計方法,不停的進行日志統計,一旦發現統計結果有問題,就會報警。而這種統計由于是在大資料處理能力的平台上生成的,是以往往發現問題的時間差能縮小到分鐘級甚至秒級。這種做法由于搜集的是原始日志記錄,是以就可以靈活的在系統運作時定制很多統計和報警的政策,但完全不會增加服務系統的壓力,也不需要修改服務系統的代碼。

必看!網際網路開發模式的經驗之談

最後說說統計,任何一個網際網路系統,都是在使用者的使用中不斷優化的,這個優化的依據,最重要的客觀依據,就是統計資料。而統計資料,一般由兩部分構成:

使用者的行為資料。比如登入行為,就可以給系統留下使用者的IP、登入時間、登出時間等資料;購買行為,就可以留下購買商品,購買價格,購買時間這些資料。

根據使用者的行為的關聯,統計出來的資料。比如根據登入行為,我們可以統計出使用者的線上時長,使用者重複登入的次數,使用者重複登入的間隔,還有什麼次日存留、七天存留等等……;根據購買行為,我們更是可以整理出使用者的購買商品傾向,ARPU值,甚至同類使用者的購買共性,這些也是所謂大資料做商品統計的主要方向。

根據上面的分析,我們可以發現,實際上統計系統也是應該分兩個部分設計,一個是盡量記錄使用者行為的基礎資料,第二個是以複雜多變的統計條件,去挖掘這些使用者行為資料中包含的規律。對于第一部分,一個可以存放海量日志資料的分布式存儲系統非常重要;對于第二部分,分布式的統計運算系統是必不可少的。對于這個體系,Google的Hadoop提供了業界的示範。但是如果你願意,也可以使用這個思路自己來建設自己的統計系統,也許你的資料量無需要用到Hadoop那麼複雜。

總結

網際網路開發模式,是針對于網際網路本質上是一個“服務”而發展起來的。因為是“服務”而不是産品,是以應對快速變化的能力是最高的技術标準。我們傾向采用更适合表達需求的軟體開發技術、自動化程度更高的開發工具,來提高我們的開發效率,而不是靠單純的“激勵主觀能動性”來做管理。

是以我們在基于自動化測試、自動化部署等持續內建工具的平台上,使用重視原型疊代的方法來開發項目,在反複以原型确認需求,以及适應需求變化的過程中,逐漸的完善整個開發生産線。并且把開發和營運視為一個整體,在服務的營運過程中,不斷的完善網際網路服務的營運工具,讓開發和營運在同一個生命周期裡生長。

必看!網際網路開發模式的經驗之談