摘要:架構(gòu)設(shè)計實體化單元測試敏捷開發(fā)講究要快速的修改代碼,我們往往會發(fā)現(xiàn),代碼修改的越頻繁,越多,這似乎是一個無法解決的矛盾。
本文由云+社區(qū)發(fā)表,作者:韓偉互聯(lián)網(wǎng)開發(fā)的核心問題
當(dāng)我1999年進(jìn)入互聯(lián)網(wǎng)行業(yè)工作的時候,華為剛剛通過了著名的CMM認(rèn)證。當(dāng)時作為一個小程序員,非常向往業(yè)界經(jīng)典的軟件開發(fā)模式。因為看上去,如果企業(yè)實行了CMM,我們程序員就不用再天天為了老板一個拍腦袋的主意而加班開發(fā)了,各種各樣的奇葩需求和無理變更,也會煙消云散。但是,在接下來的十幾年,幾乎沒有那個互聯(lián)網(wǎng)公司再去通過CMM認(rèn)證。
是否CMM這種軟件開發(fā)模式,就根本不適合互聯(lián)網(wǎng)行業(yè)呢?這是一直以來我都在思考的問題。反而是跟隨著互聯(lián)網(wǎng)企業(yè)的一步步長大,我無意識的體驗了很多現(xiàn)在流行概念的早期實踐:敏捷、重構(gòu)、持續(xù)集成、DevOps,這些實踐一開始都非常的幼稚粗糙,但是卻真正的伴隨著互聯(lián)網(wǎng)業(yè)務(wù)的逐步成長。所以,在討論互聯(lián)網(wǎng)服務(wù)的開發(fā)模式時,我認(rèn)為必須要先搞清楚互聯(lián)網(wǎng)服務(wù)開發(fā)的核心問題是什么。
本質(zhì):服務(wù),而不是產(chǎn)品軟件到底是“服務(wù)”還是“產(chǎn)品”,這個話題一直都非常具有爭議。作為程序開發(fā)者,實際上是非常希望軟件能夠是一個產(chǎn)品,因為軟件的后續(xù)維護和修改,往往是“導(dǎo)致”項目失敗的最常見原因。然而事與愿違的是,在互聯(lián)網(wǎng)企業(yè)中,打多數(shù)的軟件項目,表現(xiàn)出來的是典型的“服務(wù)”特征:
沒有明確的需求合同。這導(dǎo)致了沒有辦法為軟件設(shè)計固定的開發(fā)方案,也難以確定長期目標(biāo)。
沒有預(yù)付款和客戶驗收?;ヂ?lián)網(wǎng)服務(wù)用戶來了就用,爽了就給錢,不爽了就走,連溝通的機會都不會有。
甚至連明顯的銷售環(huán)節(jié)都沒有。很多互聯(lián)網(wǎng)公司只有市場推廣部門,而沒有所謂“銷售”部門,因為推廣就幾乎等于銷售,在推廣的同事,就必須把銷售的事情一起做了。
因此,在互聯(lián)網(wǎng)行業(yè)中,軟件開發(fā)更多的是以一種服務(wù)的形式存在。這種特征,在對需求的分析管理;開發(fā)技術(shù)的選擇;集成與測試;運營和客服四個方面,都導(dǎo)致了不同于“產(chǎn)品”型軟件的巨大差異:
對于一項服務(wù)來說,需求是持續(xù)變化的,你可以找到一些通用的模式,但是必須保持變化。
開發(fā)效率是第一重要的,因為市場競爭中,應(yīng)對需求變化快的單位將獲得更多的客戶。
由于服務(wù)必須保持長期的穩(wěn)定可用,又要具備快速的更新部署能力,所以系統(tǒng)集成的效率和質(zhì)量要求非常高。所幸的是系統(tǒng)運行的環(huán)境大多數(shù)都是在可控制的空間里(比如開發(fā)公司自己的機房內(nèi))。
服務(wù)是公司和客戶的一種持續(xù)溝通和交互的過程,并非一個單向的發(fā)售行為,所以互聯(lián)網(wǎng)服務(wù)需要更多細(xì)致的運營和維護的工具,否則難以做到迅速而細(xì)致的滿足海量的互聯(lián)網(wǎng)用戶的需求。
小米的MIUI開發(fā)節(jié)奏
管理:手段.vs.工具在各種項目管理的課程里面,陳述了大量針對人去工作的方法。各種會議、報告、表格、評估、測量多不勝數(shù),然而軟件項目進(jìn)度的控制,依然是一個難度堪比登月的事情?!獙τ诤芏囗椖拷?jīng)理來說,程序員們基本是一個黑盒子,他們自己都不知道一個事情需要多長時間干完,就更別提別人怎么去預(yù)估和控制。這里最大的問題,我覺得是:我們往往總是想著怎樣“控制”住軟件項目的進(jìn)度,而忽視了如何減少不利于項目進(jìn)度的因數(shù)。實際上影響軟件開發(fā)進(jìn)度的主要因數(shù),一般有一下幾個:
程序員的能力水平。有一些項目其中的技術(shù),是程序員完全沒接觸過的類型,這里包含了學(xué)習(xí)、調(diào)試的時間。
開發(fā)過程中的各種修改變更。由于對可行性、需求確認(rèn)等方面的因數(shù),開發(fā)往往會走“回頭路”。有些項目做到一般會發(fā)現(xiàn)技術(shù)上不可行,需要修改需求;而另外一些項目是在項目做到一半甚至快完成的時候,需求方發(fā)現(xiàn)需要修改產(chǎn)品設(shè)計,因為在產(chǎn)品可體驗之前,完全無法想象到最后會是現(xiàn)在的樣子。
各種和開發(fā)無關(guān)的過程中的事務(wù)。這里包括開會、寫報告、溝通、等待開發(fā)電腦編譯、處理開發(fā)服務(wù)器故障、各種開發(fā)環(huán)境和測試環(huán)境的問題處理等等……這些事情往往都看起來不是非?!坝屑夹g(shù)含量”,但是實際上會嚴(yán)重影響開發(fā)進(jìn)度。因為開發(fā)工作需要一個穩(wěn)定、專心的工作環(huán)境,頻頻的被各種事務(wù)打斷,會讓程序員反復(fù)的花費時間去“進(jìn)入”工作狀態(tài)——面對成千上萬行程序代碼,要找到之前寫到哪個部分,其實不是那么簡單。
針對上面說的幾個問題,很多都可以通過應(yīng)用更好的開發(fā)工具來解決。比如一些新的需求類型,我們可以求助于互聯(lián)網(wǎng)上豐富的開源軟件和開源庫;面對需求變更,我們可以使用設(shè)計模式、單元測試等工具;開發(fā)中的事務(wù)問題,更是可以有大量業(yè)界先進(jìn)工具可用:SVN,Git,Jira,Project,IDE,Chef,Docker……
與其我們拿著鞭子抽打程序員,還不如給程序員更好的開發(fā)工具,這樣對于項目進(jìn)度的推動,其實更有好處。
資產(chǎn):代碼.vs.流程互聯(lián)網(wǎng)公司是由人組成的,人是會流動的,有一些小型的公司,往往會因為一兩個核心員工的離職,造成整個系統(tǒng)的代碼無法看懂,無法修改,從而最后導(dǎo)致公司完蛋。這種糟糕的情況,不止一次的出現(xiàn)過。然而,如果我們能有一套完善的開發(fā)流程,或者是習(xí)慣,以及配合良好的開發(fā)環(huán)境,加上有一定質(zhì)量的代碼,是完全能做到把項目代碼,在不同程序員之間順利交接的。可惜我們很多公司管理者,并不重視程序員用什么工具開發(fā)軟件,也不知道如何去提高代碼的可讀性,所以造成我們的項目特別害怕人員變動。如果我們把人員變動看成是一個必然會發(fā)生的事情,那么我們就會更重視整個代碼的開發(fā)環(huán)境和開發(fā)過程,從一開始就把開發(fā)規(guī)范確定下來,規(guī)定使用什么環(huán)境,應(yīng)用何種工具,并且堅持執(zhí)行,同時在實踐過程中不斷的改進(jìn)。只有這樣有預(yù)備的去做,最后才會保留的住公司真正的資產(chǎn)。
一家互聯(lián)網(wǎng)公司,我們在評估其開發(fā)資產(chǎn)的時候,并不應(yīng)看他“擁有”多少行代碼,因為這些代碼是無法直接賣錢的。而互聯(lián)網(wǎng)公司的開發(fā)速度,以及這個速度背后的能力才是最重要的。
敏捷開發(fā)的意義和實踐敏捷開發(fā)是我們現(xiàn)在最常見的一個“開發(fā)模式”,然而很多時候,我們看到“敏捷”兩個字,似乎就是讓程序員多加點班,或者忽略一些過程加快把代碼弄出來,而真正理解“敏捷”含義的并不多。實際上,敏捷并不會加快單位代碼的開發(fā)速度!敏捷最主要的目標(biāo),是應(yīng)對需求不明確和需求變更,而這兩者正式互聯(lián)網(wǎng)服務(wù)中最常見的情況。
需求變更的原因在互聯(lián)網(wǎng)服務(wù)中,由于沒有直接的“客戶”下單要求,所以很多需求,都是由公司內(nèi)部的人“代表”的,最典型的就是我們的“老板”們了。正式因為沒有明確的“下訂單”的過程,所以很多傳統(tǒng)的需求分析變得沒法做了,因為不管是老板還是產(chǎn)品經(jīng)理,都是面對著成千上萬的客戶去猜測他們的需求,如果他們自己能代表客戶還好,如果猜錯了,項目的代碼肯定要修改。很多互聯(lián)網(wǎng)公司都非常重視“數(shù)據(jù)”,原因就是這些“數(shù)據(jù)”往往代表了用戶對產(chǎn)品的看法,而這些看法成了互聯(lián)網(wǎng)產(chǎn)品設(shè)計的唯一客觀標(biāo)準(zhǔn)。然而這些數(shù)據(jù)本身,會包含了大量復(fù)雜性,由于統(tǒng)計方式、產(chǎn)品形態(tài)、季節(jié)時間等等,都會產(chǎn)生偏差。我們的項目需求,往往就是在這些偏差中確定。這就難免產(chǎn)生需求的變更了。
互聯(lián)網(wǎng)的客戶個體多,服務(wù)內(nèi)容豐富,功能變化快,是互聯(lián)網(wǎng)項目中需求變更很多的主要原因。因此這也讓敏捷開發(fā),成為互聯(lián)網(wǎng)項目開發(fā)中最重要的方法?!艚輳娬{(diào)的是用原型來驗證需求,在互聯(lián)網(wǎng)服務(wù)里就是,盡快推出服務(wù),通過數(shù)據(jù)來驗證想法。如果我們能越頻繁的修正原型,就能越快的接近真正的需求,也就是說,如果我們的互聯(lián)網(wǎng)服務(wù)能越快的修正各種問題,同時越快的推出新的版本,就能讓用戶越牢固的“黏在”這個服務(wù)上。
架構(gòu)設(shè)計實體化:單元測試敏捷開發(fā)講究要快速的修改代碼,我們往往會發(fā)現(xiàn),代碼修改的越頻繁,BUG越多,這似乎是一個無法解決的矛盾。然而,在敏捷開發(fā)方法論中,有一個重要的措施,就是用來防止這種修改造成的BUG增加的。這就是——單元測試。 單元測試本質(zhì)上,充當(dāng)著自動的QA人員的角色,如果我們把所有的設(shè)計和需求,都先按單元測試的形式“固化”編寫下來,那么我們在修改代碼后,就能快速的、自動的、反復(fù)的去驗證我們的代碼有沒有問題。如果這些測試足夠全面和詳細(xì),那么我們是不會擔(dān)心代碼修改導(dǎo)致大量的BUG的,因為單元測試會自動幫我們支出問題所在。一旦我們知道了問題,修正起來反而變成是最簡單的事情了。
假如一個項目的代碼丟失了,但全面的單元測試都還在,那么要重建這個項目并不困難,因為所有的需求,都被蘊含在這些測試代碼中,程序員們幾乎不需要去重新啃文檔,談需求,他們只要把代碼弄成能通過單元測試就好了。這種需求的“代表物”不但是程序員開發(fā)的概念和目標(biāo),而且還可以自動的幫程序員去驗證他們的實現(xiàn)。所以,如果你要使用敏捷開發(fā),要嘗試頻繁修改原型,就一定要使用TDD(測試驅(qū)動開發(fā)),特別是高度重視單元測試的作用。
統(tǒng)一軟件設(shè)計思路的重要性曾幾何時,我們認(rèn)為,使用什么語言開發(fā),用結(jié)構(gòu)化編程,還是面向?qū)ο缶幊獭@些一般人難以深入理解的事情,都是程序員這伙頑固的家伙的怪癖,基本屬于私人喜好的范疇。外人既不應(yīng)該深入干預(yù),也沒辦法去影響,因為如果你不識好歹去在這些事情上冒犯程序員,他們隨時可能一言不合就辭職。既然我們只需要可以運行的代碼,我們?yōu)槭裁疵帮L(fēng)險去激怒程序員呢?然而,在互聯(lián)網(wǎng)服務(wù)的開發(fā)過程中,代碼本身并不是某一個固定的、靜態(tài)的東西,它需要不斷的與時俱進(jìn),需要跟隨這業(yè)務(wù)的發(fā)展而變化,同時也會從某一個程序員手里,流向整個開發(fā)團隊。在這種情況下,軟件開發(fā)習(xí)慣、代碼的風(fēng)格、程序的設(shè)計思路,就變成一個非常重要的事情了。
代碼交流:面向?qū)ο?/b>確實現(xiàn)在還存在大量的討論,說“面向?qū)ο蟛皇侨f能的”。說得對,但是,世界上有什么東西是萬能的呢?我只能說,在需求變更非??斓那闆r下,面向?qū)ο笏枷耄乾F(xiàn)在我們能選擇的最好工具了。在“數(shù)據(jù)結(jié)構(gòu)+算法=程序”的時代,軟件主要是以計算任務(wù)為主,電腦是為了代替人腦進(jìn)行超乎想像的運算任務(wù)而存在。而在互聯(lián)網(wǎng)時代,軟件主要的任務(wù)已經(jīng)變成了處理這個真實世界的信息了。信息的存儲、交換的任務(wù),已經(jīng)遠(yuǎn)遠(yuǎn)超過了“計算”的任務(wù)數(shù)量。雖然我們知道,所謂的信息處理,最底層還是依賴大量的“計算”,然而,我們的程序員們,早已不再需要編寫大量“計算”的代碼,我們面臨的挑戰(zhàn),是如何用代碼準(zhǔn)確而快速的表達(dá)這個世界。
面向?qū)ο笏枷氚ǚ治?、設(shè)計、編碼三個部分(OOA/OOD/OOP)。這些思想看起來繁文縟節(jié),似乎非常啰嗦。然而,其核心思想?yún)s非常簡單:從表達(dá)過程,轉(zhuǎn)向表達(dá)對象。人類的思維中,對象、或物體,是一個個具備自己的信息特征的個體,而行為和過程,往往是依附于這些個體的。比如鳥會飛、賬號會鎖定、汽車會死火等等。所以如果我們的代碼,是以表達(dá)對象,把信息和行為統(tǒng)一起來,是最接近于我們的認(rèn)識規(guī)律的。
在互聯(lián)網(wǎng)開發(fā)領(lǐng)域,由于網(wǎng)絡(luò)無處不在,涉及到的領(lǐng)域異常廣泛,如果我們沒有一個能把代碼世界和現(xiàn)實世界聯(lián)系的紐帶,我們的項目將非常難以理解?!y以理解的項目,就難以變化,從而就失去了互聯(lián)網(wǎng)最顯著的特征。所以我認(rèn)為,面向?qū)ο蟮乃枷耄敲恳粋€互聯(lián)網(wǎng)開發(fā)人員都應(yīng)該理解的,并且應(yīng)該是面對大部分業(yè)務(wù)時,首先考慮選擇的。
代碼架構(gòu)與重構(gòu)我見過無數(shù)的代碼架構(gòu)圖,里面畫滿了進(jìn)程和服務(wù)器的拓?fù)?,各種線條上標(biāo)注了通訊協(xié)議,編碼格式,還有各種流程圖和協(xié)作圖,然而,這些架構(gòu)設(shè)計,無一例外的對于需求變更毫無幫助。因為它們描述的是一種現(xiàn)狀,甚至連現(xiàn)狀都不是,只是一種猜測,一種關(guān)于現(xiàn)狀的猜測。隨著項目代碼的不斷變化,代碼數(shù)量和關(guān)系都會膨脹,這種進(jìn)程、通訊級別的結(jié)構(gòu),除了越來越復(fù)雜以外,根本對于指導(dǎo)項目如何應(yīng)對各種“代碼腐化”毫無用處。
因此我們想到了流行的“重構(gòu)”,然而,如果我們只是重構(gòu)進(jìn)程的關(guān)系,通信的層次,那些錯綜復(fù)雜的代碼調(diào)用關(guān)系一樣存在。各種回調(diào)、事件、耦合還是讓代碼無法理解。我們只是在試圖把混亂塞到一些瓶子里面,并沒有解決混亂本身。所以,我們需要的另外一個思想武器:代碼結(jié)構(gòu)。只有我們從另外一個角度,另外一個視圖去觀察代碼,才能把握代碼之間耦合的情況。正如建筑里的平面圖和立面圖,都是不可或缺的。
所以我們應(yīng)該高度重視“代碼架構(gòu)”,也就是描述代碼之間的關(guān)系的架構(gòu),而不是進(jìn)程之間的關(guān)系的架構(gòu)。在關(guān)注代碼互相調(diào)用、耦合的關(guān)系上,我們能把混亂復(fù)雜的代碼關(guān)系理清,整理出一個便于理解,便于修改的代碼外觀。這些工作看起來完全是針對開發(fā)人員的,但是實際上,這些工作是能提高整個開發(fā)效率的。它能讓代碼從難以修改,變得容易修改,從而得以支持快速的業(yè)務(wù)需求變化,這是對業(yè)務(wù)、對產(chǎn)品最重要的支持能力。
持續(xù)集成的意義和實踐不管是敏捷開發(fā)的快速迭代,還是重構(gòu)系統(tǒng),我們都將頻繁的編譯代碼、部署、測試,也就是所謂的集成。如果我們的系統(tǒng)集成效率太低,那么快速的迭代可能變成慢速的迭代,重構(gòu)系統(tǒng)的頻率也會大大降低。有一些項目,每一次集成,都要最少經(jīng)歷兩三個小時,如果不順利的話,搞一個通宵都未必能完成?!鞍l(fā)版本”是很多程序員和運維管理人員的常見加班原因。對于這個問題,很多小型公司開始的時候,并沒有給與足夠的重視,認(rèn)為這些事情不過是程序員或者運維的本分工作之一,也是最日常的工作。真正得到出問題了,才發(fā)現(xiàn)重要性。
在任何一個互聯(lián)網(wǎng)應(yīng)用業(yè)務(wù)中,我們都會需要“發(fā)版”:出新功能、修改BUG、啟動運營活動、甚至是機房搬遷。所有的這些,如果沒有一套合適的工具來保障,每次發(fā)版都會是一場噩夢。所以持續(xù)集成(CI),很自然的成為互聯(lián)網(wǎng)企業(yè)中最流行的、研究最廣泛的技術(shù)之一。
所有資產(chǎn)納入版本管理持續(xù)集成的所有東西,都應(yīng)該來源于版本管理系統(tǒng)(SVN/Git)。除此之外,軟件資產(chǎn)不應(yīng)該存放在任何其他地方。版本管理系統(tǒng)應(yīng)該是開發(fā)團隊的保險箱和金庫,除了代碼以外,所有的數(shù)據(jù)文件,配置,腳本,文檔,都應(yīng)該放入這個保險庫。由于版本管理系統(tǒng)可以追溯到任何一個是時間點,這可以讓故障恢復(fù),問題回溯有良好的支持。
關(guān)于源代碼使用版本管理系統(tǒng),已經(jīng)有很長歷史了。但是互聯(lián)網(wǎng)服務(wù)中,除了代碼,還有很多其他的資源,比如圖片、數(shù)據(jù)、腳本等等。除了產(chǎn)品項目外,我們的很多額外系統(tǒng),比如運維工具、產(chǎn)品文檔等等,都是需要妥善保管的,這些也都應(yīng)該存放到版本管理系統(tǒng)中。
一般現(xiàn)在的版本管理系統(tǒng),都有“分支”的功能,簡單來說就是類似于“拷貝”了一份新的資源出來,在這之上的修改,可以由我們選擇合并到其他分支或者放棄。所以SVN的常用方案,是啟動三個類型的分支:trunk/branch/tag,專門針對“測試”、“開發(fā)”、“運營”。如果我們按預(yù)定的分支模型來設(shè)計版本管理系統(tǒng)的使用,那么我們的持續(xù)集成就可以很細(xì)致的選擇集成哪一個版本的內(nèi)容。
而在Git里面,每個使用者,都可以擁有自己的資源庫,這對于開發(fā)測試可以更加的靈活,但是對于使用者的要求更高一些:在不同的資源庫合并的過程中,需要更好的版本管理策略。持續(xù)集成系統(tǒng)可以自己擁有一個或者多個Git資源庫,這樣他們可以完全脫離版本管理服務(wù)器來獨立運行。
自動化部署我們曾經(jīng)無數(shù)次的登錄服務(wù)器,無數(shù)次的拷貝文件,無數(shù)次的修改配置,無數(shù)次的導(dǎo)入數(shù)據(jù)到數(shù)據(jù)庫,無數(shù)次的……如果我們對這些重復(fù),而且容易出錯的工作熟視無睹,我們將永遠(yuǎn)的被這些本該機器去做的事情困住。 自動化部署,是整個持續(xù)集成工作中最重要的步驟。當(dāng)我們每次發(fā)版都要很仔細(xì)的修改很多文件的時候,我們是無法避免在某次倒霉的事故后被挨批的。只有我們能把部署工作,也用我們的開發(fā)能力去解決,編寫自動部署工具之后,我們才真正的能提升部署這個事情到一個新的臺階————我們終于可不再擔(dān)心發(fā)版。
和自動化測試一樣,自動部署腳本,也是把一系列的技術(shù)需求,從紙面文檔+人手處理,改成用代碼實體化,并且可積累改善的方法。自動化部署工具在開源界也非常熱門,比如jekins,還有chef等等,都是為了解決部署問題而發(fā)明的軟件工具。也許對于你來說,自己用bash開發(fā)一套腳本才是合乎你的品味,但是不管怎樣,一定要有這樣的工具。就算要花費較長的開發(fā)時間,調(diào)動項目開發(fā)的程序員,一起來認(rèn)真的開發(fā)一段時間自動部署功能,都是非常值得的。因為從今以后,你就可以擁有一個自己的部署系統(tǒng),這個系統(tǒng)不但可以積累你的運營部署經(jīng)驗,還能加入很多錯誤、故障的自動檢查,讓你不再需要導(dǎo)出找“永遠(yuǎn)不出錯的”運維人員。
自動化部署系統(tǒng)中,最核心的部分就是配置管理。擁有一個對現(xiàn)有環(huán)境資源集中管理的數(shù)據(jù)倉庫是非常重要的。如果每個你的腳本可以識別自己所在的環(huán)境,以主動的方式去“申請”自己的配置文件和安裝任務(wù),是非常好的一個模式。因為從一個節(jié)點主動去分發(fā)程序,比不上多個節(jié)點向中心集群請求部署任務(wù),來的更容易穩(wěn)定。因為在節(jié)點上的部署代理程序,能更準(zhǔn)確的知道自己環(huán)境的情況,也可以做本地的測試。
自動化集成測試前面曾經(jīng)說過,敏捷開發(fā)非常依賴于自動化的單元測試。實際上持續(xù)集成,也非常依賴于自動化的集成測試。集成測試可以把自動化部署的結(jié)果進(jìn)行檢驗,避免手工進(jìn)行反復(fù)驗證。如果只有自動化部署,而沒有自動化測試,那么集成工作,其實還是非常浪費人力的。更重要的是,我們在每次“發(fā)版本”之后,總會擔(dān)心新的修改,導(dǎo)致一些舊的功能失效。這種問題實際上是很常見的,如果無法自動化的做這種回歸性的測試,那么我們每次發(fā)版還是要忍受漫長的測試工作進(jìn)度。
自動化集成測試也有很多開源的工具可供選擇,特別是基于B/S模式開發(fā)的WEB程序,但如果是手機APP的項目,或者客戶端C/S程序(比如網(wǎng)絡(luò)游戲),對于這類服務(wù)器系統(tǒng)的集成測試,往往需要我們自己根據(jù)業(yè)務(wù)來編寫測試程序。對于服務(wù)器系統(tǒng)來說,一般我們針對其通信協(xié)議編寫測試程序即可,而對于客戶端系統(tǒng),如果是GUI系統(tǒng)的,我們還可以根據(jù)GUI的內(nèi)部調(diào)度命令(安卓就有這樣的套件)來測試,但如果是類似游戲這類業(yè)務(wù),就只能用圖形識別技術(shù)了。
在持續(xù)集成的流程中,集成測試往往是最后一步的檢驗關(guān)口。如果集成測試失敗,應(yīng)該給所有關(guān)注集成的人員發(fā)送警報(實際上,如果成功也應(yīng)該報告)?,F(xiàn)在企業(yè)往往會用郵件、IM、微信、短信或者別的一些東西接收這種消息。
DevOps的意義和實踐在互聯(lián)網(wǎng)企業(yè)初始的階段,運維工作往往是服務(wù)器端開發(fā)人員兼任的。當(dāng)我在承擔(dān)這種既是開發(fā)又是運維的工作時,往往非常羨慕那些“開發(fā)、運維分離”的公司。因為作為開發(fā)人員,沒有三班倒的值班備份人力,往往是7X24小時的待命狀態(tài),工作壓力非常大。然而,當(dāng)我自己參與到一些真正開發(fā)、運維分離的項目的時候,卻發(fā)現(xiàn),項目運營事故中,最少有70%的事故,是由運維的原因造成的。
除了常見的硬件、網(wǎng)絡(luò)故障,操作系統(tǒng)配置出錯,日志清理出問題,部署配置搞錯,進(jìn)程不小心殺掉等等都出現(xiàn)過。看來服務(wù)器端開發(fā)和運維還真是難解難分,而DevOps的思想,就是為了努力解決這種矛盾。我們不應(yīng)該再把開發(fā)和運維對立起來,而應(yīng)該認(rèn)識到,運維是開發(fā)的一種延續(xù),運維的需求也是服務(wù)器端系統(tǒng)的功能需求;運維是開發(fā)的目地,便利的、通用的運維工具,本身是能提高開發(fā)效率的一種專業(yè)產(chǎn)品。
運維與開發(fā)的一體性:運維、運營、QA可以把DevOps看作開發(fā)(軟件工程)、技術(shù)運營和質(zhì)量保障(QA)三者的交集
一個互聯(lián)網(wǎng)軟件的上線運營,往往是由開發(fā)人員編寫出來,然后經(jīng)過QA人員測試,最后放在運營環(huán)境里進(jìn)行運營。這個過程并非是單向的過程,基于前文說的,互聯(lián)網(wǎng)服務(wù)都是在反復(fù)修改迭代中完善的,所以項目本身,一定是由多個版本,反復(fù)在開發(fā)、QA、運維之間循環(huán)交接。舉例來說,一個網(wǎng)絡(luò)游戲,在第一次開發(fā)出來后,都會經(jīng)過比較仔細(xì)的QA測試,然后通過運維人員進(jìn)行上線部署,最后由運營推廣人員進(jìn)行宣傳,同時也要配合這些宣傳開啟游戲內(nèi)部的一些功能,客服人員也會在開始運營后參與進(jìn)來,除了提供客戶咨詢外,抓作弊玩家和封帳號也會持續(xù)進(jìn)行。而作為開發(fā)人員的游戲策劃,立刻會關(guān)注游戲系統(tǒng)的各種統(tǒng)計數(shù)據(jù),以期在下一個版本中改善游戲設(shè)計。這個過程,可以看到在產(chǎn)品開發(fā)出來之后,整個團隊幾乎都還是需要以各種方式“使用”此服務(wù)器端系統(tǒng)的。所以我們在開發(fā)互聯(lián)網(wǎng)服務(wù)的時候,不能僅僅面向互聯(lián)網(wǎng)上的一般用戶,同時也需要考慮整個開發(fā)團隊的使用需求。
現(xiàn)代的互聯(lián)網(wǎng)軟件系統(tǒng)往往都帶有服務(wù)器端部分。而這些服務(wù)器程序需要7X24運行,因此產(chǎn)生了兩類非常明顯的需求:
運維需求:這類需求往往表現(xiàn)為非功能性需求,它要求服務(wù)器程序能夠適應(yīng)大規(guī)模用戶訪問和持續(xù)穩(wěn)定運行。
運營需求:這里需求通常是功能性需求,因為產(chǎn)品上線后,產(chǎn)品和運營、客服、測試人員,還需要持續(xù)不斷的使用這個系統(tǒng),和互聯(lián)網(wǎng)的海量用戶進(jìn)行互動。
運營:客服、活動在互聯(lián)網(wǎng)服務(wù)中,運營是一個非常重要的環(huán)節(jié)??蛻舫酥苯邮褂没ヂ?lián)網(wǎng)軟件的功能外,背后其實往往還有大量的從業(yè)人員在通過這個軟件提供服務(wù)。
其中最常見的就是客服服務(wù)??头钚枰氖遣樵児δ堋軌虿榈较到y(tǒng)中特定用戶的使用數(shù)據(jù),從而協(xié)助客戶解決問題??头牧硗庖粋€主要工作,是封帳號和封IP?,F(xiàn)在互聯(lián)網(wǎng)黑色產(chǎn)業(yè)鏈非常龐大,互聯(lián)網(wǎng)企業(yè)保護自己的手段其實不多,而客服是其中一個重要的環(huán)節(jié),避免黑色產(chǎn)業(yè)侵襲自己的利益,就需要互聯(lián)網(wǎng)服務(wù)系統(tǒng)有人工干預(yù)其數(shù)據(jù)的能力。
運營互聯(lián)網(wǎng)服務(wù)另外一個常見的行為就是“活動”,也就是開放一些限時的服務(wù)。就和超市一樣,互聯(lián)網(wǎng)服務(wù)也要定時或不定時的加入或關(guān)閉一些特別的服務(wù)。這些工作非常細(xì)致和瑣碎,需要服務(wù)器系統(tǒng)能夠提供人工參與或者機器定時啟動的一些功能。在《魔獸世界》這個網(wǎng)游中,大部分的活動都是自動的和定時的,可以從游戲里的一個日歷功能查到。而在國產(chǎn)的互聯(lián)網(wǎng)產(chǎn)品中,的很多是臨時加入,需要人工維護的,如“雙十一購物節(jié)”這種。這些對于服務(wù)器系統(tǒng)的版本更新,功能修改,都提出了更高的要求。
因此一般我們在設(shè)計互聯(lián)網(wǎng)服務(wù)系統(tǒng)的時候,就應(yīng)該一開始就把運營需求,也作為版本目標(biāo)納入開發(fā)計劃中。一些比較好的團隊,會抽象和總結(jié)同類互聯(lián)網(wǎng)項目(比如游戲、電商類型)在客服、運營活動上的共性,形成一套標(biāo)準(zhǔn)的服務(wù)規(guī)范以及實現(xiàn)這個規(guī)范的接口。由互聯(lián)網(wǎng)服務(wù)開發(fā)團隊去實現(xiàn)這些規(guī)范的接口,提供功能上的支持,而另外一個運營開發(fā)小組,則負(fù)責(zé)根據(jù)這個接口,開發(fā)供運營團隊人員使用的界面、內(nèi)部管理系統(tǒng)等。比如游戲的運營規(guī)范會要求游戲提供查詢角色區(qū)服、帳號的名字、等級等數(shù)據(jù),提供接口在游戲中發(fā)布任務(wù);電商系統(tǒng)的運營規(guī)范會要求網(wǎng)店提供本店銷售排行查詢、優(yōu)惠券折扣接口等等。
運維:部署(虛擬機)、監(jiān)控、統(tǒng)計作為非功能性的需求來說,部署需求是第一位的。頻繁的部署是互聯(lián)網(wǎng)服務(wù)快速演變的基礎(chǔ)能力。另外,互聯(lián)網(wǎng)用戶的增加(和消退)也是非常迅速的,這導(dǎo)致了我們可能需要快速的進(jìn)行服務(wù)器擴容,或者縮容。這種情況都需要涉及到部署。所以我們在開發(fā)服務(wù)器系統(tǒng)的時候,部署需求是第一個需要考慮。加上如果我們希望實行持續(xù)集成,那么就更加需要重視部署的能力。作為服務(wù)器端系統(tǒng),如果被設(shè)計成帶有非常復(fù)雜的進(jìn)程種類和進(jìn)程通訊關(guān)系的話,要做好部署就會變得更加復(fù)雜。加上可能部署的環(huán)境還不統(tǒng)一,可能出現(xiàn)的問題就更復(fù)雜了。所以現(xiàn)在有大量的技術(shù)嘗試改善這個方面。首先被大家廣泛接受的是虛擬機技術(shù),也就是所謂云服務(wù)器(IAAS),這種技術(shù)能讓你無需直接操作硬件,不用扛機器到機房來進(jìn)行部署,是一種巨大的進(jìn)步。
而后現(xiàn)在我們有了Docker這種基于Linux容器技術(shù)的工具,這可以把服務(wù)器操作系統(tǒng)層的差異環(huán)境,都統(tǒng)一成一個個image文件,部署的時候只要運行image文件即可。但是這些依然無法簡化錯綜復(fù)雜的服務(wù)器進(jìn)程關(guān)系,所以現(xiàn)在有了各種“隊列服務(wù)”技術(shù),比如Kafka,RabbitMQ, ActiveMQ等等,這些隊列服務(wù)把進(jìn)程間通訊簡化成專門的服務(wù),減少了部署的復(fù)雜性。而ZooKeeper的廣泛使用,讓我們在多進(jìn)程間協(xié)調(diào)和監(jiān)控有了更多的手段。在具體部署工具方面,Chef這一類軟件做了各種有益的嘗試,這些都是能讓我們優(yōu)化部署需求功能的工具。
互聯(lián)網(wǎng)服務(wù)的24X7持續(xù)服務(wù)能力,實際上會收到各種挑戰(zhàn),除了版本發(fā)布可能導(dǎo)致的問題外,在大量機器硬件里面,硬件故障率是一個固定的比例。網(wǎng)絡(luò)抖動,機房線路故障也常常會出現(xiàn)。更容易出現(xiàn)的是異常的用戶訪問波動:一大波用戶洶涌而來,但是也有可能是DDOS攻擊。不管怎樣,你都需要隨時掌握服務(wù)器系統(tǒng)的工作狀態(tài)。這時你就需要一個監(jiān)控系統(tǒng),但如果產(chǎn)品上線才發(fā)現(xiàn)要做,那往往已經(jīng)很遲了。因為一個系統(tǒng)是否有問題,并不是簡單的從內(nèi)存、CPU、網(wǎng)卡流量就能看出端倪的,我們往往需要在服務(wù)開發(fā)之初,就定義好各種需要監(jiān)控的指標(biāo),傳統(tǒng)常見的指標(biāo)有:每秒主循環(huán)的次數(shù)、每秒處理業(yè)務(wù)包的次數(shù)、服務(wù)器中緩存的會話數(shù)等等……一些做的好的系統(tǒng),還會有很多業(yè)務(wù)層面的監(jiān)控指標(biāo),比如某個特定服務(wù)的處理效率、處理成功率等等。
既然一個系統(tǒng)有大量的監(jiān)控指標(biāo),就涉及如何生成和管理這些數(shù)據(jù)的問題。傳統(tǒng)的做法是在系統(tǒng)中“埋入”這些監(jiān)控程序,系統(tǒng)一邊運行一邊統(tǒng)計這些指標(biāo),然后定時生成日志或者通過網(wǎng)絡(luò)上報給某個監(jiān)控系統(tǒng)。但是這種做法的缺點是:如果你需要更多的指標(biāo),或者修改指標(biāo)的統(tǒng)計方法,你就被迫要修改代碼,重啟服務(wù),這樣會影響正在運行的服務(wù)。現(xiàn)在另外一個做法是,由系統(tǒng)把運行的原始信息記錄成日志,然后把日志集中上報到一個監(jiān)控系統(tǒng)中,這個監(jiān)控系統(tǒng)一般都帶有分布式的文件存儲系統(tǒng)和分布式計算統(tǒng)計能力。在搜集到大量實時日志的同時,這個系統(tǒng)根據(jù)預(yù)設(shè)的指標(biāo)統(tǒng)計方法,不停的進(jìn)行日志統(tǒng)計,一旦發(fā)現(xiàn)統(tǒng)計結(jié)果有問題,就會報警。而這種統(tǒng)計由于是在大數(shù)據(jù)處理能力的平臺上生成的,所以往往發(fā)現(xiàn)問題的時間差能縮小到分鐘級甚至秒級。這種做法由于搜集的是原始日志記錄,所以就可以靈活的在系統(tǒng)運行時定制很多統(tǒng)計和報警的策略,但完全不會增加服務(wù)系統(tǒng)的壓力,也不需要修改服務(wù)系統(tǒng)的代碼。
最后說說統(tǒng)計,任何一個互聯(lián)網(wǎng)系統(tǒng),都是在用戶的使用中不斷優(yōu)化的,這個優(yōu)化的依據(jù),最重要的客觀依據(jù),就是統(tǒng)計數(shù)據(jù)。而統(tǒng)計數(shù)據(jù),一般由兩部分構(gòu)成:
用戶的行為數(shù)據(jù)。比如登錄行為,就可以給系統(tǒng)留下用戶的IP、登錄時間、登出時間等數(shù)據(jù);購買行為,就可以留下購買商品,購買價格,購買時間這些數(shù)據(jù)。
根據(jù)用戶的行為的關(guān)聯(lián),統(tǒng)計出來的數(shù)據(jù)。比如根據(jù)登錄行為,我們可以統(tǒng)計出用戶的在線時長,用戶重復(fù)登錄的次數(shù),用戶重復(fù)登錄的間隔,還有什么次日存留、七天存留等等……;根據(jù)購買行為,我們更是可以整理出用戶的購買商品傾向,ARPU值,甚至同類用戶的購買共性,這些也是所謂大數(shù)據(jù)做商品統(tǒng)計的主要方向。
根據(jù)上面的分析,我們可以發(fā)現(xiàn),實際上統(tǒng)計系統(tǒng)也是應(yīng)該分兩個部分設(shè)計,一個是盡量記錄用戶行為的基礎(chǔ)數(shù)據(jù),第二個是以復(fù)雜多變的統(tǒng)計條件,去挖掘這些用戶行為數(shù)據(jù)中包含的規(guī)律。對于第一部分,一個可以存放海量日志數(shù)據(jù)的分布式存儲系統(tǒng)非常重要;對于第二部分,分布式的統(tǒng)計運算系統(tǒng)是必不可少的。對于這個體系,Google的Hadoop提供了業(yè)界的示范。但是如果你愿意,也可以使用這個思路自己來建設(shè)自己的統(tǒng)計系統(tǒng),也許你的數(shù)據(jù)量無需要用到Hadoop那么復(fù)雜。
總結(jié)互聯(lián)網(wǎng)開發(fā)模式,是針對于互聯(lián)網(wǎng)本質(zhì)上是一個“服務(wù)”而發(fā)展起來的。因為是“服務(wù)”而不是產(chǎn)品,所以應(yīng)對快速變化的能力是最高的技術(shù)標(biāo)準(zhǔn)。我們傾向采用更適合表達(dá)需求的軟件開發(fā)技術(shù)、自動化程度更高的開發(fā)工具,來提高我們的開發(fā)效率,而不是靠單純的“激勵主觀能動性”來做管理。
因此我們在基于自動化測試、自動化部署等持續(xù)集成工具的平臺上,使用重視原型迭代的方法來開發(fā)項目,在反復(fù)以原型確認(rèn)需求,以及適應(yīng)需求變化的過程中,逐步的完善整個開發(fā)生產(chǎn)線。并且把開發(fā)和運營視為一個整體,在服務(wù)的運營過程中,不斷的完善互聯(lián)網(wǎng)服務(wù)的運營工具,讓開發(fā)和運營在同一個生命周期里生長。
此文已由作者授權(quán)騰訊云+社區(qū)在各渠道發(fā)布
獲取更多新鮮技術(shù)干貨,可以關(guān)注我們騰訊云技術(shù)社區(qū)-云加社區(qū)官方號及知乎機構(gòu)號
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/42982.html
摘要:阿里巴巴的共享服務(wù)理念以及企業(yè)級互聯(lián)網(wǎng)架構(gòu)建設(shè)的思路,給這些企業(yè)帶來了不少新的思路,這也是我最終決定寫這本書的最主要原因。盡在雙阿里巴巴技術(shù)演進(jìn)與超越是迄今唯一由阿里巴巴集團官方出品全面闡述雙八年以來在技術(shù)和商業(yè)上演進(jìn)和創(chuàng)新歷程的書籍。 showImg(https://segmentfault.com/img/remote/1460000015386860); 1、大型網(wǎng)站技術(shù)架構(gòu):核...
摘要:架構(gòu)設(shè)計實體化單元測試敏捷開發(fā)講究要快速的修改代碼,我們往往會發(fā)現(xiàn),代碼修改的越頻繁,越多,這似乎是一個無法解決的矛盾。 本文由云+社區(qū)發(fā)表,作者:韓偉 互聯(lián)網(wǎng)開發(fā)的核心問題 當(dāng)我1999年進(jìn)入互聯(lián)網(wǎng)行業(yè)工作的時候,華為剛剛通過了著名的CMM認(rèn)證。當(dāng)時作為一個小程序員,非常向往業(yè)界經(jīng)典的軟件開發(fā)模式。因為看上去,如果企業(yè)實行了CMM,我們程序員就不用再天天為了老板一個拍腦袋的主意而加班...
摘要:鑒于目前大多數(shù)服務(wù)器環(huán)境都是,提前接觸能夠相輔相成。正則也是必須要掌握的一個知識點。有多種創(chuàng)建多線程的方式,不過目前使用線程池的多一些。 原創(chuàng):小姐姐味道(微信公眾號ID:xjjdog),歡迎分享,轉(zhuǎn)載請保留出處。 你可能有所感悟。零散的資料讀了很多,但是很難有提升。到處是干貨,但是并沒什么用,簡單來說就是缺乏系統(tǒng)化。另外,噪音太多,雷同的框架一大把,我不至于全都要去學(xué)了吧。 這里,我...
2020年發(fā)生的眾多事件讓對2021年的大多數(shù)預(yù)測浮出水面。人工智能(AI)和物聯(lián)網(wǎng)(IoT)等熱門技術(shù)趨勢仍將在明年重塑我們生活的方式。然而,最重要的用處是幫助我們在這個不斷變化的時代下適應(yīng)和生存。沒有什么趨勢比云計算更重要。云是數(shù)據(jù)驅(qū)動、基于應(yīng)用程序的技術(shù)生態(tài)系統(tǒng)的支柱,在幫助我們管理這種變化方面起著至關(guān)重要的作用。云服務(wù)徹底改變了從聯(lián)系人追蹤到家庭遞送服務(wù)、遠(yuǎn)程醫(yī)療和遠(yuǎn)程辦公以及娛樂的一切。...
閱讀 873·2021-11-19 11:29
閱讀 3363·2021-09-26 10:15
閱讀 2874·2021-09-22 10:02
閱讀 2447·2021-09-02 15:15
閱讀 1983·2019-08-30 15:56
閱讀 2426·2019-08-30 15:54
閱讀 2929·2019-08-29 16:59
閱讀 646·2019-08-29 16:20