go-ums 從需求分析到設計實現( v0.1.0 )
_ gocn 的編輯器完全支援 markdown 啊, 這下發長文方便了. :P
_
專案原始碼地址 https://github.com/tsingson/go-ums
文字有點長, 儘量寫得簡單明瞭
文章概括內容都寫上了, 由於文件進一步細化並補充更多需求後, 需要拆分為設計文件/介面文件/測試文件/評審文件.....等等, 這裡不再持續更新.
後續補充變更, 請訪問 專案原始碼地址
0. go-ums 是什麼
go-ums 開發目標是一個開源專案, 核心由 golang 開發, 提供使用者管理(user-management-subsystem) / AAA 認證/鑑權/授 / 多業務會話共享與管理等, 以支援分散式部署及雲部署為主要目標
這是一個從零開始的小專案, 持續漸進
在 reading-go 夜讀 相關 issue 討論中, 有個 gin 的練手專案, 有點意思.
這是一個類似的專案, 不同的地方是, 這個專案是以文件開始的.
更多專案關聯文件, 請訪問 https://github.com/tsingson/go-ums , 在 readme 中列示並持續新增中
先有文件, 再寫程式碼. 在文件簡單說明一些我的設計套路
注: 這裡的設計, Design, 不限於架構設計, 程式設計, 也包含個人在攝影/印刷/書籍/海報中找出問題/解決問題的一些"套路".
先文件, 後實施, 也是曾經作 SA/SE 的習慣了吧. 當年曾戲稱自己是 Simple Editor , 哈, 懷念那8年, 大鬍子, yaho BB, black more, 北京香山, 上海文廣,三角洲島.......
稍後在持續更新中一一道來, 看看橫向之間的有趣關聯.
1. 業務場景
不談業務需求, 與業務場景中的人兒們,再好的技術也難以落地變現.
這就是原始需求的收集/整理/清理/梳理, 是開發貫串始終的目標與仲裁準則:
- 是什麼? 有什麼價值?
- 是誰在用? 如何用( 業務操作流程)? 哪些是關鍵節點(不能省掉的業務行為), 重點與難點是什麼?
- 在這些業務場景中, 邊界在哪裡( 哪些情況是正常, 哪些是異常, 如何判定, 什麼時間什麼情況下有哪些處理方式)
從一個簡單而典型的業務場景開始, 來
1.1 業務場景/需求描述
這個開源專案是從 goim 在開源社群交流討論後, 在 reading-go 討論中偶然開始的
從業多年, 個人幾乎不在網路上談論個人在 iT 技術職業經歷, 尤其是專案細節, 這裡, 算是換個方式來公開談談吧
所以, 這裡也從 goim 作為起點
很多朋友, 在閱讀 goim 原始碼時, 都會感覺到, 就算是 im 業務完整實施, 需要與使用者管理結合:
- 使用者註冊後, 提供一個使用者唯一標識, , 對應 goim 中的 mid
- 使用者認證, 讓使用者可以長連線到 goim , 在認證成功時
- 提供一個 token , 該 token 中包含使用者可以進入的房間列表
- 提供使用者傳送 im 資訊的入口地址( logic 部署多個情況下)
- 使用者在 goim 中涉及會話的業務功能( 變更房間.....)
所以, 我們可以從上面描述到的, (不能省掉的) 基本業務功能開始
來, 來, 來 ...GO!
1.1.1 場景與流程簡述
( 省略)
稍後補充示意圖
1.1.2 業務指標(效能要求)
(簡化)
- 要求業務響應, 排除網路延遲, 業務響應要求在 100ms 以內
- 支援10K tps 高併發
- 年度業務中斷時間低於5次, 業務中斷時間低於30分鐘
- 業務資料保留期限 1年
- 業務操作記錄要求支援審計
1.2.3 部署要求
(簡化)
- 伺服器部署中國骨幹網路IDC (電信網路為主, 廣州/上海兩地IDC ) 及美國骨幹網路IDC ( 略)
- 以部署服務端優先支援 linux 與 docker
- 客戶端支援 windows / mac / linux 的 terminal 命令列, 支援主流瀏覽器( 當前市場佔80%的主流版本, 相當於 IE 10+)
1.2.4 開發/運維/運營要求
(省略)
1.2.5 成本要求
(省略)
1.2 feature list 需求列表
注, 以下按開發進度作了分組.
分組的意思, 就是排優先順序, 排優先順序即是排重要/緊急程度(按 SWOT Analysis 方式), 以決定先後處理順序.
1.2.1 prototype 開發需求 v0.1.0
使用者相關操作
- [ ] 使用者註冊 register 使用者以 email + 密碼 註冊提交個人資訊, 提交後驗證 email 是否存在唯一衝突, 如果沒有, 註冊成功( 分配使用者ID) 注意, 這裡隱藏著一個檢查使用者是否存在的操作
- [ ] 使用者登入與登出 login / logout 使用者以 email + passwrd 或 使用者名稱 + password 或 userID + password 可以進行登入, 登入成功, 給使用者傳送通行令牌 accessToken 注意, 這裡隱藏著一個檢查使用者登入成功返回一個 access token 的操作
- [ ] 使用者認證 authentication 針對具體業務, 使用者訪問具體業務時, 傳送 access token 進行認證, 如果使用者認證成功, 可以訪問指定業務, 否則拒絕. 一般來說, 使用者認證成功即表示建立一個合法的業務會話
- [ ] 使用者通行令牌驗證 verify 使用者訪問指定業務時, 驗證 token 是否在有效期內, 以及相關授權是否有變更, 如不符合業務授許可權制, 則拒絕提供服務
1.2.2 trial 試執行 v0.1.1
使用者相關操作
- [ ] 使用者啟用 active 使用者註冊後, 向使用者郵箱傳送 email 驗證的啟用郵件, 使用者從郵件中獲取啟用碼後, 進行啟用操作
- [ ] 使用者登入與登出 login / logout
使用者以 email + passwrd 或 使用者名稱 + password 或 userID + password 可以進行登入, 登入成功, 給使用者傳送通行令牌 accessToken
- [ ] 使用者鎖定 suspend 禁止使用者業務消費行為, 一般來說, 使用者在具體業務上, 會有指定的服務週期, 超出服務週期, 使用者被鎖定
- [ ] 使用者恢復 resume 恢復使用者授權的業務行為
- [ ] 使用者刪除 deleted 使用者刪除自己或管理後臺刪除使用者, 注意, 在商用中, 使用者“刪除”一般意味著使用者狀態修改為 deleted 並停止所有訪問與所有業務, 但保留所有關聯資料( 這些關聯資料, 只有在一定期限後, 會手動或自動清除 purge )
2. 概要設計之模型設計
參照 1.2.1 小節, 很容易作一個簡單設計
2.1 資料模型
使用者物件名稱 account
- 使用者ID, 與 goim 配合, 就用 int64 吧, 一個全域性唯一的正整數
- email , (簡化), 都是字串, email 格式也不驗證, 其中 email 字串長不得少於5個字元( >=5 ) ,
- password, (簡化) 都是字串, 密碼不得少於6個字元( >= 6), 字元為 a..zA..Z0..9$%-
- access tokdn 通告令牌, 也用字串代替吧, 字串長度 >=32 字元
- 使用者角色, 分別為 非會員, 會員
- 使用者狀態, 分別為註冊未啟用, 已啟用, 禁用, 已刪除
- 使用者建立時間, 簡單點, 用 int64 或 UTC timestamp
- 使用者資訊變更時間, 簡單點, 用 int64 或 UTC timestamp
操作結果(狀態)定義
- transaction ID 事務唯一標識
- 狀態碼, 整數, 操作成功返回 200 / 操作失敗返回 500 / 請求接受並在處理中返回202
- 操作結果文字資訊, 少於255字元, 操作成功, 文字資訊, 要求標記業務操作名稱, 如 register ), 操作失敗, 返回失敗原因( 文字資訊 )
注: transaction ID 事務唯一標識, 支援非同步操作, 以支援分散式或叢集, 以及操作失敗時, 進行操作重試( 這樣可以讓服務端處理上次操作失敗的資料, 例如進行清理, 或繼續使用, 以及在日誌中進行檢查/審計)
原型實現的約束與限制:
- 為了快速實現原型, 使用者密碼直接儲存, 不加密
- 使用者ID , 直接用使用者建立的 utc 時間截( 納秒 )
簡化操作結果(狀態定義), 這裡先按 golang 實現習慣方式, 操作結果修改為 go 的 error 返回( 即 error = nil 或 != nil ) 注: 這個地方, 只是針對 go 的簡化
2.2 使用者操作與約束
(簡化)
- 使用者註冊 register ------> 呼叫 exists 檢查是否重複註冊, 如果不是, 建立使用者ID 並儲存使用者信資訊, 返回使用者資料( 不返回密碼), 返回操作結果狀態碼
- 檢查使用者是否重複存在 exists, 返回操作結果
- 使用者登入 login ------> 以 email + pwd 登入, 登入成功, 建立並返回 access token, 返回操作結果狀態碼
- 使用者登出 logout -----> 清除 access token , 返回操作結果狀態碼
- 使用者認證 auth -------> 輸入使用者ID 或 token , 呼叫 verify 檢查 會話中的token 是否合法, 如果 token 合法則返回成功, 返回操作結果狀態碼
- 使用者令牌驗證 verify --------> 檢查 token 是否存在, 並且是否相等, 返回操作結果狀態碼
2.3 業務流程設計 (僅以 register 使用者註冊為例)
2.3.1 register 使用者註冊
業務流程描述: 客戶端 ----------> 服務端, 進行使用者註冊, 傳送註冊資料, 由伺服器端返回註冊成功(獲取使用者ID ) 或失敗資訊
----> 輸入:
- transaction ID 事務唯一標識
- email 合法郵箱地址
- password 密碼
----> 內部邏輯實現
- 檢查 email 是否重複( 即被成功註冊過), 判斷沒有重複, 則進行 2, 判斷有重複, 進行下說明 3
- 生成使用者 ID , 並儲存到檔案或資料庫, 儲存成功, 返回成功結果輸出, 儲存失敗, 進行下說明 3
- 處理錯誤輸出
- 以上處理, 每一步均以 事務 ID 與時間為主鍵存日誌
----> 輸出
輸出 (成功, 返回使用者資訊, 遮蔽密碼欄位)
- account ID 使用者ID
- 使用者角色
- 使用者狀態
- 建立時間
-
變更時間
輸出 (失敗, 返回事務標識, 錯誤狀態碼, 錯誤原因文字)
- transaction ID 事務唯一標識
- 返回操作結果狀態碼
- 操作結果文字描述
2.3.2 介面設計
大白話:
介面就是兩個網元之間, 進行互動/通訊的網路協議/控制通訊命令(信令)/以約定格式傳輸相關資料(資料封裝)的簡稱
例如 web 瀏覽器與 web 伺服器這兩個網元之間, 一般採用 HTTP 協議, 信令是 GET / POST / PUT / PATCH / DELETE ...., 資料封裝通常是以 MIME 來指定, 比如下面用到的 "application/json; charset=utf-8"
設計實現以下介面
- RESTful 介面 ( 描述省略, 見程式碼)
- gRPC ( protobuf ) 介面 ( 略 )
- gRPC ( flatbuffers ) 介面( 對接 android java SDK , 詳細說明略)
- websocket 介面 ( 略 )
- TCP 介面 ( 略 )
2.3.2.1 RESTful 介面設計
關於 RESTful 介面, 相關推薦規範, 請自行查詢
這裡先簡要說明一下:
RESTful 通常是 HTTP + json 實現的介面, 其中
類似 /api/v1/account 這樣的 URI 就是一個介面, 其中 /api/v1 字首只是輔助管理
在下面我們示例實現的使用者註冊介面, 可以定義為 /api/v1/register 或者 /xxx/yyyy 這樣你喜歡的方式
- HTTP 的 method 就是操作方式, 例如:
- GET:讀取(Read)
- POST:新建(Create)
- PUT:更新(Update)
- PATCH:更新(Update),通常是部分更新
- DELETE:刪除(Delete)
資料編碼(序列化/反序列化) 是 "application/json; charset=utf-8” 標的 JSON 格式
- 少量操作關聯資料, 可以在 HTTP header 中傳遞, 比如 transactionID/ token / cookie , 這些關聯資料, 一般用來協助狀態跟蹤
2.3.2.1.1 使用者註冊
對照 2.3.1 , 使用者註冊的介面, 可以設計如下
--------->input請求
請求資源
POST 請求以下網址 http://localhost:3001/api/v1/register
request header
Context-Type: "application/json; charset=utf-8"
TransactionID: "201001419845668864"
request body
{
"email": "test@email.com",
"password": "201001419845668864"
}
--------->output返回
response header
Context-Type: "application/json; charset=utf-8"
TransactionID: "201001419845668864"
操作成功, 返回 http 狀態碼 200, 返回資料如下
response body
{
"email": "test@email.com",
"password": "201001419845668864"
}
操作失敗, 返回狀態碼 500, 返回資料如下
**
{
"transactionID":"201001419845668864"
"code": 500,
"msg": "使用者Email已經被其他使用者使用, 請選擇其他email重新註冊"
}
其他部分, 稍後補充.........
2.3.3 測試用例如下
- 檢查 email 無重複, 操作成功
- 檢查 email 有重複, 操作失敗
- 異常, 主要關注兩個, 儲存失敗或異常, 通訊異常中斷 (詳細說明, 省略)
3.概要設計之架構設計
先簡化為以下架構作為驗證原型開發
client ( 多個) <----> gateWay( HA熱備, 支援路由/分流等) <-----> AAA (本地快取, 多個部署)<-------> UMS ( 雙機熱備)
其中:
- client 到 AAA 首先實現 RESTful
- AAA 到 UMS 之間, 選擇 gRPC + flatbuffers
- UMS 後儲存, 選擇 redis + postgreSQL
稍後補充.........
4. 詳細設計
4.1 設計目標與原則
由於需求原因, 我們需要考慮達成以下目標:
- 低延遲, 高容量, 高併發
- 可擴充套件的多點部署, 雲部署
所以, 先拍腦袋隨意定義一下要實現目標, 如下所示. 接下來, 再評估哪些真正需要, 優先順序, 以及具體實現方案
- 網元之間無狀態
- 執行緒之間無鎖
- 儘可能快的網元間介面通訊
- 儘可能減少介面之間資料序列化/反序列化的次數, 加快介面之間資料序列化/反序列化的效率
- 網元支援按需動態擴充套件或收縮部署, 簡單點, 就是網元健康檢查 + 路由 + 分流可控制
- 支援 QOS 控制, 先支援限流
4.2 設計實現 ( golang 為例)
稍後補充說明部分
4.2.1 模型的實現
使用者模型與操作的 golang 實現
見 [https://github.com/tsingson/go-ums/blob/master/model/account.go]
(說明省略)
4.2.2 介面設計的實現
見 [https://github.com/tsingson/go-ums/blob/master/model/account.go]
(說明省略)
4.2.3 業務邏輯實現
見 https://github.com/tsingson/go-ums/blob/master/pkg/services/account.go
(說明省略)
4.2.4 UT ( Unit Test) 單元測試
測試用例如下
- 檢查 email 無重複, 操作成功
- 檢查 email 有重複, 操作失敗
- 其他異常( 略)
見 /pkg/service 下測試程式碼
4.3 LIT ( local integration test) 網元整合測試
見 /pkg/web 下各測試程式碼
4.4 SIT ( system intergration test ) 系統整合測試
見 /cmd/cli 下程式碼
稍後補充..........
4.5 編譯/部署/運維
稍後補充.............
5. 效能測試/部署測試/ trial 驗證
省略 ...
6. 附註/參考
6.1 介面設計相關參考
_
_
關於我
網名 tsingson (三明智, 江湖人稱3爺)
原 ustarcom IPTV/OTT 事業部播控產品線技術架構溼/解決方案工程溼角色(8年), 自由職業者,
喜歡音樂(口琴,是第三/四/五屆廣東國際口琴嘉年華的主策劃人之一), 攝影與越野,
喜歡 golang 語言 (商用專案中主要用 postgres + golang )
_
題圖: 2018/12/24 香港黑白攝影展前, 與深圳影友在香港街頭
_
tsingson 寫於中國深圳
小羅號口琴音樂中心, 2019/05/11
相關文章
- go-ums 從設計到實現( v0.1.0 )-持續更新Go
- 從需求分析、產品設計到部署交付各階段說明
- NodeJs 實戰——原生 NodeJS 輕仿 Express 框架從需求到實現(二)NodeJSExpress框架
- # NodeJs 實戰——原生 NodeJS 輕仿 Express 框架從需求到實現(一)NodeJSExpress框架
- Socket程式設計,從TCP分析到建立web網站程式設計TCPWeb網站
- 《Python程式設計:從入門到實踐》Python程式設計
- 需求分析之道——需求分析要做什麼(C系架構設計法,sishuok)架構
- [從RPC到Go-Micro 壹]Go語言實現RPC程式設計RPCGoC程式程式設計
- 從2012到2021,從土木到程式設計師程式設計師
- 從設計到歸因 - AB Test 實戰心得
- Python 程式設計從入門到實踐5Python程式設計
- 對工程實踐——基於智慧物聯結點的設計與實現進行需求分析和建模
- 從程式設計到養生程式設計程式設計
- 需求設計
- 如何從 0 到 1 設計、構建移動分析架構架構
- 《率土之濱》專題,從遊戲設計到玩法分析遊戲設計
- 隱私計算DataTrust:從產品需求到工程架構實踐(連載2)Rust架構
- Python實現微博輿情分析的設計與實現Python
- [前端怪談_2] 從 Dva 的 Effect 到 Generator + Promise 實現非同步程式設計前端Promise非同步程式設計
- [前端漫談_2] 從 Dva 的 Effect 到 Generator + Promise 實現非同步程式設計前端Promise非同步程式設計
- 掰扯掰扯需求分析:從工程到生活中的4個case
- 從0到1實現PromisePromise
- 報表合計需求的實現方法
- 實驗二-需求分析
- 實驗二:需求分析
- 實驗2:需求分析
- 從0到1實現一個簡單計算器
- 從業務測試需求痛點到自動化測試平臺設計開發
- 從碼農到設計者,從單例模式入手設計程式碼單例模式
- 關於意義:從現實到遊戲,從自我到自由遊戲
- Python專案實戰(一)《Python程式設計 從入門到實踐》Python程式設計
- Python 指令碼高階程式設計:從基礎到實踐Python指令碼程式設計
- 日誌實時分析:從入門到精通
- 專業程式設計師進階之路:從需求出發程式設計師
- 道觀小程式架構設計與實現分析架構
- 如何在遊戲設計中實現優雅藝術?從流程解析到具體例項遊戲設計
- 從0到1實現VueUI庫思路VueUI
- Object.assign()從認識到實現Object