1. 项目简介
本课题参考12306站点进行售票系统建模设计,实现一个类12306售票系统,尽可能接近覆盖真实线上系统,实现的功能有但不限于:
- 用户信息注册
- 查询余票:根据时间,车次,站点区间,座次(一等座,二等座,硬卧,硬座等)查询余票
- 售票:支持一次购买同一车次的多张车票(多人),支持订单30分钟内锁定,超时释放
- 退票:支持一个用户帐户下的批量退票
- 改签:同一用户一张车票只能改签一次
2. 软件架构
该项目面向的是多用户,为方便调试后端服务程序,以B/S架构举例说明。
B/S(Browser/Server)架构,也即浏览器/服务器架构,在该架构模式下,开发Web应用优势明显,前后端分离的实现也比较简单。应用程序的业务逻辑实现和数据处理全部由服务器端提供,这些数据只需要在前端通过浏览器显示即可,轻量快捷。
该架构方式下,浏览器通过发送HTTP请求到Web服务器后,后端程序对这些请求进行处理,包括但不限于与数据库交互,再通过返回HTML页面到浏览器中,从而能实现前后端的通信。
3. 接口API
API定义了客户端与服务器端数据交互的规范格式。在本项目中,将采用RestfulAPI接口设计风格,列举以下几个API为例:
1. 用户注册
用户首次使用本软件时需要进行的操作。用户通过POST请求提交注册需要的JSON数据,即username、password,接口地址为/user/register;
请求数据:
1 { 2 "username":"", 3 "password":"" 4 }
返回数据:
1 { 2 "code":"", // 消息代码 3 "msg":"", // 返回的信息,说明成功与否 4 "data":"" 5 }
2. 用户登录
通过登录,用户方可使用本软件,且我们可以根据用户存储相对于的资料等信息,采用POST请求,接口地址为user/login:
1 { 2 "username":"", 3 "password":"" 4 }
后端逻辑需要比较用户post的请求数据与数据库中保持的数据是否一直后,再返回响应的登录信息,包含失败及成功,若成功,则反应对应的token以记录登录状态:
1 { 2 "code":"", 3 "msg":"", 4 "data":{ 5 "token":"" 6 } 7 }
3. 余票查询
用户可以在使用时,提交相应的起点站、终点站、时间以及类型等相关信息来查询相对应的余票信息,以便得到相应结果,采用的请求方式为POST,接口地址为search/remainder:
1 { 2 "start_city":"", 3 "end_city":"", 4 "date":"", 5 "type":"" 6 }
返回的余票包含的信息可能但不并局限于以下JSON:
1 { 2 "code":"", 3 "msg":"", 4 "data":{ 5 "list": [ 6 { 7 "train_number":"", // 列次 字符串 8 "start_station":"", 9 "end_station":"", 10 "start_time":"", // 出发时间 11 "arrival_time":"", // 达到时间 12 "start_station_type":"", //起始站类型, 是否始发站还是过站, 0, 1 13 "end_station_type":"", //到达站类型, 是否是过站还是终点站, 1,2 14 "train_type":"", // 列车类型, 15 "business_seats_number": , // 商务座余数 16 "first_seats_number": , // 一等座 17 "second_seats_number": , // 二等座 18 "no_seats_number": , //无座 19 "hard_seats_number": , // 硬座数量 20 "hard_berth_number": ,// 硬卧 21 "soft_berth_number": ,// 软卧 22 "senior_soft_berth_number": , // 高软 23 } 24 ] 25 } 26 }
4. 视图分析
1. 分解视图
分解视图所展示的一般是一个比较明了的分解结构特点,它是描述软件架构模型的关键视图,体现的是系统结构的特点,往往由不同层级的软件模块形成层次化的结构。根据功能划分,可以得到该项目的分解视图如下:
2. 依赖视图
依赖视图所展示的是软件各个模块之间的依赖关系。在本项目中,我们在后端采用MySQL数据库存储一些不常用的数据,将高频查询的数据存储在Redis缓存中;同时,各个模块之间也存在着一些依赖关系,如订单系统应依赖于用户信息系统等。下面给出系统整体的依赖视图:
3. 执行视图
执行视图所展示的是系统运行时的时序结构特点,在本项目中,执行视图如下所示:
4. 实现视图
实现视图展示的是源代码的目录文件结构信息,如下所示:
1 ├── controllers 控制层,处理请求相关 2 ├── middlerwares 中间件 3 ├── models 数据模型相关 4 ├── routers 路由配置相关 5 ├── serializers 实体映射相关 6 ├── utils 常用工具类 7 ├── conf 配置文件 8 ├ ├── mysql 9 ├ ├── redis 10 ├ ├── config.ini
5. 部署视图
部署视图是将执行实体和计算机资源建立映射关系。部署视图有助于软件开发人员分析一个软件的质量属性。在本项目中,部署视图如下所示:
6. 工作分配视图
工作分配视图将系统分解成可独立完成的工作任务,以便分配给各项目团队和成员。它有利于团队成员跟踪工作任务的浸塑,也有利于合理地分配资源。该项目的工作分配视图如下:
5. 数据库设计
数据库采用目前开发最经常使用的关系型数据库MySQL,在此基础上使用Redis作为缓存,提高查询的效率。
由之前分析,可将数据库分为以下几个表项:
1. 公共部分
本项目在构建数据库时,使用Gorm模型建立了数据库,其包含有公共部分如下:
编号 | 字段 | 数据类型 | 解释 |
1 | id | uint | ID |
2 | created_at | time.Time | 创建时间 |
3 | updated_at | time.Time | 更新时间 |
4 | deleted_at | time.Time | 删除时间 |
2. 用户 User
编号 | 列名 | 数据类型 | 解释 |
1 | UID | string | 用户ID |
2 | UserName | string | 用户名 |
3 | Password | string | 密码 |
4 | User | Passenger | 乘客 |
5 | RegularPassengers | Passenger | 常用乘车人 |
6 | Orders | Order | 订单 |
3. 乘客 Passenger
编号 | 字段 | 数据类型 | 解释 |
1 | Name | string | 姓名 |
2 | CertificateType | uint | 证件类型 |
3 | Sex | bool | 性别 |
4 | Birthday | data | 出生日期 |
5 | Country | uint | 国家 |
6 | CertificateDeadline | data | 证件有效期截至日期 |
7 | Certificate | string | 证件号码 |
8 | PassengerType | uint | 旅客类型 |
9 | MobilePhone | string | 手机号码 |
10 | string | 电子邮箱 | |
11 | CheckStatus | uint | 审核状态 |
12 | UserStatus | uint | 用户状态 |
4. 列车 Train
编号 | 字段 | 数据类型 | 解释 |
1 | TrainNo | string | 列车代号 |
2 | TrainType | uint | 列车类型 |
3 | Seats | Seat | 座位 |
5. 座位 Seat
编号 | 字段 | 数据类型 | 解释 |
1 | SeatNo | string | 座位编号 |
2 | CarNumber | uint | 车厢编号 |
3 | Price | Train | 列车 |
4 | price | float | 票价 |
5 | SeatType | uint | 座位类型 |
6 | SeatStatus | uint | 座位状态 |
6. 班次 Schedule
编号 | 字段 | 数据类型 | 解释 |
1 | train | Train | 列车 |
2 | start_station | Station | 终点站 |
3 | end_station | Sation | 起点站 |
4 | start_time | time | 出发时间 |
5 | end_time | time | 到达时间 |
6 | stop | Stop | 经停站 |
7 | duration | uint | 沿途时间 |
7. 车站 Station
编号 | 字段 | 数据类型 | 解释 |
1 | station_name | string | 车站名 |
2 | city | string | 城市名 |
3 | city_pinyin | string | 拼音 |
4 | first_pinyin | string | 首字母 |
5 | city_code | string | 城市代码 |
6 | station_code | string | 车站代码 |
8. 经停站 Stop
编号 | 字段 | 数据类型 | 解释 |
1 | schedule | Schedule | 班次 |
2 | serial_number | uint | 站序 |
3 | start_station | Station | 起始站 |
4 | end_station | Station | 终止站 |
5 | start_time | time.Time | 发车时间 |
6 | end_time | time.Time | 到达时间 |
7 | duration | uint | 沿途时间 |
9. 订单 Order
编号 | 字段 | 数据类型 | 解释 |
1 | trade_no | string | 交易编号 |
2 | passenger | Passenger | 乘客 |
3 | user | User | 用户 |
4 | schedule | Schedule | 班次 |
5 | status | uint | 订单状态 |
6 | seat | Seat | 座位 |
10. E-R图
在以上基础上,我们可以构建出数据库的E-R图如下所示:
6. 系统运行环境及技术选型
1. 系统运行环境
本项目是一个纯粹的后端项目,故而其系统运行环境为Ubuntu,我们将在Docker上对其进行部署,并采用wrk作为性能测试工具对其进行压力检测。
2. 技术选型
在本项目开发过程中,我们使用的开发框架为Go-Gin框架,其自带有参数检验功能可大大提高软件的健壮性;采用MySQL+Redis的组合,可以降低查询时间,保证系统地响应效率;开发工具主要为VS Code + Goland。
7. 核心工作机制
以用户登录以及购票为例,整个概念模型的工作机制大致如下:
用户在前端提供用户名和密码,以POST请求的方式输入到后端服务器,服务器通过对数据库进行比较查询,以判断是否匹配从而决定是否允许用户执行需要权限操作的功能,如购票、退票、改签等。
用户在购票时,首先发送车次查询信息,在收到服务器反馈的余票足够的情况下,用户可以提交购票请求,待服务器在后端决定是否可以售票后再返回相应数据予用户,此后完成售票功能。