來源:公眾號 作者:方志朋
鏈接:https://mp.weixin.qq.com/s/TtnOPw_lnJYzFmtZnlpsew
技術架構析珊,是將產(chǎn)品需求轉變?yōu)榧夹g實現(xiàn)的過程。技術架構解決的問題包括了如何進行純技術層面的分層恕稠、開發(fā)框架選擇擎颖、語言選擇(這里以 JAVA 語言為主)匣砖、涉及到各自非功能性需求的技術點(安全布朦、性能、大數(shù)據(jù))纯出。技術架構是確定組成應用系統(tǒng)實際運行的技術組件蚯妇、技術組件之間的關系,以及部署到硬件的策略暂筝。
技術架構面臨最大的挑戰(zhàn)是“不確定性”箩言。在技術架構上,很多時候就會面臨這種選擇焕襟。是要選擇業(yè)界最新的技術陨收?還是選擇團隊最熟悉的技術?如果選擇最新的技術鸵赖,遇到新技術出了問題怎么解決务漩?如果選擇目前熟悉的技術,后續(xù)技術演進怎么辦它褪?這些都是架構師在做技術架構過程中需要考慮的饵骨。
業(yè)務在千變萬化、技術在層出不窮茫打,沒有一套通用的技術架構模式來適用所有的系統(tǒng)居触。那么,我們如何保證在做技術架構時老赤,能夠實現(xiàn)一個穩(wěn)定轮洋、出色的系統(tǒng)。面對這些“不確定性”時的架構設計問題诗越,這里從戰(zhàn)略和戰(zhàn)術兩個層面來提供一些設計原則砖瞧。戰(zhàn)略層提供的是技術架構的方法和思路,屬于頂層設計嚷狞;戰(zhàn)術層提供的是技術架構的技術實踐方式块促,更偏向詳細設計荣堰。
戰(zhàn)略層設計原則
戰(zhàn)略層的設計原則就是:合適原則、簡單原則竭翠、演化原則
振坚。
1.1 合適原則
技術人員有一種很強的技術情懷,就是在做設計的過程中斋扰,很希望挑戰(zhàn)新的技術渡八、在項目中采用最新的框架、或者自己重造一個比業(yè)界的還要牛的輪子传货。這樣才能夠顯示出自己的優(yōu)秀屎鳍,以至于不讓自己顯的那么平庸。比如问裕,在項目中重新造一個能夠解決億萬級數(shù)據(jù)的新的 xx 流式計算技術逮壁,比 flink 還要牛一百倍;有或者在項目中使用最新的 xx 技術粮宛,能讓系統(tǒng)承擔億級用戶的訪問窥淆。
那么現(xiàn)實是,如果在設計過程中一味追求新技術巍杈,往往失敗的可能性很高忧饭。
- 沒有那么多人,卻想干那么多活
現(xiàn)實環(huán)境中我們一個業(yè)務團隊可能就十幾個人筷畦,項目工期短考赛、上線要求快锁右。在這種情況下膝擂,如果還要抽調幾個人去研究样悟、搭建作媚、維護新的技術框架攘滩,對于項目勢必會造成延期的影響。
- 沒有那么多積累纸泡,卻想一步登天
很多業(yè)界領先的方案漂问,不是一幫優(yōu)秀的開發(fā)加在一起,加班加點就能做出來的女揭。而是經(jīng)過幾年時間的發(fā)展才逐步完善和初具規(guī)模蚤假。如果我們也想自己做一套類似的技術,不是說不可能吧兔。我們需要集合當下的技術實力磷仰、技術積累,做出適合自己團隊情況的技術評估境蔼。
- 沒有最新灶平,只要最合適
所有新的技術剛出來都是打著比舊技術擁有更加出色的性能伺通、提供更加優(yōu)秀的擴展性。是不是使用新技術逢享,就能解決一切問題了罐监?新技術的出道,勢必是解決某一場景下的問題瞒爬,并不是一味萬能良藥弓柱。只有了解清楚每種技術的產(chǎn)生背景,適用場景侧但,才能出一個對自己項目最優(yōu)的選擇矢空。技術選型沒有最新,只有最合適禀横。
總結一下妇多,合適原則就是適合優(yōu)于業(yè)界領先。
1.2 簡單原則
我們總是希望能將我們的軟件設計的精美燕侠、宏大者祖,這樣才能彰顯我們系統(tǒng)的復雜度和難度。我們是不是會遇到這樣的場景绢彤,在做設計方案的時候七问,如果一個解決方案很簡單,而且能很快的滿足需求茫舶。在評審方案時械巡,就會有人覺得這個方案是不是太簡單了,沒有什么技術含量饶氏,是不是需要再設計的復雜一點讥耗。
系統(tǒng)是不是一定要設計的復雜?在回答這個問題前疹启,我們先看下軟件領域的結構復雜性和邏輯復雜性古程。
(1)結構復雜性
結構復雜的系統(tǒng)有兩個特點:
第一,組成的組件數(shù)量很多
喊崖;
第二挣磨,這些組件之間的關系很復雜
。如下圖:
結構上的復雜性存在的第一個問題是荤懂,組件越多茁裙,就越有可能其中某個組件出現(xiàn)故障,從而導致系統(tǒng)故障节仿。假設組件的故障概率是 1%(有 1% 的時間不可用)晤锥,那么 2 個組件的系統(tǒng)可用性是 99%99%=98%,5 個組件的系統(tǒng)可用性是 99%99%99%99%*99%=95%廊宪,兩者相差 3%矾瘾。說明組件越多眉踱,系統(tǒng)穩(wěn)定性就越差。
結構上的復雜性存在的第二個問題是霜威,某個組件改動谈喳,會影響關聯(lián)的組件。比如上圖中 C 組件發(fā)生改動戈泼,會影響 A婿禽、B、D大猛,而 A 有會影響 E扭倾。這樣就會形成一連串的多比諾效應
。
(2)邏輯復雜性
意識到結構復雜性的問題后挽绩,只要減少組件就能讓系統(tǒng)結構變簡單膛壹?這樣做還是行不通,原因在于除了結構的復雜性唉堪,還有邏輯的復雜性模聋,如果一個組件的邏輯太復雜,通用會帶來問題唠亚。
我們試想一下链方,把淘寶的所有功能都在一個組件中實現(xiàn),可以想象這個系統(tǒng)要有多龐大:幾百人維護一個系統(tǒng)灶搜、代碼分支幾十個祟蚀、需求變更應接不暇、不同分支的回歸測試割卖、修改一段代碼可能影響整個系統(tǒng)的運行等等前酿。這些場景相信大家都不希望看到的。
總結一下鹏溯,簡單原則就是大道至簡罢维。
1.3 演化原則
軟件架構和建筑架構很多相同的地方,架構這個詞也是從建筑領域借鑒過來的剿涮。比如言津,軟件架構描述的是系統(tǒng)的結構攻人、以及各模塊之間的關系取试。而建筑結構描述的是一幢建筑的結構,以及建筑內部各部件如何有機的組成怀吻。
但是瞬浓,軟件架構和建筑架構有一個本質上的差異:那就是建筑一旦完成就不會再變,而軟件卻需要根據(jù)業(yè)務的發(fā)展不斷的變化蓬坡。對于建筑來說猿棉,永恒是主題磅叛;而對于軟件來說,變化才是主題萨赁。
如果沒有意識到“軟件架構需要根據(jù)業(yè)務發(fā)展不斷變化”這個本質弊琴,在做架構設計的時候很容易陷入一個誤區(qū):試圖一步到位設計一個軟件架構,期望不管業(yè)務如何變化杖爽,架構都穩(wěn)如磐石敲董。如果是按照這樣的目標是設計,一開始上來就做出一套看似是終極的方案慰安,投入龐大的資源做各種預測腋寨、分析。結果是投入巨大的資源化焕、開發(fā)周期漫長萄窜,最終跌跌撞撞落地的系統(tǒng),卻發(fā)現(xiàn)已經(jīng)無法很好的滿足現(xiàn)有的業(yè)務撒桨。
所以技術架構設計需要一個過程:
首先查刻,要滿足當前的業(yè)務需求進行技術架構設計
其次,架構要不斷地在實際應用過程中迭代凤类,保留優(yōu)秀的設計赖阻,修復有缺陷的設計,改正錯誤的設計踱蠢,去掉無用的設計火欧,使架構逐漸完善。
最后茎截,當業(yè)務發(fā)生變化時苇侵,架構要擴展、重構企锌、甚至重寫榆浓;代碼也許會重寫,但有價值的經(jīng)驗撕攒、教訓陡鹃、邏輯、設計卻可以在新架構中延續(xù)抖坪。
總結一下萍鲸,演化原則就是演化優(yōu)于一步到位。
戰(zhàn)術層設計原則
戰(zhàn)術層的設計原則分為 3 部分:高并發(fā)原則
擦俐、高可用原則
脊阴、業(yè)務設計原則
。這些原則是對技術架構設計過程中提供詳細的指導思路,幫助你做技術選型嘿期、技術拆分品擎。
2.1 高并發(fā)原則
設計高并發(fā)的系統(tǒng),需要考慮以下幾個方面的設計:無狀態(tài)备徐、拆分萄传、服務化、消息隊列蜜猾、數(shù)據(jù)異構盲再、緩存。
(1)無狀態(tài)
- 無狀態(tài)應用瓣铣,便于水平擴展答朋。
- 有狀態(tài)配置可通過配置中心實現(xiàn)無狀
(2) 拆分
- 系統(tǒng)維度:按照系統(tǒng)功能、業(yè)務拆分棠笑,比如購物車梦碗、結算、訂單等蓖救。
- 功能維度:對系統(tǒng)功能再做細粒度拆分洪规。
- 讀寫維度:根據(jù)讀寫比例特征拆分;讀多循捺,可考慮多級緩存斩例;寫多,可考慮分庫分表从橘。
- AOP 維度:根據(jù)訪問特征念赶,按照 AOP 進行拆分.
- 模塊維度:對整體代碼結構劃分 web、service恰力、dao叉谜。
(3)服務化
- 服務化演進:進程內服務 - 單機遠程服務 - 集群手動注冊服務 - 自動注冊和發(fā)現(xiàn)服務 - 服務的分組、隔離踩萎、路由 - 服務治理停局。
- 考慮服務分組、隔離香府、限流董栽、黑白名單、超時企孩、重試機制锭碳、路由、故障補償?shù)取?/li>
(4)消息隊列
- 目的:服務解耦(一對多消費)柠硕、異步處理工禾、流量削峰緩沖等运提。
- 大流量緩沖:犧牲強一致性蝗柔,保障最終一致性闻葵。
- 數(shù)據(jù)校對:解決異步消息機制下消息丟失問題。
(5)數(shù)據(jù)異構
- 數(shù)據(jù)異構:通過消息隊列機制接受數(shù)據(jù)變更癣丧,原子化存儲槽畔。
- 數(shù)據(jù)閉環(huán):屏蔽多重數(shù)據(jù)來源,將數(shù)據(jù)異構存儲胁编,形成閉環(huán)厢钧。
(6)緩存
- 用戶層:DNS 緩存、瀏覽器 DNS 緩存嬉橙、操作系統(tǒng) DNS 緩存早直、本地 DNS 服務商緩存、DNS 服務器緩存市框、客戶端緩存霞扬、瀏覽器緩存、APP 客戶端緩存枫振。
- 代理層:CDN 緩存(一般基于 ATS喻圃、Varnish、Nginx粪滤、Squid 等構建斧拍,邊緣節(jié)點 - 二級節(jié)點 - 中心節(jié)點 - 源站)
- 接入層:Nginx 的 Proxy_cache 代理緩存,或者 Nginx+Lua+Redis 做業(yè)務數(shù)據(jù)緩存杖小。
- 應用層:頁面靜態(tài)化肆汹、業(yè)務數(shù)據(jù)緩存(Redis/Memcache/ 本地文件等)、消息隊列
- 數(shù)據(jù)層:NoSQL(Redis予权、Memcache县踢、SSDB 等)
2.2 高可用原則
- 降級
- 降級開關集中化管理:將開關配置信息推送到各個應用。
- 可降級的多級讀服務:如服務調用降級為只讀本地緩存伟件。
- 開關前置化:如 Nginx+Lua 配置降級策略硼啤,引流流量;可基于此做灰度策略斧账。
- 業(yè)務降級:高并發(fā)下谴返,保證核心功能,次要功能可由同步改為異步策略或屏蔽功能咧织。
- 限流
- 目的:防止惡意請求攻擊或超過系統(tǒng)峰值
- 惡意請求流量只訪問到 Cache
- 穿透后端應用的流量 Nginx 的 limit 處理
- 惡意 Ip 使用 Nginx Deny 策略或者 iptables 拒絕
- 可回滾
- 發(fā)布版本失敗時嗓袱,可隨時快速回退到上一個穩(wěn)定版本。
2.3 業(yè)務設計原則
- 防重設計
- 冪等設計
- 流程定義
- 狀態(tài)與狀態(tài)機
- 后臺系統(tǒng)操作可反饋
- 后臺系統(tǒng)審批化
- 文檔注釋
- 備份
技術架構圖
技術架構圖是將系統(tǒng)的技術方案习绢、技術選型通過視圖的方式進行展現(xiàn)渠抹。技術架構圖分為兩類:一類蝙昙,功能需求技術架構圖(邏輯架構圖),是描繪如何通過技術組件來實現(xiàn)系統(tǒng)產(chǎn)品功能的圖梧却。另一來奇颠,非功能需求技術架構圖(物理架構圖),是描繪如何通過物理部署的來實現(xiàn)系統(tǒng)運行的圖放航。
3.1 邏輯架構圖
功能需求技術架構圖以產(chǎn)品架構圖和應用架構圖為基礎烈拒。實現(xiàn)每個功能點需要使用什么技術、技術實現(xiàn)邏輯如何广鳍,就提現(xiàn)在技術架構圖上荆几。功能需要技術架構圖繪制可以按照“整體 - 局部 - 整體”的思路實現(xiàn)。
- 整體
首先可以按照應用架構圖的應用分布得到應用分布框架赊时。如下:
- 局部
在整體框架的基礎上吨铸,對每一個局部的子系統(tǒng)進行詳細的技術實現(xiàn)的表達。子系統(tǒng)的技術架構圖中需要展示每個子系統(tǒng)使用的技術組件祖秒,比如(緩存技術诞吱、消息中間件、流程引擎狈涮、流式計算框架等等)狐胎。同時,這些技術組件是如何實現(xiàn)業(yè)務功能歌馍,需要清晰的展示技術實現(xiàn)邏輯握巢。
下圖是對風控系統(tǒng)中的實時引擎、離線引擎松却、準實時引擎三個子系統(tǒng)的進行的技術架構暴浦。在實時引擎中,主要使用 RuleEngine(規(guī)則引擎)作為技術特點晓锻,這里就重點列出 RuleEngine歌焦。準實時引擎使用 Blink 作為流計算的技術框架,并概要的展示了計算邏輯砚哆。
- 整體
在完成每個子系統(tǒng)的技術實現(xiàn)后独撇,最終進行一次整合,繪制一張總體的系統(tǒng)技術架構圖躁锁。各子系統(tǒng)之間通過服務接口纷铣、數(shù)據(jù)庫、緩存或消息中間等技術實現(xiàn)數(shù)據(jù)交互战转,以此將打通各個子系統(tǒng)搜立,實現(xiàn)最終整個產(chǎn)品從數(shù)據(jù)、技術的串聯(lián)槐秧。
3.2 物理架構圖
物理架構偏重于網(wǎng)絡設計啄踊、集群設計忧设、中間件設計、數(shù)據(jù)存儲設計等基礎軟硬件的設計架構颠通。非功能需求的技術架構圖重點在于展示企業(yè)系統(tǒng)在物理上是如何部署址晕。物理架構規(guī)定了組成系統(tǒng)的物理元素、物理元素之間的關系以及他們的部署策略蒜哀。物理架構反映出軟件系統(tǒng)動態(tài)運行時的組織情況斩箫。從物理架構圖中吏砂,我們能夠全局的得知整個系統(tǒng)是如何從流量訪問撵儿、數(shù)據(jù)流轉、數(shù)據(jù)存儲到技術組件的運轉狐血。
總 結
我們從架構的本質開始淀歇,分別對業(yè)務架構、產(chǎn)品架構匈织、數(shù)據(jù)架構浪默、應用架構、技術架構的設計提供了一些思路和原則缀匕。這些思路和原則在進行架構設計和畫架構圖的過程中提供一些指導幫助纳决。最后我們再來思考一個問題,好的軟件架構是規(guī)劃還是演化出來乡小?
架構規(guī)劃對架構的影響是很重大的阔加。首先,好的架構是設計出來的满钟。好的架構胜榔,系統(tǒng)的性能和質量都將很高。架構設計的質量直接影響架構后續(xù)向好的方向演化的難易程度湃番。架構設計如同城市規(guī)劃一樣夭织,缺少規(guī)劃將難于演化。
演化是一個過程吠撮,這個過程或長或短尊惰,所以演化需要考慮系統(tǒng)的生命周期。如果演化的過程非常漫長泥兰,超出了軟件的生命周期弄屡,即使架構越來越優(yōu)化,對于產(chǎn)品或者項目的幫助也將有限逾条,所以時間這個約束條件是非匙裂遥苛刻的。
在現(xiàn)有規(guī)劃的基礎上進行演化师脂,我們無法得到普適的架構担孔,但可以得到確定領域的通用架構江锨,可以在特定領域通過演化使架構逐步優(yōu)化,幫助業(yè)務快速的發(fā)展糕篇。