一、軟件架構風格
“每一個模式描述了一個在我們周圍不斷重複發生的問題及該問題解決方案的核心。這樣,你就能一次又一次地使用該方案而不必做重複工作”。模式的關鍵在於模式的可重複性,問題與場景的可重複性帶來解決方案的可重複使用。而架構也與此同義,爲了實現系統的高性能、高可用、易伸縮、可擴展、安全等各種技術架構目標,各大互聯網公司提出各種解決方案,這些方案被業界複用,從而逐漸形成大型網站架構模式。
分層是企業應用系統中最常見的一種架構模式,將系統在橫向維度上切分成幾個部分,每個部分負責一部分相對比較單一的職責,然後通過上層對下層的依賴和調用組成一個完整的系統。
分層在計算機世界無處不在,在本項目也用到了,如下圖:
主要層分爲負責處理請求的api層,負責業務處理的service層,負責數據處理的model層,其他還有負責緩存的cache層,中間件層middleware以及一些配置層等等,具體見下圖:
分割就是即是縱向方面對軟件進行切分。本系統以問答爲核心,粒度適中,比如服務層目前分割成用戶,問題,回答等,其中問題又可分割成普通問題和熱點問題,其對應頁面展示也有所不同。
數據訪問熱點不均衡,頻繁數據放在緩存中,並且有一定期限不會長期佔用寶貴內存,通過緩存加快數據訪問速度,減輕後端應用和數據存儲的負載能力,這種設計對數據庫架構十分重要。
本系統採用redis遠程字典式緩存服務,將部分熱點數據進行緩存,能夠快速響應用戶對熱點內容讀取的需求,另外點贊收藏等易變化的部分數據不立即存入數據庫,而是通過緩存操作加定時任務,實現弱一致性的數據存取。
系統的安全問題也是架構設計中必須要考慮到的,比如直接使用https進行通信,選擇更好的加密算法也是需要考慮好的。本項目主要使用Bcrypt算法。用戶表的密碼通常使用MD5等不可逆算法加密後存儲,爲防止彩虹表破解更會先使用一個特定的字符串加密,然後再使用一個隨機的salt加密。 特定字符串是程序代碼中固定的,salt是每個密碼單獨隨機,一般給用戶表加一個字段單獨存儲,比較麻煩。 BCrypt算法將salt隨機並混入最終加密後的密碼,驗證時也無需單獨提供之前的salt,從而無需單獨處理salt問題。
二、接口設計風格
談完了系統的架構風格,我們來談談接口設計的策略風格。一個後端系統主要任務就是設計好各種不同任務的底層接口,一個好的接口設計往往利於提高系統的解耦程度,而一個好的設計規範更能方便使用者調用,也利於後端開發人員理解任務的性質。
本系統採用restful風格的API設計規範,即"動詞 + 賓語"的結構組成的數據操作指令,主要涉及get(讀取)、post(新建)、put(更新)、patch(部分更新)和delete(刪除)。
此外,響應狀態碼也應該精確,這裏是內部返回響應,主要包含狀態碼,提示信息,數據,如下圖通用返回結構體:
三、軟件系統概念原型下的視圖
一個系統無論大小,皆可分模塊,通過視圖勾劃出系統結構,往往會通過不同抽象層級的軟件模塊形成層次化的結構。
如下圖,可知大致功能劃分。
各層依賴視圖:
關於泛化視圖,由於採用的是面向過程的go語言沒有類與類的繼承等特性,但採用了組合方式來實現各層函數的調用。例如model層需要定義answer結構體,並且爲這個實體嵌入一些常用方法,以供service層調用。
關於執行視圖,這裏以判斷用戶是否能修改問題的時序圖來舉例:
也可看看用例圖:
部署視圖,本系統採用docker部署:
四、軟件系統運行環境和技術選型說明
編程語言:go
web框架:gin
orm:gorm
緩存:redis
消息中間件:rabbitMQ
運行環境:Linux+docker
五、數據庫設計
設計者的概念模型和最終用戶的概念模型。設計模型作爲產品設計者的概念模型,是對產品構成結構和操作方式的系統化、結構化描述;相對應的用戶模型,是用戶在產品使用過程中形成的關於產品構成和操作方式等的結構化理解。而設計者是通過一系列視覺線索,以及用戶的產品使用過程將設計模型傳遞給用戶,並最終轉換爲用戶概念模型。設計模型和用戶模型的最理想狀態就是二者完全等同,即產品的所有設計意圖和操作方式完全被用戶所理解。因此實體的劃分與聯繫至關重要,由功能結構分析可知,系統需包含用戶、用戶信息、問題、問題標籤、回答、收藏、消息實體,大致E-R圖如下:
- 通用字段
列名 |
數據類型 |
長度 |
唯一 |
非空 |
註釋 |
id |
int |
11 |
是 |
是 |
通用主鍵 |
created_at |
datetime |
|
否 |
否 |
創建時間 |
updated_at |
datetime |
|
否 |
否 |
更新時間 |
deleted_at |
datetime |
|
否 |
否 |
刪除時間 |
- 用戶表(user)
列名 |
數據類型 |
長度 |
唯一 |
非空 |
註釋 |
username |
varchar |
255 |
是 |
是 |
用戶名 |
password |
varchar |
255 |
否 |
是 |
密碼 |
nickname |
varchar |
255 |
否 |
否 |
暱稱 |
|
varchar |
255 |
是 |
是 |
郵箱 |
avatar |
text |
|
否 |
是 |
頭像 |
status |
int |
11 |
否 |
是 |
狀態 |
user_profile_id |
int |
11 |
是 |
是 |
用戶信息邏輯外鍵 |
- 用戶信息表(user_profile)
列名 |
數據類型 |
長度 |
唯一 |
非空 |
註釋 |
|
varchar |
255 |
否 |
否 |
郵箱 |
phone |
varchar |
255 |
否 |
否 |
手機號 |
description |
varchar |
100 |
否 |
否 |
個人介紹 |
- 問題標籤表(tag)
列名 |
數據類型 |
長度 |
唯一 |
非空 |
註釋 |
name |
varchar |
255 |
否 |
是 |
名字 |
description |
varchar |
1000 |
否 |
是 |
描述 |
icon |
varchar |
255 |
否 |
否 |
圖標url |
topic_count |
int |
11 |
否 |
是 |
所屬問題個數 |
- 問題表(topic)
列名 |
數據類型 |
長度 |
唯一 |
非空 |
註釋 |
title |
varchar |
255 |
否 |
是 |
標題 |
content |
text |
1000 |
否 |
否 |
簡述 |
user_id |
Int |
11 |
否 |
是 |
用戶id |
comment_count |
int |
11 |
否 |
是 |
評論總數 |
collect_count |
int |
11 |
否 |
是 |
收藏總數 |
view |
int |
11 |
否 |
是 |
點擊量 |
top |
bit |
1 |
否 |
是 |
是否置頂 |
up_count |
int |
11 |
否 |
是 |
點贊次數 |
down_count |
Int |
11 |
否 |
是 |
點踩次數 |
- 標籤-問題表(topic_tag)
列名 |
數據類型 |
長度 |
唯一 |
非空 |
註釋 |
tag_id |
int |
11 |
否 |
是 |
標籤id |
topic_id |
int |
11 |
否 |
是 |
問題id |
六、項目源代碼文件結構
總體如下:
主要層下級目錄:
七、概念原型核心工作機制
在系統架構時經常會採用概念原型來使得跟系統相關的所有成員,如客戶、用戶、開發人員等對系統初步達成一致的理解。其中,分解不同的視圖,能狗從不同的視角來掌握整個業務的大致流程。
從上文結合數據庫設計可知,本系統主要有用戶模型,問題模型,回答模型等主體模型。