專案原始碼 github.com/tsingson/go…
文字有點長, 儘量寫得簡單明瞭,並持續更新
0. go-ums 是什麼
go-ums 開發目標是一個開源專案, 核心由 golang 開發, 提供使用者管理(user-management-subsystem) / AAA 認證/鑑權/授 / 多業務會話共享與管理等, 以支援分散式部署及雲部署為主要目標
這是一個從零開始的小專案, 持續漸進
在 reading-go 夜讀 相關 issue 討論中, 有個 gin 的練手專案, 有點意思.
這是一個類似的專案, 不同的地方是, 這個專案是以文件開始的.
更多專案關聯文件, 請訪問 github.com/tsingson/go… , 在 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.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 使用者註冊(示例)
----> 輸入:
- transaction ID 事務唯一標識
- email 合法郵箱地址
- password 密碼
----> 內部邏輯實現
- 檢查 email 是否重複( 即被成功註冊過), 判斷沒有重複, 則進行 2, 判斷有重複, 進行下說明 3
- 生成使用者 ID , 並儲存到檔案或資料庫, 儲存成功, 返回成功結果輸出, 儲存失敗, 進行下說明 3
- 處理錯誤輸出
- 以上處理, 每一步均以 事務 ID 與時間為主鍵存日誌
----> 輸出
輸出 (成功, 返回使用者資訊, 遮蔽密碼欄位)
- account ID 使用者ID
- 使用者角色
- 使用者狀態
- 建立時間
- 變更時間
輸出 (失敗, 返回事務標識, 錯誤狀態碼, 錯誤原因文字)
- transaction ID 事務唯一標識
- 返回操作結果狀態碼
- 操作結果文字描述
2.3.2 介面設計
設計實現以下介面
- RESTful 介面 ( 描述省略, 見程式碼)
- gRPC ( protobuf ) 介面 ( 略 )
- gRPC ( flatbuffers ) 介面( 對接 android java SDK , 詳細說明略)
- websocket 介面 ( 略 )
- TCP 介面 ( 略 )
2.3.3 測試用例如下
- 檢查 email 無重複, 操作成功
- 檢查 email 有重複, 操作失敗
- 異常, 主要關注兩個, 儲存失敗或異常, 通訊異常中斷 (詳細說明, 省略)
3.設計實現 ( golang 為例)
3.1 模型的實現
使用者模型與操作的 golang 實現
(說明省略)
3.2 介面設計的實現
(說明省略)
3.3 業務邏輯實現
(說明省略)
3.4 單元測試
測試用例如下
- 檢查 email 無重複, 操作成功
- 檢查 email 有重複, 操作失敗
- 其他異常( 略)
3.5 整合測試
省略..........
4. 效能測試/部署測試/ trial 驗證
省略 ...
5. 附註/參考
持續...
_
關於我
網名 tsingson (三明智, 江湖人稱3爺)
原 ustarcom IPTV/OTT 事業部播控產品線技術架構溼/解決方案工程溼角色(8年), 自由職業者,
喜歡音樂(口琴,是第三/四/五屆廣東國際口琴嘉年華的主策劃人之一), 攝影與越野,
喜歡 golang 語言 (商用專案中主要用 postgres + golang )
_
題圖: 2018/12/24 香港黑白攝影展前, 與深圳影友在香港街頭
_
tsingson 寫於中國深圳
小羅號口琴音樂中心, 2019/05/11