架构训练营模块三作业
前言
本文是学生管理系统的架构说明文档,旨在整体上说明系统整体设计、部署架构
词汇表
Gin: go 语言开源 web 框架
Json: 一种轻量级序列化方案
1. 业务背景
随着学校的规模的不断扩大,学生数量的增加,需要处理的信息也日趋增大。不仅花费大量的教师资源,处理效率也十分低下。
为提高学生管理的管理水平,优化资源,尽可能降低管理成本成为学生管理的新课题,学生管理系统是从学生管理现状出发,根据学生管理的新要求进行开发设计的,它需要解决学生信息管理数据信息量大修改不方便,对一系列数据进行分析时花费时间长等问题,帮助学生管理人员有效管理学生信息。
因此学生信息管理系统可以通过系统规范化地管理、科学性统计和快速查询、修改、增加、删除等,提高信息的准确度以及日常管理的工作效率。
本系统主要是应用于学生各类信息的管理,总体任务是实现学生信息关系的系统化、规范化、自动化,其主要任务是统计学生各类信息进行日常管理,如查询、修改、增加、删除、以及学生选课、成绩的查询等功能设计的管理系统。
2. 约束和限制
1.必须在 3 个月内完成
2.服务器数量不超过 4 台,数据库服务器不超过 3 台
3.数据存储至少备份一份
4.以 Go 语言为开发语言
3. 总体架构
为学生提供选课、上传笔记、考试等功能
为教师提供创建考试、阅卷、录分等功能
为教务提供管理账号、增删数据、排课等功能
系统分为 3 个子系统,分别为权限子系统、课程子系统、学生子系统,子系统主要提供功能及调用关系如下图:
3.1 架构分析
3.1.1 高可用
对于校内系统,短时间的宕机,保证有限时间内可恢复即可,但数据若出现丢失,恢复时间则不可控或无法实现,所以存储至少做到数据备份,达到高可用级别;计算高可用则不做特殊要求,使用前置负载均衡在业务服务器宕机时能实现手动切换即可
3.1.2 高性能
校内系统,日常用户数量以及使用频率并不会特别高,对高性能无特殊要求
3.1.3 可扩展性
校内系统,业务需求明确,日后改动性小,对可扩展性无特殊要求
3.2 总体架构
1)前置 nginx 作为负载均衡,对外暴露整体服务
2)采用按业务功能模块化方案,分为 3 个子系统,分别是学生子系统、课程子系统、权限子系统,子系统之间直接相互调用,不经过 nginx
3)数据存储使用 mysql,mysql 使用 InnoDB,读写使用主实例,备实例在主实例宕机时手动切换
4. 详细设计
4.1 核心功能
4.1.1 权限验证
权限验证使用客户端请求 Header Authorization 携带 jwt 方案(RS256 加密),服务端结合 Nginx auth_request 模块辅助实现,具体流程如下:
用户请求到达 nginx 时,需要权限验证接口若无 jwt 则返回 401 响应,若有则由 nginx 本地缓存验证,缓存有效则跳转至第 4 步,无效则跳转第 5 步,若缓存 miss 则进行下一步
nginx 发起子请求,将当前 url 与 jwt 传递给权限子系统
权限子系统进行权限验证以及 jwt 中公共字段验证后,若无权限,nginx 做一个 30s 的短效 LRU cache 并跳转至第 5 步;若有权限,则存储进一个 10min 的 LRU cache
nginx 代理至处理业务功能的相应子系统(权限子系统、学生子系统、课程子系统)请求(业务子系统仅通过公钥进行 jwt 验证即可,不进行具体权限验证)并向客户端返回业务数据,至此结束
nginx 根据权限验证失败结果返回 403
补充:由于 jwt 一经发放服务端无法令其失效,故新增权限后,用户需退出重新登录刷新权限,否则至多在 10min 后获得刷新
4.2 关键设计
[必选,描述系统的一些关键设计点是如何实现和取舍的]
[样例(如果你有兴趣,可以对比一下 kafka 的文档:Kafka design):
1)消息发送可靠性
业务服务器中嵌入消息队列系统提供的 SDK,SDK 支持轮询发送消息,当某个分组的主服务器无法发送消息时,SDK 挑选下一个分组主服务器重发消息,依次尝试所有主服务器直到发送成功;如果全部主服务器都无法发送,SDK 可以缓存消息,也可以直接丢弃消息,具体策略可以在启动 SDK 的时候通过配置指定。
如果 SDK 缓存了一些消息未发送,此时恰好业务服务器又重启,则所有缓存的消息将永久丢失,这种情况 SDK 不做处理,业务方需要针对某些非常关键的消息自己实现永久存储的功能。
2)消息存储可靠性
消息存储在 MySQL 中,每个分组有一主一备两台 MySQL 服务器,MySQL 服务器之间复制消息以保证消息存储高可用。如果主备间出现复制延迟,恰好此时 MySQL 主服务器宕机导致数据无法恢复,则部分消息会永久丢失,这种情况不做针对性设计,DBA 需要对主备间的复制延迟进行监控,当复制延迟超过 30 秒的时候需要及时告警并进行处理。
3)消息如何存储
每个消息队列对应一个 MySQL 表,消息队列名就是表名,表结构设计为……(此处请自行补充)
]
[技巧:常见的关键设计点包括高性能、高可用、可扩展、安全等]
1)存储高可用
mysql 备库通过订阅主库 binlog,实现热备,当主节点故障时,主动切换业务服务器中数据库地址
2)计算高性能
将整体系统垂直拆分为三个子系统,负责不同业务功能,不需使用影响性能的分布式锁、分布式事务等功能
使用 jwt 方案,在客户端中存储用户部分信息,减少反复查询用户信息性能消耗
3)安全
使用非对称加密的 jwt,降低密钥存放多处子系统引起的安全风险
子系统端口不对外开放
4.3 设计规范
[必选,描述 Role 和 Relation 相关的开发框架、连接协议、数据包格式等]
[样例:
1)消息队列服务器使用 Spring Boot + Netty 开发
2)MySQL 使用 Innodb 存储引擎
3)TCP 包的结构设计……(此处省略,请自行补充)
]
[技巧:如果某个规范涉及内容比较多,请独立章节描述,例如数据包格式定义]
1)系统使用 Go + Gin 开发
2)子系统之间调用使用 http+json,不通过 Nginx 代理
3)Mysql 使用 Innodb 引擎,子系统独立数据库,主键原则上使用自增 bigint 类型
5. 质量设计
5.1 请求跟踪
封装 log 方法,在客户端生成随机 ID 存放在请求头,log 方法每次均打印出请求 ID,用于后期排查问题跟踪子系统之间日志请求,增加系统可观测性
6. 演进规划
版权声明: 本文为 InfoQ 作者【TIEDPAG】的原创文章。
原文链接:【http://xie.infoq.cn/article/4f71264a49fe05e05b60a0ce3】。未经作者许可,禁止转载。
评论