go-ums 從設計到實現( v0.1.0 )-持續更新

tsingson發表於2019-05-11

專案原始碼 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. 是什麼? 有什麼價值?
  2. 是誰在用? 如何用( 業務操作流程)? 哪些是關鍵節點(不能省掉的業務行為), 重點與難點是什麼?
  3. 在這些業務場景中, 邊界在哪裡( 哪些情況是正常, 哪些是異常, 如何判定, 什麼時間什麼情況下有哪些處理方式)

從一個簡單而典型的業務場景開始, 來

1.1 業務場景/需求描述

這個開源專案是從 goim 在開源社群交流討論後, 在 reading-go 討論中偶然開始的

從業多年, 個人幾乎不在網路上談論個人在 iT 技術職業經歷, 尤其是專案細節, 這裡, 算是換個方式來公開談談吧

所以, 這裡也從 goim 作為起點


很多朋友, 在閱讀 goim 原始碼時, 都會感覺到, 就算是 im 業務完整實施, 需要與使用者管理結合:

  1. 使用者註冊後, 提供一個使用者唯一標識, , 對應 goim 中的 mid
  2. 使用者認證, 讓使用者可以長連線到 goim , 在認證成功時
    1. 提供一個 token , 該 token 中包含使用者可以進入的房間列表
    2. 提供使用者傳送 im 資訊的入口地址( logic 部署多個情況下)
  3. 使用者在 goim 中涉及會話的業務功能( 變更房間.....)

所以, 我們可以從上面描述到的, (不能省掉的) 基本業務功能開始

來, 來, 來 ...GO!

1.1.1 場景與流程簡述

( 省略)

稍後補充示意圖

1.1.2 業務指標(效能要求)

(簡化)

  1. 要求業務響應, 排除網路延遲, 業務響應要求在 100ms 以內
  2. 支援10K tps 高併發
  3. 年度業務中斷時間低於5次, 業務中斷時間低於30分鐘
  4. 業務資料保留期限 1年
  5. 業務操作記錄要求支援審計

1.2.3 部署要求

(簡化)

  1. 伺服器部署中國骨幹網路IDC (電信網路為主, 廣州/上海兩地IDC ) 及美國骨幹網路IDC ( 略)
  2. 以部署服務端優先支援 linux 與 docker
  3. 客戶端支援 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

  1. 使用者ID, 與 goim 配合, 就用 int64 吧, 一個全域性唯一的正整數
  2. email , (簡化), 都是字串, email 格式也不驗證, 其中 email 字串長不得少於5個字元( >=5 ) ,
  3. password, (簡化) 都是字串, 密碼不得少於6個字元( >= 6), 字元為 a..zA..Z0..9$%-
  4. access tokdn 通告令牌, 也用字串代替吧, 字串長度 >=32 字元
  5. 使用者角色, 分別為 非會員, 會員
  6. 使用者狀態, 分別為註冊未啟用, 已啟用, 禁用, 已刪除
  7. 使用者建立時間, 簡單點, 用 int64 或 UTC timestamp
  8. 使用者資訊變更時間, 簡單點, 用 int64 或 UTC timestamp

操作結果(狀態)定義

  1. transaction ID 事務唯一標識
  2. 狀態碼, 整數, 操作成功返回 200 / 操作失敗返回 500 / 請求接受並在處理中返回202
  3. 操作結果文字資訊, 少於255字元, 操作成功, 文字資訊, 要求標記業務操作名稱, 如 register ), 操作失敗, 返回失敗原因( 文字資訊 )

注: transaction ID 事務唯一標識, 支援非同步操作, 以支援分散式或叢集, 以及操作失敗時, 進行操作重試( 這樣可以讓服務端處理上次操作失敗的資料, 例如進行清理, 或繼續使用, 以及在日誌中進行檢查/審計)

原型實現的約束與限制:

  1. 為了快速實現原型, 使用者密碼直接儲存, 不加密
  2. 使用者ID , 直接用使用者建立的 utc 時間截( 納秒 )
  3. 簡化操作結果(狀態定義), 這裡先按 golang 實現習慣方式, 操作結果修改為 go 的 error 返回( 即 error = nil 或 != nil ) 注: 這個地方, 只是針對 go 的簡化

