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請求的方式輸入到后端服務器,服務器通過對數據庫進行比較查詢,以判斷是否匹配從而決定是否允許用戶執行需要權限操作的功能,如購票、退票、改簽等。
用戶在購票時,首先發送車次查詢信息,在收到服務器反饋的余票足夠的情況下,用戶可以提交購票請求,待服務器在后端決定是否可以售票后再返回相應數據予用戶,此后完成售票功能。