工程实践项目是实现一个相似知乎的问答社区系统(后端)html
基本要求:前端
进阶要求:git
软件架构风格是描述某一特定应用领域中系统组织方式的惯用模式,经常使用的软件架构风格有以下几类:github
管道-过滤器golang
客户-服务器redis
P2P算法
发布-订阅数据库
CRUDjson
层次化后端
本项目是一个典型的 C/S (客户-服务器)架构模式,服务器负责全部数据的存储与组织,客户端经过 HTTP 访问服务器,请求相应的数据并向用户展现出来,同时接收用户输入,与用户作交互。
API 定义了客户端与服务端数据交互的基本格式,包括客户端以什么样的格式请求,请求参数,服务端以什么样的格式响应,正确响应与错误响应的不一样内容等。
本项目采用 RestfulAPI 风格的接口设计,具体篇幅太大,就不展开叙述了,仅列举一下部分 API 的简要说明:
接口名称 | 接口地址 | 请求方式 | 请求参数 | 响应信息 | 备注 |
---|---|---|---|---|---|
用户注册 | /user/register | POST | 用户名,密码,密码确认 | 用户基本信息 | |
用户登陆 | /user/login | POST | 用户名,密码 | 用户token,基本信息 | 用户token保存用户的登陆状态,保存到本地,请求其它接口的时候带上。 |
我的信息 | /user/me | POST | 用户token | 用户完整信息 | |
发布问题 | /questions | POST | 用户token,问题标题,可选的问题详细描述 | 问题基本信息 | 已登陆用户才可发布问题,未携带token会拒绝服务 |
查看问题 | /questions/{qid} | GET | 可选的用户token | 问题详细信息 | |
修改问题 | /questions/{qid} | PUT | 用户token,问题标题,可选的问题详细描述 | 问题基本信息 | 问题所属用户才可修改问题 |
删除问题 | /questions/{qid} | DELETE | 用户token | ok | 问题所属用户才可删除问题 |
首页推荐列表 | /questions | GET | limit请求数量,offset位置偏移 | 问题列表,每一个问题包含一个一段时间内的热门回答信息 | |
问题热榜列表 | /hot_questions | GET | limit请求数量,offset位置偏移 | 问题列表 | |
回答问题 | /questions/{qid}/answers | POST | 用户token,回答内容 | 回答基本信息 | 已登陆用户才可回答问题,未携带token会拒绝服务 |
查看回答 | /questions/{qid}/answers/{aid} | GET | 可选的用户token | 回答详细信息 | |
修改回答 | /questions/{qid}/answers/{aid} | PUT | 用户token,回答内容 | 回答基本信息 | 问题所属用户才可修改回答 |
删除回答 | /questions/{qid}/answers/{aid} | DELETE | 用户token | ok | 问题所属用户才可删除回答 |
回答列表 | /questions/{qid}/answers | GET | limit请求数量,offset位置偏移,type排序方式 | 回答列表 |
软件架构模型是经过一组关键视图来描述的,同一个软件架构,因为选取的视角(Perspective)和抽象层次不一样能够获得不一样的视图,这样一组关键视图搭配起来能够完整地描述一个逻辑自洽的软件架构模型。通常来讲,咱们经常使用的几种视图有分解视图、依赖视图、泛化视图、执行视图、实现视图、部署视图和工做任务分配视图。
对系统的经常使用分解方法有面向功能分解,面向数据分解,面向特征分解,面向并发分解等,根据本项目的特色,比较适合面向功能的分解方法,分解视图以下:
依赖视图展示了软件模块之间的依赖关系。本项目最前端使用 Nginx 部署应用,数据来源于后端的 MySQL 和 Redis 数据库,同时在应用层内各模块间也存在依赖关系,据此能够画出项目的依赖视图:
执行视图展现了系统运行时的时序结构特色,好比流程图、时序图等。执行实体能够最终分解到软件的基本元素和软件的基本结构,于是与软件代码具备比较直接的映射关系。
本项目是一个后端项目,根据客户端的不一样请求执行不一样的操做,从总体上来讲,每一次操做均可以用以下时序图归纳:
源代码的目录文件结构及其与软件架构的映射关系说明以下:
├── api API控制层,负责处理请求 │ ├── v1 具体API版本,增量发布 ├── cache redis 缓存相关 ├── conf 项目的静态配置 ├── middleware 中间件 ├── model 数据库模型以及相关操做 ├── routes 路由配置 ├── serializer 将实体映射成不一样的viewmodel,以及经常使用的响应信息 ├── service 服务层,将比较复杂的业务从api层分离出来 ├── utils 经常使用工具 | main.go 应用入口
项目前期采用单点部署,各组件运行于一台服务器上,视图以下:
后期可升级为分布式结构来提升可靠性和提供更大的吞吐量:
工做分配视图将系统分解成可独立完成的工做任务,以便分配给各项目团队和成员,本项目是一个面向 API 服务的程序,最终目标是实现一系列功能完备的接口,因此最好的分解方法就是按照接口分解,每一个成员负责几个接口实现:
本项目采用 ORM(对象关系映射)来将项目的数据结构映射到数据库里,由框架负责管理数据库具体操做,核心数据结构以下:
type User struct { gorm.Model Username string `gorm:"unique;not null;"` // 用户名 Password string `gorm:"not null;"` // 密码 UserProfile UserProfile `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"` // 关联用户信息 Questions []Question `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"` // 关联问题信息 Answers []Answer `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"` // 关联回答信息 } type UserProfile struct { gorm.Model UserID uint Nickname string `gorm:"default:null"` // 昵称 Email string `gorm:"unique;default:null;"` // 邮箱 Avatar string `gorm:"default:null;"` // 头像 Status int `gorm:"not null;default:0;"` // 状态 Description string `gorm:"default:null"` // 我的描述 }
type Question struct { gorm.Model UserID uint `gorm:"not null;"` // 问题所属用户Id Title string `gorm:"not null;"` // 标题 Content string `gorm:"type:text"` // 内容 Answers []Answer `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"` // 关联回答信息 }
type Answer struct { gorm.Model UserID uint `gorm:"not null;"` // 回答所属用户Id QuestionID uint `gorm:"not null;"` // 回答所属问题Id Content string `gorm:"type:text;not null;"` // 内容 }
项目使用 Docker 打包部署,能够运行于任何 Linux 服务器上。
项目使用 Golang 开发,用到的组件主要有:
项目概念原型的核心工做机制描述以下: