人月聊IT:对业务系统的可扩展性设计思考
人月聊 IT
讀完需要
9
分鐘速讀僅需 3 分鐘
對于業務系統本身在架構設計的時候考慮擴展,原來更多的都是談的 IT 基礎技術架構本身的高可用性和高擴展性。而對于業務系統擴展性,簡單來說就是如何靈活的應對需求的變化和擴展,如何減少在處理變更或擴展中代碼不斷產生的壞味道。
說到擴展性,一般會談到數據庫擴展性和應用擴展性兩個方面的內容,當然很多應用的擴展性最終會反饋到數據庫本身的擴展性上面來。而對于應用本身的擴展性本身又包括了數據模型的擴展,接口的擴展,業務規則的擴展,流程的擴展幾個方面的內容,下面分別對上面內容進行描述。
1
? ?
數據庫設計的擴展性
對于數據庫設計的擴展性準備談兩個方面,一個是數據庫本身的拆分問題,一個是數據庫設計方面的內容。數據庫拆分重點是解決在非集群架構下如何擴展的問題,數據庫設計重點是解決在 IT 基礎設施架構不變情況下擴展和性能提升。
1.1
? ?
數據庫的水平拆分和垂直拆分
對于數據庫本身的擴展和性能,一個方面就是采用數據庫集群架構,另外一個關鍵方法就是進行數據庫拆分,而數據拆分本身分為垂直拆分和水平拆分。
垂直拆分簡單來說就是根據業務域將數據庫表拆分到不同的數據庫上面,而水平拆分則是指對于同一個數據庫表按照用戶,組織等其它拆分維度將數據水平拆分到不同的數據庫上,但是這些數據庫本身數據庫結構是一樣的。
垂直拆分實際上和我們現在談的微服務架構下的數據庫拆分概念一致。
而水平拆分要解決的問題是如果已經進行微服務架構設計,但是單個微服務本身的數據庫性能無法達到要求,這個時候就必須考慮水平拆分。例如我們可以按不同區域將用戶數據拆分到不同的數據庫中,或者按企業本身的多組織結構,將不同組織數據庫拆分到不同的數據庫中。
水平拆分本身應該對上層應用透明。
即上層應用并不清楚底層進行了數據庫水平拆分,而仍然像訪問一個沒有拆分的數據庫一樣進行數據庫的訪問,數據庫的 CRUD 操作等。在這個時候就需要在拆分完成的數據庫上面構建一層 DaaS 數據訪問層,也可以叫做數據庫訪問中間件,即屏蔽底層拆分的復雜性。
拿 Mysql 數據庫來舉例,前面幾年就出現了很多的 Mysql 數據庫中間件,類似最早的 Cobar,Amoeba,到 360 的 Atlas,Mycat 等。
拿 Mycat 數據庫中間件來看,具體的架構如下:
但是實際在 DaaS 中間件實現過程中,本身對于上層應用仍然有要求,雖然現在中間件本身已經支持了類似分布式事務處理等功能,但是還是無法支撐完全意義上的全部 Sql 特性。同時在數據庫拆分后本身還存在數據如何拆分和分區,具體路由規則等問題。從 Mysql 中間件本身這幾年的關注熱度來看,實際上本身存在下降趨勢。特別是類似 TiDB,阿里的 PolarDB 采用其它技術實現方式更好的來解決了分布式數據庫問題。
1.2
? ?
數據庫設計的擴展性
對于數據庫本身的擴展,最容易想到的就是如何面對業務表單對象本身的字段擴展,而這個最簡單的考慮就是預留彈性字段,比如一張訂單表預留 10 到 20 個字段做為彈性擴展字段進行處理。其次,你也可以考慮預留一個大字符串字段,將多個數據項轉變為 Json 字符串后再進行存儲,特別是對于不涉及到具體業務規則,檢索條件的字段都可以這樣進行處理。
如果字段擴展極其不確定,或者說針對不同的單據類型實際上擴展的字段數都不一樣等情況,你也可以考慮將傳統的數據庫橫表設計模式轉變為縱表設計模式。這種擴展性最好,但是涉及到數據庫 SQL 查詢,關聯查詢會極其不方便,因此還是要慎用。
其次,我們很多時候還會把業務系統中經常變化的內容轉變為配置進行存儲,這經常看到的就是各類基礎數據表,數據字典表,全局變量配置表,數據編碼映射表,編碼生成規則表等。這些數據表將業務本身可配置的內容持久化到數據庫中以方便進行修改。在一個業務系統本身進行集群化部署的情況下,這些配置信息是不適合放到中間件服務器的配置文件里面的,持久化到數據庫表里面反而是一個好的選擇。
再次,對于數據庫單表容量的擴展本身也是重點要考慮的問題。
拿我們實際項目來說,對于 ESB 服務運行日志的存儲,單個服務實例表的數據庫行數超過 5 億條,這個時候對模糊查詢性能影響極大,必須對數據庫表進行分區。在實際項目中,我們基本是按每天來設計分區表,每天就產生一個分區表。
在采用分區后至少能夠滿足查區間范圍在一天內的數據庫會很快,其次就是對于數據庫按天進行清理或備份更加容易。但是即使這樣數據庫模糊查詢性能也很難滿足要求。因此在這種情況下還需要在數據庫上增加一級二級索引來解決問題。
1.3
? ?
應用層的擴展性設計
如果對于一個業務處理表單,本身 CRUD 功能實現后,后續這個業務表單需要擴展字段屬性,這類擴展實際上是比較容易實現的,只要提前在數據庫表預留了擴展字段,即能夠很方便的實現這種擴展能力。當然在考慮到界面展現的時候,我們還需要考慮這些擴展屬性項是否進行顯示,這個內容本身也要可配置。
如果一個業務系統采用了流程引擎,那你可以看到一個流程設計本身就很容易擴展,比如增加或刪除流程活動節點,選擇活動節點的處理角色和參與人等,這些內容本身可配置,擴展沒有問題。
一個業務系統本身也分為多個模塊或組件,那么模塊間的接口本身穩定性就很重要,那么接口如何保證可擴展?對于接口的擴展實際上和數據庫表擴展思路類似,我們可以在接口上面啟用多個擴展字段,也可以在接口中啟用一個存儲大 Json 串的擴展字典,在 Json 串中可以靈活定義和傳輸多個字段內容。
一個業務系統本身的變更往往涉及到數據對象的變更,流程的變更和規則的變更。而這里面最麻煩的就是規則的變更,而規則的變更說到擴展和可配置性,大家容易想到的就是啟用規則引擎來進行處理。而實際上對于復雜規則的實現,即使你采用了規則引擎,里面也要寫大量的腳本代碼,即這部分采用規則引擎本身并沒有太大的意義可言。因此對于規則的擴展核心是如何將規則從原有的業務系統單據中剝離出來,即我們首先定義的標準的規則擴展接口,同時在接口中輸入你需要使用到的數據對象,當需要擴展的時候我們僅僅對接口內容進行實現。
可以構想一個最簡單的場景,對于采購訂單創建功能,我們可以考慮在訂單創建 Button 事件處理中增加對接口方法的擴展和調用。即訂單保存的時候涉及到如下步驟:
//ISaveBefore.Process(Form Data); //Save(); //ISaveAfter.Process(Form Data);即當你需要在訂單保持前進行預處理,或者是在訂單保持成功后進行額外操作的時候,你完全可以對上面兩個接口方法進行實現。這兩個接口方法實際上對保存事件前后進行了攔截,而攔截到的內容如何處理你完全可以自己進行擴展。
為何要采用上面的方式進行設計?你可以想下如果一個 CRM 系統你面臨諸多的客戶,每個客戶可能都存在會在你的標準 CRM 版本上面進行定制。對于訂單創建功能 90%的功能都是標準功能,但是僅僅是前后的處理規則和邏輯有少量差異。那么我們這樣設計就很方便針對不同的客戶擴展不同的定制代碼包,而確保 CRM 產品主干版本只有一套,這種方式可以最大化產品復用度,同時由標準化配置管理工作。
其次當我們實施了上百家客戶的 CRM 系統后,你會發現所有用到的規則本身也可以進行標準化,比如標準化為 100 個規則邏輯,而實際上客戶在實施的時候是選擇要啟用哪些規則控制。這個時候你就可以考慮規則本身也可進行靈活配置的事情了。
舉例來說。
ISaveBefore.Process(Form Data) {//將不同的規則項獨立出來BusinessRule1();BusinessRule2();BusinessRuleN(); }然后我們再需要一個簡單的配置表,來配置一個新客戶究竟啟用哪些規則項就可以了。對于啟用的規則項就執行,對于不啟用的規則項就不執行。在這種處理方式下,雖然我們沒有啟用規則引擎,但是規則本身形成了條目化的規則庫或規則片段,其次規則片段可以靈活綁定到客戶項目上。這種規則處理的靈活性將足夠我們在實際實施項目中靈活應對。
通過類似 AOP 的思路,攔截進行擴展,將是應用層擴展的一個關鍵思路點。這種擴展方式雖然沒有實現完全的靈活可配置化,但是卻具備了相當的靈活性和可管理性。
2
? ?
基于 SOA 思想擴展性設計
再重新強調下 SOA 架構思想的一個關鍵即上層的應用或流程應該是基于服務組裝和編排出來的,當上層應用出現變化的時候,很多時候并不需要底層的服務進行變化或修改,而只需要對服務重新進行組裝。
這個和當前我們談的中臺架構思想是一致的,即前端應用會出現業務需求變更或變化,但是大部分時候中臺能力并不需要變化,而只需要對前端應用邏輯進行修改。
在私有云 PaaS 平臺建設里面,我當時就給出了結合 SOA 架構思想的一個完整的業務組件邏輯設計的一個參考圖,具體如下:
在整個架構中,橫向分為了平臺層,服務層和應用層。對于服務層可以理解為當前中臺提供的共享 API 服務能力開放是一個道理。對于應用層,原來叫薄應用,也可以理解當前微服務下的前端應用。整體的架構完全符合我在前面一篇文章談到的資源+服務+應用的三層架構模式。
對于應用層而言,其中仍然分為數據層、業務邏輯層和展現層的三層架構模式:
2.1
? ?
數據層
數據層主要包括了對于主數據等共享數據的訪問和讀取,也包括了對業務組件模塊自己私有數據的 CRUD 操作。數據層可以直接調用 DaaS 服務層能力操作底層數據庫,也可以直接調用封裝后的領域數據服務能力查詢和訪問數據。
2.2
? ?
業務邏輯層
業務邏輯層和傳統業務邏輯層最大的區別是體現了 SOA 服務化的思想。即對于業務流程和功能的業務實現是通過平臺層提供的技術服務和業務服務能力進行組合和組裝實現的。這既可以通過傳統的代碼開發和服務調用來實現,也可以通過類似 BPEL 設計和建模工具等可視化的進行靈活配置和實現。
可以看到,對于業務邏輯層的重點就是對已有的各種業務服務,數據服務,技術服務能力進行組合,完成一個關鍵的業務功能實現。
2.3
? ?
展現層
展現層主要是各種前端和界面實現技術,傳統的如 JSP,HTML,JQuery 等。也包括當前主流的類似 VUE,React, Angular 等 Web 前端開發框架。展現層通過調用邏輯層的服務能力進行數據的存取和業務規則的實現,同時也包括了界面集成技術實現多個業務組件的界面集成。
3
? ?
業務系統可擴展總結
最后再簡單總結下一個應用系統的可擴展設計。
其一,可擴展設計涉及到數據庫,應用層,業務規則邏輯,界面層的多處可擴展性。必須要各個分層,各個點上都考慮到可擴展性,往往才能夠完成一個完整的擴展性設計需求。
其二,可擴展性設計一方面是解決的業務系統并發量增加后的可擴展能力,一個方面重點是解決的業務需求變更的時候系統本身的適應變化度。對于變化的適應本身又分多個層面,即是否需要變更數據庫,是否需要變更應用開發代碼,是否需要重新編譯等。在擴展性設計中最好的就是盡量不要涉及到重新編譯和版本部署。
其三,可擴展性設計往往會犧牲性能,因此也不能過度的使用擴展性和冗余設計,導致整體應用架構性能出現明顯下降。
原文轉自:https://www.toutiao.com/i6897886759997178372/?
- EOF -
想要加入中生代架構群的小伙伴,請添加群合伙人大白的微信
申請備注(姓名+公司+技術方向)才能通過哦!
阿里技術專家光錐:億級長連網關的云原生演進之路
CPU虛擬化系列文章之虛擬機切入和退出
RocketMQ 專家丁威:Kafka 和 RocketMQ 從性能角度對比
DDD專家張逸:《解構領域驅動設計》前言
張凱江:架構能力-“構建”世界的能力
申通快遞在雙11的云原生應用實踐
阿里云原生張羽辰:服務發現技術選型那點事兒
監控之美——Prometheus云原生監控
徐昊:運用四色建模法進行領域分析
多隆:從工程師到阿里巴巴合伙人
58 轉轉技術總監駱俊武:一個核心系統 3 萬多行代碼的重構實戰篇
? ?END ? ?? #架構師必備#點分享點點贊點在看
總結
以上是生活随笔為你收集整理的人月聊IT:对业务系统的可扩展性设计思考的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ural 1207. Median on
- 下一篇: hdu-1392 Surround th