2.2 使用者操作

(簡化)

  1. 使用者註冊 register ------> 呼叫 exists 檢查是否重複註冊, 如果不是, 建立使用者ID 並儲存使用者信資訊, 返回使用者資料( 不返回密碼), 返回操作結果狀態碼
  2. 檢查使用者是否重複存在 exists, 返回操作結果
  3. 使用者登入 login ------> 以 email + pwd 登入, 登入成功, 建立並返回 access token, 返回操作結果狀態碼
  4. 使用者登出 logout -----> 清除 access token , 返回操作結果狀態碼
  5. 使用者認證 auth -------> 輸入使用者ID 或 token , 呼叫 verify 檢查 會話中的token 是否合法, 如果 token 合法則返回成功, 返回操作結果狀態碼
  6. 使用者令牌驗證 verify --------> 檢查 token 是否存在, 並且是否相等, 返回操作結果狀態碼

2.3 詳細設計 (僅以 register 使用者註冊為例)

2.3.1 register 使用者註冊(示例)

----> 輸入:
  1. transaction ID 事務唯一標識
  2. email 合法郵箱地址
  3. password 密碼
----> 內部邏輯實現
  1. 檢查 email 是否重複( 即被成功註冊過), 判斷沒有重複, 則進行 2, 判斷有重複, 進行下說明 3
  2. 生成使用者 ID , 並儲存到檔案或資料庫, 儲存成功, 返回成功結果輸出, 儲存失敗, 進行下說明 3
  3. 處理錯誤輸出
  4. 以上處理, 每一步均以 事務 ID 與時間為主鍵存日誌
----> 輸出
輸出 (成功, 返回使用者資訊, 遮蔽密碼欄位)
  1. account ID 使用者ID
  2. email
  3. 使用者角色
  4. 使用者狀態
  5. 建立時間
  6. 變更時間
輸出 (失敗, 返回事務標識, 錯誤狀態碼, 錯誤原因文字)
  1. transaction ID 事務唯一標識
  2. 返回操作結果狀態碼
  3. 操作結果文字描述

2.3.2 介面設計

設計實現以下介面

  1. RESTful 介面 ( 描述省略, 見程式碼)
  2. gRPC ( protobuf ) 介面 ( 略 )
  3. gRPC ( flatbuffers ) 介面( 對接 android java SDK , 詳細說明略)
  4. websocket 介面 ( 略 )
  5. TCP 介面 ( 略 )

2.3.3 測試用例如下

  1. 檢查 email 無重複, 操作成功
  2. 檢查 email 有重複, 操作失敗
  3. 異常, 主要關注兩個, 儲存失敗或異常, 通訊異常中斷 (詳細說明, 省略)

3.設計實現 ( golang 為例)

3.1 模型的實現

使用者模型與操作的 golang 實現

見 [github.com/tsingson/go…]

(說明省略)

3.2 介面設計的實現

見 [github.com/tsingson/go…]

(說明省略)

3.3 業務邏輯實現

github.com/tsingson/go…

(說明省略)

3.4 單元測試

測試用例如下

  1. 檢查 email 無重複, 操作成功
  2. 檢查 email 有重複, 操作失敗
  3. 其他異常( 略)

參見 go-ums v0.1.0 測試/編譯/執行

3.5 整合測試

省略..........

4. 效能測試/部署測試/ trial 驗證

省略 ...

5. 附註/參考

持續...

_

關於我

網名 tsingson (三明智, 江湖人稱3爺)

原 ustarcom IPTV/OTT 事業部播控產品線技術架構溼/解決方案工程溼角色(8年), 自由職業者,

喜歡音樂(口琴,是第三/四/五屆廣東國際口琴嘉年華的主策劃人之一), 攝影與越野,

喜歡 golang 語言 (商用專案中主要用 postgres + golang )

_

題圖: 2018/12/24 香港黑白攝影展前, 與深圳影友在香港街頭

_

tsingson 寫於中國深圳

小羅號口琴音樂中心, 2019/05/11

相關文章