go-ums 从需求分析到设计实现( v0.1.0 )

项目源码地址 github.com/tsingson/go…html

文字有点长, 尽可能写得简单明了前端

文章归纳内容都写上了, 因为文档进一步细化并补充更多需求后, 须要拆分为设计文档/接口文档/测试文档/评审文档.....等等, 这里再也不持续更新.java

后续补充变动, 请访问 项目源码地址mysql

x. update 更新 ( 2019/11/05)

因为带一个朋友学习 golang 开发, 因此, 这个项目正在重写, 基本上, 本文提到的内容会所有变动, 主要变动以下:react

  1. 变动为 step by step 的方式, 全新写一个能够商用的 ums 用户管理子系统
  2. 后台存储变动为默认支持 bbolt / postgres , 并提供接口, 对接 mysql ....
  3. 带后台管理 web 界面( 用 react ), 提供 gRPC ( probuf / flatbuffers 两种) 与 RESTfull 管理/集成接口
  4. 支持 AAA 分布式部分
  5. 附带完整测试代码

因为是 step by step 给朋友演示开发过程, 因此, 大约分红三个步骤开发:linux

  1. 建模, 在 /model 下完成存储模型的基本处理, 包括用户模型, 用户状态与用户权限模型,与相关存储
  2. 前端接口, 以及前端 web 实现, 前端模拟用户端( http 与 TCP 两种模式), 后端管理界面
  3. 实现分布式 (附带压力测试)

架构变动以下:android

具体变动, 见 项目源码地址git

0. go-ums 是什么

go-ums 开发目标是一个开源项目, 核心由 golang 开发, 提供用户管理(user-management-subsystem) / AAA 鉴权/受权/计账 / 多业务会话共享与管理等, 以支持分布式部署及云部署为主要目标github

这是一个从零开始的小项目, 持续渐进golang

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.2.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 用户注册

业务流程描述: 客户端 ----------> 服务端, 进行用户注册, 发送注册数据, 由服务器端返回注册成功(获取用户ID ) 或失败信息

----> 输入:
  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 接口设计

大白话:

接口就是两个网元之间, 进行交互/通信的网络协议/控制通讯命令(信令)/以约定格式传输相关数据(数据封装)的简称

例如 web 浏览器与 web 服务器这两个网元之间, 通常采用 HTTP 协议, 信令是 GET / POST / PUT / PATCH / DELETE ...., 数据封装一般是以 MIME 来指定, 好比下面用到的 "application/json; charset=utf-8"

设计实现如下接口

  1. RESTful 接口 ( 描述省略, 见代码)
  2. gRPC ( protobuf ) 接口 ( 略 )
  3. gRPC ( flatbuffers ) 接口( 对接 android java SDK , 详细说明略)
  4. websocket 接口 ( 略 )
  5. TCP 接口 ( 略 )

接口设计, 事实是描述一下业务数据的输入/输出, 以及须要对接的两端业务主体的业务过程(业务上如何进行交流与处理) 这里简化掉了, 并细化得很"编程化"了

2.3.2.1 RESTful 接口设计

关于 RESTful 接口, 相关推荐规范, 请自行查询

这里先简要说明一下:

RESTful 一般是 HTTP + json 实现的接口, 其中

  1. 相似 /api/v1/account 这样的 URI 就是一个接口, 其中 /api/v1 前缀只是辅助管理

    在下面咱们示例实现的用户注册接口, 能够定义为 /api/v1/register 或者 /xxx/yyyy 这样你喜欢的方式

  2. HTTP 的 method 就是操做方式, 例如:

    • GET:读取(Read)
    • POST:新建(Create)
    • PUT:更新(Update)
    • PATCH:更新(Update),一般是部分更新
    • DELETE:删除(Delete)
  3. 数据编码(序列化/反序列化) 是 "application/json; charset=utf-8” 标的 JSON 格式

  4. 少许操做关联数据, 能够在 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 测试用例以下

  1. 检查 email 无重复, 操做成功
  2. 检查 email 有重复, 操做失败
  3. 异常, 主要关注两个, 保存失败或异常, 通信异常中断 (详细说明, 省略)

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 实现

见 [github.com/tsingson/go…]

(说明省略)

4.2.2 接口设计的实现

见 [github.com/tsingson/go…]

(说明省略)

4.2.3 业务逻辑实现

github.com/tsingson/go…

(说明省略)

4.2.4 UT ( Unit Test) 单元测试

测试用例以下

  1. 检查 email 无重复, 操做成功
  2. 检查 email 有重复, 操做失败
  3. 其余异常( 略)

见 /pkg/service 下测试代码

4.3 LIT ( local integration test) 网元集成测试

见 /pkg/web 下各测试代码

4.4 SIT ( system intergration test ) 系统集成测试

见 /cmd/cli 下代码

稍后补充..........

4.5 编译/部署/运维

参见 go-ums v0.1.0 测试/编译/运行

稍后补充.............

5. 性能测试/部署测试/ trial 验证

省略 ...

6. 附注/参考

6.1 接口设计相关参考

_

_

关于我

网名 tsingson (三明智, 江湖人称3爷)

原 ustarcom IPTV/OTT 事业部播控产品线技术架构湿/解决方案工程湿角色(8年), 自由职业者,

喜欢音乐(口琴,是第三/四/五届广东国际口琴嘉年华的主策划人之一), 摄影与越野,

喜欢 golang 语言 (商用项目中主要用 postgres + golang )

_

题图: 2018/12/24 香港黑白摄影展前, 与深圳影友在香港街头

_

tsingson 写于中国深圳

小罗号口琴音乐中心, 2019/05/11

相关文章
相关标签/搜索