目錄
對于軟件架構(gòu)來說,我覺得第一重要的是架構(gòu)的收益,如果不說收益,只是為了技術(shù)而技術(shù),而沒有任何意義。對于技術(shù)收益來說,我覺得下面這幾個收益是非常重要的:
是否可以降低技術(shù)門檻加快整個團(tuán)隊(duì)的開發(fā)流程。能夠加快整個團(tuán)隊(duì)的工程流程,快速發(fā)布,是軟件工程一直在解決的問題,所以,系統(tǒng)架構(gòu)需要能夠進(jìn)行并行開發(fā),并行上線和并行運(yùn)維,而不會讓某個團(tuán)隊(duì)成為瓶頸點(diǎn)。(注:就算拖累團(tuán)隊(duì)的原因是組織構(gòu)架,也不妨礙我們做出并行的系統(tǒng)架構(gòu)設(shè)計(jì))
是否可以讓整個系統(tǒng)可以運(yùn)行的更穩(wěn)定。要讓整個系統(tǒng)可以運(yùn)行的更為的穩(wěn)定,提升整個系統(tǒng)的 SLA,就需要對有計(jì)劃和無計(jì)劃的停機(jī)做相應(yīng)的解決方案(參看《關(guān)于高可用的架構(gòu)》)
是否可以通過簡化和自動化降低成本。最高優(yōu)化的成本是人力成本,人的成本除了慢和貴,還有經(jīng)常不斷的 human error。如果不能降低人力成本,反而需要更多的人,那么這個架構(gòu)設(shè)計(jì)一定是失敗的。除此之外,是時(shí)間成本,資金成本。
如果一個系統(tǒng)架構(gòu)不能在上面三個事上起到作用,那就沒有意義了。
國內(nèi)很多公司都會有很多分工,基本上都會分成運(yùn)維和開發(fā),運(yùn)維又會分成基礎(chǔ)運(yùn)維和應(yīng)用運(yùn)維,開發(fā)則會分成基礎(chǔ)核心開發(fā)和業(yè)務(wù)開發(fā)。不同的分工會導(dǎo)致完全不同的視角和出發(fā)點(diǎn)。比如,基礎(chǔ)運(yùn)維和開發(fā)的同學(xué)更多的只是關(guān)注資源的利用率和性能,而應(yīng)用運(yùn)維和業(yè)務(wù)開發(fā)則更多關(guān)注的是應(yīng)用和服務(wù)上的東西。這兩者本來相關(guān)無事,但是因?yàn)榉植际郊軜?gòu)的演進(jìn),導(dǎo)致有一些系統(tǒng)已經(jīng)說不清楚是基礎(chǔ)層的還是應(yīng)用層的了,比如像服務(wù)治理上的東西,里面即有底層基礎(chǔ)技術(shù),也需要業(yè)務(wù)的同學(xué)來配合,包括 k8s 也樣,里面即有底層的如網(wǎng)絡(luò)這樣的技術(shù),也有需要業(yè)務(wù)配合的 readniess和 liveness 這樣的健康檢查,以及業(yè)務(wù)應(yīng)用需要 configMap 等等 ……
這些東西都讓我感覺到所謂 DevOps,其實(shí)就是因?yàn)楹芏嗉夹g(shù)和組件已經(jīng)分不清是 Dev 還是 Ops 的了,所以,需要合并 Dev和 Ops。而且,整個組織和架構(gòu)的優(yōu)化,已經(jīng)不能通過調(diào)優(yōu)單一分工或是單一組件能夠有很大提升的了。其需要有一種自頂向下的,整體規(guī)劃,統(tǒng)一設(shè)計(jì)的方式,才能做到整體的提升(可以試想一下城市交通的優(yōu)化,當(dāng)城市規(guī)模到一定程度的時(shí)候,整體的性能你是無法通過優(yōu)化幾條路或是幾條街區(qū)來完成的,你需要對整個城市做整體的功能體的規(guī)劃才可能達(dá)到整體效率的提升)。而為了做到整體的提升,需要所有的人都要有一個統(tǒng)一的視角和目標(biāo),這幾年來,我覺得這個目標(biāo)就是——要站在服務(wù)和 對外API的視角來看問題,而不是技術(shù)和底層的角度。
技術(shù)選型是一件很重要的事,技術(shù)一旦選錯,那會導(dǎo)致整個架構(gòu)需要做調(diào)整,而對架構(gòu)的調(diào)整重來都不是一件簡單的事,我在過去幾年內(nèi),當(dāng)系統(tǒng)越來越復(fù)雜的時(shí)候,用戶把他們的 PHP,Python, .NET,或 Node.js 的架構(gòu)完全都遷移到 Java + Go 的架構(gòu)上來的案例不斷的發(fā)生。這個過程還是非常痛苦的,但是你沒有辦法,當(dāng)你的系統(tǒng)越來越復(fù)雜,越來越大時(shí),你就再也不能在一些玩具技術(shù)上玩了,你需要的更為工業(yè)化的技術(shù)。
盡可能的使用更為成熟更為工業(yè)化的技術(shù)棧,而不是自己熟悉的技術(shù)棧。所謂工業(yè)化的技術(shù)棧,你可以看看大多數(shù)公司使用的技術(shù)棧,比如:互聯(lián)網(wǎng),金融,電信……等等 ,大公司會有更多的技術(shù)投入,也需要更大規(guī)模的生產(chǎn),所以,他們使用的技術(shù)通常來說都是比較工業(yè)化的。在技術(shù)選型上,千萬不要被——“你看某個公司也在用這個技術(shù)”,或是一些在論壇上看到的一些程序員吐槽技術(shù)的觀點(diǎn)(沒有任何的數(shù)據(jù),只有自己的喜好)來決定自己的技術(shù),還是看看主流大多數(shù)公司實(shí)際在用的技術(shù)棧,會更靠譜一些。
選擇全球流行的技術(shù),而不是中國流行的技術(shù)。技術(shù)這個東西一定是一個全球化的東西,不是一個局域化的事。所以,一定要選國際化的會更好。另外,千萬不要被某些公司的“特別案例”騙過去了,那怕這個案例很性感,關(guān)鍵還是要看解決問題的思路和采用的技術(shù)是否具有普世性。只有普世性的技術(shù)有更強(qiáng)的生命力。
盡可能的使用紅利大的主流技術(shù),而不要自己發(fā)明輪子,更不要魔改。我見過好些個公司魔改開源軟件,比如有個公司同魔改mesos,最后改著改著發(fā)現(xiàn)自己發(fā)明另一個 kubernetes。我還見過很多公司或技術(shù)團(tuán)隊(duì)喜歡自己發(fā)明自己的專用輪子,最后都會被主流開源軟件所取代。完全沒有必要。不重新發(fā)明輪子,不魔改,不是因?yàn)樽约杭夹g(shù)不能,而是因?yàn)?,這個世界早已不是自己干所有事的年代了,這個時(shí)代是要想盡方法跟整個產(chǎn)業(yè),整個技術(shù)社區(qū)融合和合作,這樣才會有最大的收益。那些試圖因?yàn)槟硞€特例需要自成一套的玩法,短期沒問題,但長期來說,我都不看好。
絕大多數(shù)情況下,如無非常特殊要求,選 Java基本是不會錯的。一方面,這是因?yàn)?Java 的業(yè)務(wù)開發(fā)的生產(chǎn)力是非常好的,而且有 Spring 框架保障,代碼很難寫爛,另外,Java 的社區(qū)太成熟了,你需要的各種架構(gòu)和技術(shù)都可以很容易獲得,技術(shù)紅利實(shí)在是太大。這種運(yùn)行在JVM上的語言有太多太多的好處了。在 Java 的技術(shù)棧上,你的架構(gòu)風(fēng)險(xiǎn)和架構(gòu)的成本(無論是人力成本,時(shí)間成本和資金成本)從長期來說都是最優(yōu)的
在我見過的公司中,好些公司的架構(gòu)都被技術(shù)負(fù)責(zé)人個人的喜好、擅長和個人經(jīng)驗(yàn)給綁架了,完全不是從一個客觀的角度來進(jìn)行技術(shù)選型。其實(shí),從 0 到 1 的階段,你用什么樣的技術(shù)都行,如果你做一個簡單的應(yīng)用,沒有事務(wù)處理沒有復(fù)雜的交易流程,比如一些論壇、社交之類的應(yīng)用,你用任何語言都行。但是如果有一天你的系統(tǒng)變復(fù)雜了,需要處理交易了,量也上來了,從 1 到 10,甚至從 10 到 100,你的開發(fā)團(tuán)隊(duì)也變大了,需要構(gòu)建的系統(tǒng)越來越大,你可能會發(fā)現(xiàn)你只有一個選擇,就是 Java。想想京東從.NET 到 Java,淘寶從 PHP 到 Java……
注,一些有主觀喜好的人一定會對我上述對 Java 的描述感到不適,我還用一些證據(jù)說明一下——全中國所有的電商平臺,幾百家銀行,三大電信運(yùn)營商,所有的保險(xiǎn)公司,劵商的系統(tǒng),醫(yī)院里的系統(tǒng),電子政府系統(tǒng),等等,基本都是用 Java 開發(fā)的,包括 AWS 的主流語言也是 Java,阿里云一開始用 C++/Python 寫控制系統(tǒng),后面也開始用 Java ……你可能會說 B站是用 go語言,但是你可能不知道 B 站的電商和大數(shù)據(jù)是用 Java……懂著數(shù)據(jù)分析的同學(xué),建議上各大招聘網(wǎng)站上搜一下 Java 的職位數(shù)量,你就知道某個技術(shù)是否主流和熱門……
我發(fā)現(xiàn)好些公司的架構(gòu)師做架構(gòu)的時(shí)候,首要考慮的是架構(gòu)的性能是否能夠撐得住多大多大的流量,而不是考慮系統(tǒng)的完備性和擴(kuò)展性。所以,我已經(jīng)多次見過這樣的案例了,一開始直接使用 MongoDB 這樣的非關(guān)系型數(shù)據(jù)庫,或是把數(shù)據(jù)直接放在 Redis 里,而直接放棄關(guān)系型數(shù)據(jù)庫的數(shù)據(jù)完備性的模型,而在后來需要在數(shù)據(jù)上進(jìn)行關(guān)系查詢的時(shí)候,發(fā)現(xiàn) NoSQL 的數(shù)據(jù)庫在 Join 上都表現(xiàn)的太差,然后就開始各種飛線,為了不做 Join 就開始冗余數(shù)據(jù),然而自己又維護(hù)不好冗余數(shù)據(jù)后帶來的數(shù)據(jù)一致性的問題,導(dǎo)致數(shù)據(jù)上的各種錯亂丟失。
所以,我給如下的一些如下的架構(gòu)原則:
使用最科學(xué)嚴(yán)謹(jǐn)?shù)募夹g(shù)模型為主,并以不嚴(yán)謹(jǐn)?shù)哪P妥鳛檠a(bǔ)充。對于上面那個案例來說,就是——永遠(yuǎn)使用完備支持 ACID 的關(guān)系型數(shù)據(jù)庫,然后用 NoSQL 作補(bǔ)充,而不是完全放棄關(guān)系型數(shù)據(jù)庫。這里的原則就是所謂的“先緊后松”,一開始緊了,你可以慢慢松,但是開始松了,以后你想緊再也緊不過來了。
性能上的東西,總是有很多解的。我這么多年的經(jīng)歷告訴我,性能上的事,總是有解的,手段也是最多的,這個比起架構(gòu)的完備性和擴(kuò)展性來說真的不必太過擔(dān)心。
為了追求所謂的性能,把整個系統(tǒng)的完備性丟失掉,相當(dāng)?shù)氐貌粌斒А?/p>
這個原則是非常重要的,因?yàn)橹挥蟹牧藰?biāo)準(zhǔn),你的架構(gòu)才能夠有更好的擴(kuò)展性。比如:我經(jīng)常性的見到很多公司的系統(tǒng)既沒有服從業(yè)界標(biāo)準(zhǔn),也沒有形成自己公司的標(biāo)準(zhǔn),感覺就像一群烏合之眾一樣。最典型的例子就是 HTTP 調(diào)用的狀態(tài)返回碼。業(yè)內(nèi)給你的標(biāo)準(zhǔn)是 200表示成功,3xx 跳轉(zhuǎn),4xx 表示調(diào)用端出錯,5xx 表示服務(wù)端出錯,我實(shí)在是不明白為什么無論成功和失敗大家都喜歡返回 200,然后在 body 里指出是否error(前兩年我在微信公眾號里看到一個有一定名氣的互聯(lián)網(wǎng)老兵推薦使用無論正確還是出錯都返回 200 的做法,我在后臺再三確認(rèn)后,我發(fā)現(xiàn)這樣的架構(gòu)師真是害人不淺)。這樣做最大的問題是——監(jiān)控系統(tǒng)將在一種低效的狀態(tài)下工作。監(jiān)控系統(tǒng)需要把所有的網(wǎng)絡(luò)請求包打開后才知道是否是錯誤,而且完全不知道是調(diào)用端出錯還是服務(wù)端出錯,于是一些像重試或熔斷這樣的控制系統(tǒng)完全不知道怎么搞(如果是 4xx錯,那么重試或熔斷是沒有意義的,只有 5xx 才有意義)。有時(shí)候,我會有種越活越退步的感覺,錯誤碼設(shè)計(jì)這種最基本最基礎(chǔ)的東西為什么會沒有?并且一個公司會任由著大家亂來?這些基礎(chǔ)技能怎么就這樣丟掉了?
還有,我還見過一些公司,他們整個組織沒有一個統(tǒng)一的用戶 ID 的設(shè)計(jì),各個系統(tǒng)之間同步用戶的數(shù)據(jù)是通過用戶的身份證 ID,是的,就是現(xiàn)實(shí)世界的身份證 ID,包括在網(wǎng)關(guān)上設(shè)置的用戶白名單居然也是用身份證 ID。我對這個公司的內(nèi)的用戶隱私管理有很大的擔(dān)憂。一個企業(yè),一個組織,如果沒有標(biāo)準(zhǔn)和規(guī)范,也就會有抽象,這一定是要出各種亂子的。
下面,我羅列一些你需要注意的標(biāo)準(zhǔn)和規(guī)范(包括但不限于):
服務(wù)間調(diào)用的協(xié)議標(biāo)準(zhǔn)和規(guī)范。這其中包括 Restful API路徑, HTTP 方法、狀態(tài)碼、標(biāo)準(zhǔn)頭、自定義頭等,返回?cái)?shù)據(jù) JSon Scheme……等。
一些命名的標(biāo)準(zhǔn)和規(guī)范。這其中包括如:用戶 ID,服務(wù)名、標(biāo)簽名、狀態(tài)名、錯誤碼、消息、數(shù)據(jù)庫……等等
日志和監(jiān)控的規(guī)范。這其中包括:日志格式,監(jiān)控?cái)?shù)據(jù),采樣要求,報(bào)警……等等
配置上的規(guī)范。這其中包括:操作系統(tǒng)配置、中間件配置,軟件包……等等
中間件使用的規(guī)范。數(shù)據(jù)庫,緩存、消息隊(duì)列……等等
軟件和開發(fā)庫版本統(tǒng)一。整個組織架構(gòu)內(nèi),軟件或開發(fā)庫的版本最好每年都升一次級,然后在各團(tuán)隊(duì)內(nèi)統(tǒng)一。
這里重要說一下兩個事:
Restful API 的規(guī)范。我覺得是非常重要的,這里給兩個我覺得寫得最好的參考:Paypal 和 Microsoft 。Restful API 有一個標(biāo)準(zhǔn)和規(guī)范最大的好處就是監(jiān)視可以很容易地做各種統(tǒng)計(jì)分析,控制系統(tǒng)可以很容易的做流量編排和調(diào)度。
另一個是服務(wù)調(diào)用鏈追蹤。對于服務(wù)調(diào)用鏈追蹤來說,基本上都是參考于 Google Dapper 這篇論文,目前有很多的實(shí)現(xiàn),最嚴(yán)格的實(shí)現(xiàn)是 Zipkin,這也是 Spring Cloud Sleuth 的底層實(shí)現(xiàn)。Zipkin 貼近 Google Dapper 論文的好處在于——無狀態(tài),快速地把 Span 發(fā)出來,不消耗服務(wù)應(yīng)用側(cè)的內(nèi)存和 CPU。這意味著,監(jiān)控系統(tǒng)寧可自己死了也不能干擾實(shí)際應(yīng)用。
軟件升級。我發(fā)現(xiàn)很多公司包括 BAT,他們完全沒有軟件升級的活動,全靠開發(fā)人員自發(fā)。然而,這種成體系的活動,是永遠(yuǎn)不可能靠大眾的自發(fā)形成的。一個公司至少一年要有一次軟件版本升級的review,然后形成軟件版本的統(tǒng)一和一致,這樣會極太簡化系統(tǒng)架構(gòu)的復(fù)雜度。
在我見過很多架構(gòu)里,技術(shù)人員只考慮當(dāng)下,但從來不考慮系統(tǒng)的未來擴(kuò)展性和可運(yùn)維性。所謂的管生不管養(yǎng)。如果你生下來的孩子胳膊少腿,嚴(yán)重畸形,那么未來是很難玩的。因?yàn)榧軜?gòu)和軟件不是寫好就完的,是需要不斷修改不斷維護(hù)的,80%的軟件成本都是在維護(hù)上。所以,如何讓你的架構(gòu)有更好的擴(kuò)展性,可以更容易地運(yùn)維,這個是比較重要的。所謂的擴(kuò)展性,意味著,我可以很容易地加更多的功能,或是加入更多的系統(tǒng),而所謂可運(yùn)維,就是說我可以對線上的系統(tǒng)做任意的變更。擴(kuò)展性要求的是有標(biāo)準(zhǔn)規(guī)范且不耦合的業(yè)務(wù)架構(gòu),可運(yùn)維性要求的則是可控的能力,也就是一組各式各樣的控制系統(tǒng)。
通過服務(wù)編排架構(gòu)來降低服務(wù)間的耦合。比如:通過一個業(yè)務(wù)流程的專用服務(wù),或是像 Workflow,Event Driven Architecture , Broker,Gateway,Service Discovery 等這類的的中間件來降低服務(wù)間的依賴關(guān)系。
通過服務(wù)發(fā)現(xiàn)或服務(wù)網(wǎng)關(guān)來降低服務(wù)依賴所帶來的運(yùn)維復(fù)雜度。服務(wù)發(fā)現(xiàn)可以很好的降低相關(guān)依賴服務(wù)的運(yùn)維復(fù)雜度,讓你可以很輕松的上線或下線服務(wù),或是進(jìn)行服務(wù)伸縮。
一定要使用各種軟件設(shè)計(jì)的原則。比如:像SOLID這樣的原則(參看《一些軟件設(shè)計(jì)的原則》),IoC/DIP,SOA 或 Spring Cloud 等 架構(gòu)的最佳實(shí)踐(參看《SteveY對Amazon和Google平臺的吐槽》中的 Service Interface 的那幾條軍規(guī)),分布式系統(tǒng)架構(gòu)的相關(guān)實(shí)踐(參看:《分布式系統(tǒng)的事務(wù)處理》,或微軟件的 《Cloud Design Patterns》)……等等
所有的程序都會有兩種邏輯,一種是業(yè)務(wù)邏輯,一種是控制邏輯,業(yè)務(wù)邏輯就是完成業(yè)務(wù)的邏輯,控制邏輯是輔助,比如你用多線程,還是用分布式,是用數(shù)據(jù)庫還是用文件,如何配置、部署,運(yùn)維、監(jiān)控,事務(wù)控制,服務(wù)發(fā)現(xiàn),彈性伸縮,灰度發(fā)布,高并發(fā),等等,等等 ……這些都是控制邏輯,跟業(yè)務(wù)邏輯沒有一毛錢關(guān)系??刂七壿嫷募夹g(shù)深度會通常會比業(yè)務(wù)邏輯要深一些,門檻也會要高一些,所以,最好要專業(yè)的程序員來負(fù)責(zé)控制邏輯的開發(fā),統(tǒng)一規(guī)劃統(tǒng)一管理,進(jìn)行收口。這其中包括:
流量收口。包括南北向和東西向的流量的調(diào)度,主要通過流量網(wǎng)關(guān),開發(fā)框架 SDK或 Service Mesh 這樣的技術(shù)。
服務(wù)治理收口。包括:服務(wù)發(fā)現(xiàn)、健康檢查,配置管理、事務(wù)、事件、重試、熔斷、限流……主要通過開發(fā)框架 SDK – 如:Spring Cloud,或服務(wù)網(wǎng)格Service Mesh等技術(shù)。
監(jiān)控?cái)?shù)據(jù)收口。包括:日志、指標(biāo)、調(diào)用鏈……主要通過一些標(biāo)準(zhǔn)主流的探針,再加上后臺的數(shù)據(jù)清洗和數(shù)據(jù)存儲來完成,最好是使用無侵入式的技術(shù)。監(jiān)控的數(shù)據(jù)必須統(tǒng)一在一個地方進(jìn)行關(guān)聯(lián),這樣才會產(chǎn)生信息。
資源調(diào)度有應(yīng)用部署的收口。包括:計(jì)算、網(wǎng)絡(luò)和存儲的收口,主要是通過容器化的方案,如k8s來完成。
中間件的收口。包括:數(shù)據(jù)庫,消息,緩存,服務(wù)發(fā)現(xiàn),網(wǎng)關(guān)……等等。這類的收口方式一般要在企業(yè)內(nèi)部統(tǒng)一建立一個共享的云化的中間件資源池。
對此,這里的原則是:
你要選擇容易進(jìn)行業(yè)務(wù)邏輯和控制邏輯分離的技術(shù)。這里,Java 的 JVM+字節(jié)碼注入+AOP 式的Spring 開發(fā)框架,會帶給你太多的優(yōu)勢。
你要選擇可以享受“前人種樹,后人乘涼”的有技術(shù)紅利的技術(shù)。如:有龐大社區(qū)而且相互兼容的技術(shù),如:Java, Docker, Ansible,HTTP,Telegraf/Collectd……
中間件你要使用可以 支持HA集群和多租戶的技術(shù)。這里基本上所有的主流中間件都會支持 HA 集群方式的。
我發(fā)現(xiàn)很多公司都很非常大的技術(shù)債務(wù),這些債務(wù)具體表現(xiàn)如下:
使用老舊的技術(shù)。比如,使用HTTP1.0, Java 1.6,Websphere,ESB,基于 socket的通訊協(xié)議,過時(shí)的模型……等等
不合理的設(shè)計(jì)。比如,在 gateway 中寫大量的業(yè)務(wù)邏輯,單體架構(gòu),數(shù)據(jù)和業(yè)務(wù)邏輯深度耦合,錯誤的系統(tǒng)架構(gòu)(把緩存當(dāng)數(shù)據(jù)庫,用消息隊(duì)列同步數(shù)據(jù))……等等
缺少配套設(shè)施。比如,沒有自動化測試,沒有好的軟件文檔,沒有質(zhì)量好的代碼,沒有標(biāo)準(zhǔn)和規(guī)范……等等
來找我尋求技術(shù)幫助的人都有各種各樣的問題。我都會對他們苦口婆心地說同樣的一句話——“如果你是來找我 case-by-case 解決問題,我興趣不大,因?yàn)?,你們千萬不要寄希望能夠很簡單的把一輛夏利車改成一輛法拉利跑車,或是把一棟地基沒打好的歪樓搞正。以前欠下的技術(shù)債,都得要還,沒打好的地基要重新打,沒建配套設(shè)施都要建。這些基礎(chǔ)設(shè)施如果不按照正確科學(xué)的方式建立的話,你是不可能有一個好的的系統(tǒng),我也沒辦法幫你 case-by-case 的解決問題……”,一開始,他們都會對我說,沒問題,我們就是要還債,但是,最后發(fā)現(xiàn)要還的債真多,有點(diǎn)承受不了,就開始現(xiàn)原形了。
他們開始為自己的“欠的技術(shù)債”找各種合理化的理由——給你解釋各種各樣的歷史原因和不得以而為之的理由。談著談著,讓我有一種感覺——他們希望得到一種什么都不改什么都不付出的方式就可以進(jìn)步的心態(tài),他們寧可讓新的技術(shù) low 下來遷就于這些技術(shù)債,把新的技術(shù)濫用地亂七八糟的。有一個公司,他們的系統(tǒng)架構(gòu)和技術(shù)選型基本都搞錯了,使用錯誤的模型構(gòu)建系統(tǒng),導(dǎo)致整個系統(tǒng)的性能非常之差,也才幾千萬條數(shù)據(jù),但他們想的不是還債,不是把地基和配套設(shè)施建好,而且要把樓修的更高,上更多的系統(tǒng)——他們覺得現(xiàn)有的系統(tǒng)挺好,性能問題的原因是他們沒一個大數(shù)據(jù)平臺,所以要建大數(shù)據(jù)平臺……
我見過很多很多公司,包括大如 BAT 這樣的公司,都會在原來的技術(shù)債上進(jìn)行更多的建設(shè),然后,技術(shù)債越來越大,利息越來越大,最終成為一個高利貸,再也還不了(我在《開發(fā)團(tuán)隊(duì)的效率》一文中講過一個 WatchDog 的架構(gòu)模式,一個系統(tǒng)爛了,不是去改這個系統(tǒng),而是在旁邊建一個系統(tǒng)來看著它,我很難理解為什么會有這樣的邏輯,也許是為了要解決更多的就業(yè)……)
這里有幾個原則和方法我是非常堅(jiān)持的,分享給大家:
與其花大力氣遷就技術(shù)債務(wù),不如直接還技術(shù)債。是所謂的長痛不如短痛。
建設(shè)沒有技術(shù)債的“新城區(qū)”,并通過“防腐層 ”的架構(gòu)模型,不要讓技術(shù)債侵入“新城區(qū)”。
有好些人來找我跟我說他們的技術(shù)問題,然后希望我能夠給他們一個答案。我說,我需要了解一下你現(xiàn)有系統(tǒng)的情況,也就是需要先做個診斷,我只有得到這些數(shù)據(jù)后,我才可能明白真正的原因是什么 ,我才可能給你做出一個比較好的技術(shù)方案。我個人覺得這是一種對對方負(fù)責(zé)的方法,因?yàn)榧夹g(shù)手段太多了,所有的技術(shù)手段都有適應(yīng)的場景,并且有各種 trade-off,所以,只有調(diào)研完后才能做出決定。這跟醫(yī)生看病是一樣的,確診病因不能靠經(jīng)驗(yàn),還是要靠診斷數(shù)據(jù)。在科學(xué)面前,所有的經(jīng)驗(yàn)都是靠不住的……
另外,如果有一天你在做技術(shù)決定的時(shí)候,開始憑自己以往的經(jīng)驗(yàn),那么你就已經(jīng)不可能再成長了。人都是不可能通過不斷重復(fù)過去而進(jìn)步的,人的進(jìn)步從來都是通過學(xué)習(xí)自己不知道的東西。所以,千萬不要依賴于自己的經(jīng)驗(yàn)做決定。做任何決定之前,最好花上一點(diǎn)時(shí)間,上網(wǎng)查一下相關(guān)的資料,技術(shù)博客,文章,論文等 ,同時(shí),也看看各個公司,或是各個開源軟件他們是怎么做的?然后,比較多種方案的 Pros/Cons,最終形成自己的決定,這樣,才可能做出一個更好的決定。
對于 X-Y 問題,也就是說,用戶為了解決 X問題,他覺得用 Y 可以解,于是問我 Y 怎么搞,結(jié)果搞到最后,發(fā)現(xiàn)原來要解決的 X 問題,這個時(shí)候最好的解決方案不是 Y,而是 Z。 這種 X-Y 問題真是相當(dāng)之多,見的太多太多了。所以,每次用戶來找我的時(shí)候,我都要不斷地追問什么是 X 問題。
比如,好些用戶都會來問我他們要一個大數(shù)據(jù)流式處理,結(jié)果追問具體要解決什么樣的問題時(shí),才發(fā)現(xiàn)他們的問題是因?yàn)榉?wù)中有大量的狀態(tài),需要把相同用戶的數(shù)據(jù)請求放在同一個服務(wù)上處理,而且設(shè)計(jì)上導(dǎo)致一個慢函數(shù)拖慢整個應(yīng)用服務(wù)。最終就是做一下性能調(diào)優(yōu)就好了,根本沒有必要上什么大數(shù)據(jù)的流式處理。
我很喜歡追問為什么 ,這種追問,會讓客戶也跟著來一起重新思考。比如,有個客戶來找我評估的一個技術(shù)架構(gòu)的決定,從理論上來說,好像這個架構(gòu)在用戶的這個場景下非常不錯。但是,這個場景和這個架構(gòu)是我職業(yè)生涯從來沒有見過的。于是,我開始追問這個為什么會是這么一個場景?當(dāng)我追問的時(shí)候,我發(fā)現(xiàn)用戶都感到這個場景的各種不合理。最后引起了大家非常深刻的研討,最終用戶把那個場景修正后,而架構(gòu)就突然就變成了一個常見且成熟的的模型……
我對技術(shù)的態(tài)度是比較激進(jìn)的,但是,所謂的激進(jìn)并不是瞎搞,也不是見新技術(shù)就上,而是積極擁抱會改變未來的新技術(shù),如:Docker/Go,我就非??斓馗M(jìn),但是像區(qū)塊鏈或是 Rust 這樣的,我就不是很積極。因?yàn)椋洳]有命中我認(rèn)為的技術(shù)趨勢的幾個特征(參看《Go,Docker 和新技術(shù) 》)。當(dāng)然,我也不是不喜歡的就不學(xué)了,我對區(qū)塊鏈和 Rust 我一樣學(xué)習(xí),我也知道這些技術(shù)的優(yōu)勢,但我不會大規(guī)模使用它們。另外,我也尊重保守的決定,這里面沒有對和錯。但是,我個人覺得對技術(shù)激進(jìn)的態(tài)度比起保守來說有太多的好處了。一方面來說,對于用戶來說,很大程度上來說,新技術(shù)通常都表面有很好的競爭力,而且我見太多這樣成功的公司都在積極擁抱新的技術(shù)的,而保守的通常來說都越來越不好。
有一些人會跟我說,我們是實(shí)用主義,我們不需要創(chuàng)新,能解決當(dāng)下的問題就好,所以,我們不需要新技術(shù),現(xiàn)有的技術(shù)用好就行了。這類的公司,他們的技術(shù)設(shè)計(jì)第一天就在負(fù)債,雖然可以解決當(dāng)下問題,但是馬上就會出現(xiàn)新的問題,然后他們會疲于解決各種問題。最后呢,最后還是會走到新的技術(shù)上。
這里的邏輯很簡單 —— 進(jìn)步永遠(yuǎn)來自于探索,探索是要付出代價(jià)的,但是收益更大。對我而言,不敢冒險(xiǎn)才是最大的冒險(xiǎn),不敢犯錯才是最大的錯誤,害怕失去會讓你失去的更多……
(全文完)
聯(lián)系客服