在第一次舉辦meetup後,社群的志工團隊開始逐漸招募成型,我們不斷的在想著怎麼樣可以讓這樣剛萌生的熱可以延續(xù)下去,從1/26到3月份我關(guān)注到一個狀況统求,每天都有不斷收到的加入社群的請求,這是一件鼓舞社群志工團隊的很重要的訊息据块,有人有興趣來探索與了解码邻,都是將我們推進(jìn)的動力。
不過另假,有一個不容易解決的困擾那就是社群成員的組成的多元性像屋,不知道是大家謙虛還是什麼原因,加入社群的提問問題之一是 “您對DDD的認(rèn)識程度边篮,請自評1~5”
0 or 1 似乎是大家對此的公約數(shù) ?
為了想要更全面的關(guān)注社群夥伴己莺,在本次的議程安排上真的是想破頭了!
這次的議程包括了有
- DDD with Clean Architecture, Arthur Chang
- 團隊協(xié)作實戰(zhàn)DDD, Jed Lin
- Essential capabilities behind Microservices, Kim Kao
以下我分別對這些議程做些我在僅有的參與過程中的回顧,礙於篇幅關(guān)係若你對這些主題有興趣可以直接點閱簡報戈轿,並且找到DDD社群與大家交流凌受。
Clean Architecture with DDD
DDD with clean architecture - Slides on Slideshare
作為社群發(fā)起人之一的Arthur 為了要更添加主題的討論層次,也盡量與當(dāng)天講者們的話題不要完全重複思杯,把主題定為成揉合Clean Architecture的DDD的探討胜蛉,雖然在開場時他特別說到 :
我今天講的主題應(yīng)該算是 Clen Architecture 101…
但就整體的內(nèi)容廣度來說,我相信之後要安排(X)推坑(O)進(jìn)行各種環(huán)節(jié)的系列深入話題交流應(yīng)該也是沒問題的色乾。
這次在Arthur的議程中談到了架構(gòu)因子(架構(gòu)因子來自於 溫昱 的一本書:一線架構(gòu)師)誊册,喚醒你對做架構(gòu)設(shè)計時可能需要去思考的諸多變因與影響來源,尤其在組織結(jié)構(gòu)上的影響也多是如此暖璧,另外一個很重要的思考點是 :
維度
對於系統(tǒng)來說影響到一個軟件架構(gòu)的維度有4:
- Component 的擴充考量
- Layer 的擴充考量
- 多個系統(tǒng)之間協(xié)作的擴充考量
- 基於時間變化的挑戰(zhàn)
時間解虱,是一個驅(qū)動業(yè)務(wù)變革的主因,也同時經(jīng)常因為如此導(dǎo)致不可逆的架構(gòu)轉(zhuǎn)變漆撞,甚至產(chǎn)生了業(yè)務(wù)項目重點的”軸變”。某些企業(yè)可能會在經(jīng)營主要業(yè)務(wù)之餘開始去嘗試其他的更多市場機會于宙,一但在某個試點的項目中開始獲得成效而最終發(fā)現(xiàn)這個新項目成了這企業(yè)的救命符時浮驳,這時候?qū)Υ似髽I(yè)來說他的核心關(guān)注價值重點,已經(jīng)發(fā)生了商業(yè)價值上的軸轉(zhuǎn)捞魁,這時候果斷的企業(yè)主很可能就會思考把重點領(lǐng)域關(guān)注做出翻轉(zhuǎn)至会,進(jìn)而獲取更重要的價值與經(jīng)營。
團隊協(xié)作實戰(zhàn)DDD
團隊協(xié)作實戰(zhàn)DDD - Slides on Slideshare
另外要特別感謝 Jed Lin花了很多時間的準(zhǔn)備谱俭,早在社群成立非常早的初期奉件,我就不斷的打擾(O)邀請(X)他宵蛀,務(wù)必請他能盡量抽出時間與大家分享在過去的工作中的實際開發(fā)經(jīng)驗,而事實上 Jed 本人也表示 :
在受到邀請時就已經(jīng)開始準(zhǔn)備這主題了
在這個主題當(dāng)中县貌,Jed把軟體設(shè)計本身看待成解決業(yè)務(wù)問題與技術(shù)問題為起點术陶,鼓勵大家更多的關(guān)注在業(yè)務(wù)本身,同時在面對領(lǐng)域模型捕捉的部分煤痕,揉入了 Impact Map以及 User story mapping的面向做引導(dǎo)梧宫,這手法你我不陌生,但是你可能過去沒有特別去思考過這方式摆碉,而今你可以試著想想或體驗她塘匣。Eric Evans在當(dāng)初撰寫與推廣DDD的時候其實在運作手法上並沒有特別的陳述有哪些實作可行的方式,而現(xiàn)在你可去嘗試你任何可能可以達(dá)到團隊共創(chuàng)以及使用統(tǒng)一語言來達(dá)到交流與共同理解的方法巷帝,那麼它就是一個高效有意義的方法忌卤。
有了建模基礎(chǔ)之後楞泼,我們經(jīng)常在過去的開發(fā)經(jīng)驗中被要求提交系統(tǒng)分析規(guī)格書驰徊,或者系統(tǒng)設(shè)計規(guī)格書,尤其如果你是跟我一樣做了很多年的SI背景經(jīng)驗的人现拒,你很能理解撰寫這些 “一次性文件”代表的浪費與痛苦辣垒。
Jed在這次的議程中,也鼓勵大家多試著以 Specification by Example印蔬,搭配初步捕捉的領(lǐng)域模型概念進(jìn)行代碼開發(fā)勋桶,進(jìn)行邏輯驗證,團隊可以依此進(jìn)行設(shè)計與調(diào)整侥猬,從而更多試著思考捕捉出來的各個子領(lǐng)域之間的關(guān)係確認(rèn)例驹。
Essential capabilities behind Microservices
這個主題是我近來非常喜歡的話題,可能也一部分跟現(xiàn)在工作環(huán)境有關(guān)退唠,當(dāng)接觸的人群多了鹃锈,我發(fā)現(xiàn)很多人不管是什麼樣的角色(業(yè)務(wù)人員,銷售,技術(shù)團隊,廣告…)都對微服務(wù)有著熱血情懷,總會期望可以在這身上獲得些幫助瞧预。
這是一種投射作用屎债,我們肯定能理解到技術(shù)幫助業(yè)務(wù)的相輔相成,但是在當(dāng)你認(rèn)真想踏入微服務(wù)的設(shè)計與實踐維運的路之前垢油,可能或許聽聽我的這篇文章盆驹,能給你一些不同的觀點:
Essential Capabilities behind Microservices - Slides on Slideshare
簡報重點捕捉
企業(yè)對系統(tǒng)的期待是賺錢,儘管就你專業(yè)的技術(shù)優(yōu)秀人才眼中來看滩愁,他是多麼的紊亂不堪躯喇,沒有統(tǒng)整性與可讀性,讓你要花上很多心力去理解你才能去真正的維運硝枉。
可是你一直想要把它給改成你眼中井然有序廉丽,易於變革與調(diào)整的微服務(wù)體系倦微,其實從賺錢的角度來看你只是把它給擺整齊而已。
當(dāng)然這樣說是有點太過正压,可是這是要提醒你如果你帶來的各種變革無法為你的企業(yè)帶來至少同等的價值(賺錢能力)或甚至更好的表現(xiàn)欣福,那麼你還真的一定得需要這麼做嗎?
常見的面對將老系統(tǒng)轉(zhuǎn)型成微服務(wù)時的挑戰(zhàn)都列在上頭了,總是沒有人能對老舊系統(tǒng)的一切有所掌握有所認(rèn)知蔑匣,牽涉的關(guān)係人太過於龐大劣欢,如果我們是要走一個 “Big Ban”的變革,一次性的全面改變裁良,那麼往往失敗率高過天際凿将。
為了讓大家走入我心裡頭的世界,我再一次的與大家探討什麼是微服務(wù)?
那或許是個美好的青春(謊言)年代价脾,當(dāng)年Docker甫一推出搭配著 Chris Richardson的推廣牧抵,一開始有不少人直覺認(rèn)為或許Docker 就是微服務(wù)的體現(xiàn),而到了現(xiàn)在很有可能有人會跟你說 :
No ! Kubernetes才是微服務(wù)
但侨把,真是如此嗎? 對於微服務(wù)的理解應(yīng)當(dāng)從其定義開始:
如果犀变,你能夠獨自的處理好運算與存儲的的需要,並且不依賴於其他服務(wù)的能力秋柄,那麼你可以做到你應(yīng)有的內(nèi)聚”業(yè)務(wù)能力”获枝。這段話我的理解是這樣,但是說的簡單做的難骇笔,我們看看如果一個典型的遺留系統(tǒng)要轉(zhuǎn)型可能會遇到的問題是哪些?
你一定經(jīng)歷過這樣的會議室紛爭省店,到底該由誰或什麼方法來決定系統(tǒng)的劃分,不管你會經(jīng)典的方法論從名詞開始捕捉笨触,或者你是在場之中經(jīng)驗老道的佈道師懦傍,可能還更好一點的是你們是個擁抱團隊共識的團隊。
但更多常見的狀況是你老闆說了算芦劣,你沒有太多的話語權(quán)粗俱,面對這樣的場景你是只能徒呼負(fù)負(fù)或者當(dāng)一天和尚敲一天鐘的前進(jìn)? 光是這第一步就會讓很多人卻步是否還要再思考微服務(wù)!
好不容易從各種挑戰(zhàn)中度過了初步概念的劃分之後,迎接而來的是現(xiàn)實世界的技術(shù)困難點虚吟,過去一體成型的老系統(tǒng)寸认,要做身份驗證授權(quán)幾乎是session/cookie的天生戰(zhàn)場,你能通過已經(jīng)非常成熟的應(yīng)用技術(shù)來完成它串慰∑可是一但走到了原生的分散式系統(tǒng)的場域裡頭,這些大而全的一體式驗證授權(quán)已經(jīng)沒辦法再用上模庐,你需要自己重新建構(gòu)一個非常高可用的驗證授權(quán)系統(tǒng),或者仰賴第三方的服務(wù)油宜,甚至直接使用雲(yún)服務(wù)供應(yīng)商的應(yīng)用掂碱,因為:
要搭建一個SLA要求非常高的系統(tǒng)怜姿,又是作為驗證授權(quán)的入口基礎(chǔ)應(yīng)用,要花費的心力是非常驚人的!
再談服務(wù)的註冊與發(fā)現(xiàn)疼燥,從過去到現(xiàn)在我最喜歡或者說我受到最大影響的沧卢,無非是在 Java EE Pattern當(dāng)中的 Service Locator pattern,當(dāng)時因為有個JNDI可以充當(dāng)服務(wù)的註冊與發(fā)現(xiàn)的集中管理點醉者,很自然的就知道要在上頭去做各種搭建應(yīng)用但狭。
但是脫離了JNDI之後,還是有不少的作法與對應(yīng)的優(yōu)缺點撬即,從Client sie的查找來說立磁,不易於因應(yīng)服務(wù)器端產(chǎn)生的變化,像是ip換了或者其他原因剥槐。
從DNS層次上來解唱歧,解放了Client端的對Server端的無感知的困擾,但是DNS在 propagating的時間上的影響會容易在你對時間要求有高效需求時粒竖,DNS更新的時間長短與頻率是另一個你擔(dān)憂的話題颅崩。
其他更新的部分,則是通過容器編排管理相關(guān)的技術(shù)來實現(xiàn)它蕊苗,這些不在本次討論的細(xì)節(jié)中沿后,可以知道現(xiàn)在諸多的技術(shù)體系實作都能滿足,但以下這個問題可能是最難一下作出決斷的 :
關(guān)於持久化每個服務(wù)當(dāng)中須保存的資料朽砰,如果按前文提到的維基百科的定義尖滚,每個應(yīng)用需要有自己的運算與存儲能力與職責(zé),那我原本一個系統(tǒng)的拆分成5個锅移,10個熔掺,我是不是真的拆分成5 ~ 10個 資料庫 ?
先看看,假設(shè)你不拆的情況下非剃,只用一個或一組資料庫叢集的問題是什麼? 如果你的實作語言平臺與資料庫的連線是有 Connection Pool的設(shè)計的置逻,而預(yù)設(shè)你可能每一次帶起應(yīng)用程序時會直接keep 100 or 150+ 的 connections,當(dāng)你面對服務(wù)帶起數(shù)量眾多時备绽,你家的DBA會不知所措因為數(shù)量太龐大!
此外所有的請求量體也都打在同一個主資料庫上券坞,面對讀取,可能有其他方式可以解決肺素,但是寫入的壓力卻是不曾少過恨锚,更重要的是你的資料庫依然成的單點失敗的絕佳瓶頸王(恭喜登頂!! )
那如果我心一橫,直接開多個資料庫呢? 下個月你看到帳單或者你採購發(fā)申請送出去時倍靡,不是你老闆 fire你猴伶,就是你 fire你自己了,高成本的花費只為了滿足你的所謂微服務(wù)設(shè)計,很難得到價值感上的認(rèn)同他挎。
為了要更好的去把服務(wù)拆分避免高價的資料庫投資筝尾,或許NoSQL是一個選項,尤其現(xiàn)在有很多產(chǎn)品是提供了基於http請求的設(shè)計方式办桨,每個table的存取與其他table無關(guān)筹淫,在使用擴展上相對的容易得多,同時也帶來了很多在開發(fā)與運維的好處呢撞,像是更新應(yīng)用程式版本時對應(yīng)變動的schema损姜,你從此不在擔(dān)心哪個天兵給了你 alter table statement,卻沒給你 rollback的指令集與暫存異動資料的 DML statements殊霞。
當(dāng)然附帶的問題也少不了摧阅,無法處理多條件因子的複合式查詢等等問題也油然而生,我們也無法就因為這樣從全然的資料庫全數(shù)擁抱轉(zhuǎn)換到NoSQL去脓鹃。
其實逸尖,這一切還有個挑戰(zhàn),就是跨服務(wù)請求的交易補償瘸右。雖然很多人都說當(dāng)你有跨交易的請求鍊時娇跟,是否就該多思考一下你這服務(wù)的邊界的設(shè)計有沒有問題,出發(fā)點立意良善但實則要小心看待這是不是一種把責(zé)任置身事外的看法太颤。
很多時候你的系統(tǒng)的交互可能來自於多方的協(xié)作苞俘,又或者是在你的業(yè)務(wù)場景當(dāng)中就是真的區(qū)分出了不同上下文並落在不同的子領(lǐng)域當(dāng)中,這形成了天然的系統(tǒng)邊界以及交易範(fàn)疇的區(qū)隔龄章,你就是必須把手弄髒吃谣,想辦法去處理這些的分散式的交易困擾。
在一般的情況下做裙,以上面這個旅遊的概念為例:
清明假期快到了岗憋,我想要訂閱一個旅遊套餐,讓我?guī)е业募胰艘黄鸪鰢眠[锚贱,我想要訂酒店仔戈,訂機票,以及租賃適合的旅行車讓我完成一趟滿意的旅遊體驗拧廊,以這樣的業(yè)務(wù)場景下监徘,一個好的旅遊訂單,應(yīng)該要完成上面這三件事情吧碾。
如果我們在程式碼實作時凰盔,很可能會在程式當(dāng)中去撰寫 假設(shè)呼叫remote A 成功時我該如何,失敗時我又該如何倦春,在一個相對少數(shù)的業(yè)務(wù)交互的場景下户敬,你的判斷流程其實簡單可控落剪,但是如果你一次的業(yè)務(wù)行為會參與到更多的外部服務(wù)的呼叫時,把完整的失敗的補償作業(yè)給想清楚尿庐,從程式碼層次來說是辛苦的多了著榴,而且不小心就遺漏了。
面對分散式交易屁倔,當(dāng)然我們有個簡單易用的解決方案?—?2phase commit !
但是這樣的技術(shù)體系在價格上是昂貴的,面對交易量體較大或者參與交易的數(shù)據(jù)體較多時效率也差一些暮胧,尤其如果你把系統(tǒng)搭建在雲(yún)服務(wù)供應(yīng)商之上锐借,授權(quán)費的算法也是很可觀,所以或許你可以考慮使用另一個作法往衷,除了避免程式碼撰寫上的複雜钞翔,也可以略過2 phase commit的成本 :
Saga pattern in microservices
關(guān)於 Saga已經(jīng)出來很長一段時間了,有興趣的人可以直接google找到很多的介紹席舍,我在這裡提到的做法是通過 AWS 的 Step Functions來作流程業(yè)務(wù)上的編排:
在每一個較大的服務(wù)應(yīng)用中布轿,以上述的案例為例,訂酒店来颤,訂機票與租車之間本身並沒有所謂的業(yè)務(wù)發(fā)生的順序限制汰扭,但是只要有任何一個事情無法完成,那就必須都全數(shù)取消訂單福铅,才能確保我的旅遊體驗的價值可被實現(xiàn)萝毛。
如果,你能試著把這些業(yè)務(wù)訴求給流程化編排滑黔,那麼循著上圖的流程線你可以發(fā)現(xiàn)到笆包,最後一個被運行的租車工作,只要他確認(rèn)完成略荡,那就全數(shù)訂票作業(yè)完成庵佣,若租車這件事情無法成立,則循序的去取消租車汛兜,取消機票安排巴粪,以及取消訂房等事宜。
你可以通過這樣的事件編排序无,去把複雜的問題處理抽離開來验毡,這樣你只要對你既有的業(yè)務(wù)應(yīng)用設(shè)計做兩件事:
成功時,我該如何; 失敗時帝嗡,我又將如何 ~
這樣的設(shè)計思維晶通,簡化了你對外部系統(tǒng)的依賴思考,這樣的設(shè)計方式才是真正的”與外部解耦”哟玷,因為你始終只關(guān)注在當(dāng)前上下文的能力層次狮辽,更關(guān)注於內(nèi)聚力的體現(xiàn)一也。
Step Functions是一個基於JSON文件的描述流程編排的服務(wù),你不需去學(xué)習(xí)BPEL, BPMN等多種複雜的表示法喉脖,只需要會寫JSON 你就可以開始使用椰苟。
代碼範(fàn)例參考 - Implement Saga Pattern by StepFunctions + lambda
重點歸納
做系統(tǒng)設(shè)計始終沒有軟體界的C4可以使用,你在作微服務(wù)拆分時需要針對價值驅(qū)動树叽,前面提了這麼多現(xiàn)實考量會讓人有選擇障礙時舆蝴,你必須挑選真的值得你來面對分散式交易下的 :
- 追蹤交易鏈路問題
- 監(jiān)控業(yè)務(wù)行為log
- 拆分資料庫之後的選擇問題,多資料庫或者部分選擇成本低廉的替代選項
- 跨服務(wù)間的交易補償
- 甚至可能永遠(yuǎn)想不完整的交易補償業(yè)務(wù)流程
- 真的能維持原本的業(yè)務(wù)應(yīng)用水準(zhǔn)?
所以题诵,在做技術(shù)選擇之前洁仗,你可以試著以領(lǐng)域驅(qū)動設(shè)計的話題去擁抱業(yè)務(wù)團隊,通過事件風(fēng)暴大家一起集體思考性锭,哪些核心價值需要被體現(xiàn)赠潦,而且沒有他鐵定行不通的部分優(yōu)先來做逐步的拆分,一次性的全上往往帶來的是災(zāi)難草冈,這跟絕大多數(shù)的引領(lǐng)變革的團隊是同樣的道理的她奥。
祝福大家在擁抱挑戰(zhàn)引領(lǐng)變革的同時,小步前進(jìn)體驗當(dāng)前痛苦並動手改善得到團隊的真正肯定與重視怎棱。
活動後的週日總是帶著未盡的熱情哩俭,榻上翻轉(zhuǎn)難眠啊 ~