版本
| 歷史版本 | 日期 | 作者 |
|---|---|---|
| v 1.0.0.0 | 2018-04-04 | 大樹 |
| v 1.0.0.1 | 2018-04-04 | 大樹 |
總體設(shè)計(jì)

核心業(yè)務(wù)架構(gòu)

IP:路由
客戶端在使用長(zhǎng)連接前,會(huì)調(diào)用路由服務(wù),獲取連接層IP,路由層特性:a. 可以按照百分比灰度;b. 未來可以對(duì) uid,deviceId,版本進(jìn)行區(qū)域區(qū)分設(shè)置。
MVP版本可以用Nginx、阿里云負(fù)載均衡方案解決。
接入層
接入層是接受端上發(fā)起的長(zhǎng)連接服務(wù)。技術(shù)方案初步確認(rèn)為:RabbitMq 做推送,MongoDB最為二維坐標(biāo)存儲(chǔ),MQTT作為連接協(xié)議。
MQTT:
協(xié)議選擇:
業(yè)務(wù)場(chǎng)景數(shù)據(jù)量影響。
實(shí)際網(wǎng)絡(luò)通信頻度及其性能影響。
對(duì)硬件影響。
安全性。
MQTT(Message Queuing Telemetry Transport,消息隊(duì)列遙測(cè)傳輸協(xié)議),是一種基于發(fā)布/訂閱(publish/subscribe)模式的“輕量級(jí)”通訊協(xié)議,該協(xié)議構(gòu)建于TCP/IP協(xié)議上,由IBM在1999年發(fā)布。MQTT最大優(yōu)點(diǎn)在于,可以以極少的代碼和有限的帶寬,為連接遠(yuǎn)程設(shè)備提供實(shí)時(shí)可靠的消息服務(wù)。做為一種低開銷、低帶寬占用的即時(shí)通訊協(xié)議,使其在物聯(lián)網(wǎng)、小型設(shè)備、移動(dòng)應(yīng)用等方面有較廣泛的應(yīng)用。
特點(diǎn)包括:
- 使用的發(fā)布/訂閱消息模式,它提供了一對(duì)多消息分發(fā),以實(shí)現(xiàn)與應(yīng)用程序的解耦。
- 對(duì)負(fù)載內(nèi)容屏蔽的消息傳輸機(jī)制。
- 對(duì)傳輸消息有三種服務(wù)質(zhì)量(QoS):
最多一次,這一級(jí)別會(huì)發(fā)生消息丟失或重復(fù),消息發(fā)布依賴于底層TCP/IP網(wǎng)絡(luò)。即:<=1
至多一次,這一級(jí)別會(huì)確保消息到達(dá),但消息可能會(huì)重復(fù)。即:>=1
只有一次,確保消息只有一次到達(dá)。即:=1。在一些要求比較嚴(yán)格的計(jì)費(fèi)系統(tǒng)中,可以使用此級(jí)別 - 數(shù)據(jù)傳輸和協(xié)議交換的最小化(協(xié)議頭部只有2字節(jié)),以減少網(wǎng)絡(luò)流量
- 通知機(jī)制,異常中斷時(shí)通知傳輸雙方
我們這里在實(shí)際應(yīng)用場(chǎng)景司機(jī)需要不斷的上傳位置數(shù)據(jù),所以為了通道性能,可選擇Qos=0
RabbitMQ:
RabbitMQ在架構(gòu)層次上充當(dāng)接入層與推送層。
項(xiàng)目選擇接入層必須滿足以下幾點(diǎn)要求:
1:?jiǎn)螜C(jī)長(zhǎng)連接性能要求高。
2:可靈活擴(kuò)容的集群分布式模式。
3:鏈接必須有足夠的穩(wěn)定性。
4: 具備一定的優(yōu)先策略,讓Priority高的接收者先接到數(shù)據(jù)
RabbitMQ是綜上最優(yōu)選擇,Emq開源但是社區(qū)不夠龐大,而且不支持作為非MQTT得消息隊(duì)列進(jìn)行使用。
Kafka具備高吞吐量高性能的特點(diǎn),但是它是解決實(shí)時(shí)消息處理的隊(duì)列而不適用于M2M的IOT場(chǎng)景。他主要是 broker-Customer模式。
存儲(chǔ)層
MongoDB作為實(shí)時(shí)消息存儲(chǔ)層,相對(duì)redis更適合我們業(yè)務(wù)場(chǎng)景,Redis雖然能滿足mvp設(shè)計(jì)需要,但是它只能解決一部分業(yè)務(wù),必須搭配其他方案進(jìn)行存儲(chǔ)。RDBMS的性能無法滿足高頻插入并進(jìn)行工作隊(duì)列編排任務(wù)。
業(yè)內(nèi)MongoDB已經(jīng)是處理此類業(yè)務(wù)的一個(gè)標(biāo)配。
優(yōu)點(diǎn):
支持二維地理索引數(shù)據(jù)存儲(chǔ)和查詢(GeoJSON)
分布式部署
司機(jī)端基礎(chǔ)服務(wù)
請(qǐng)求鏈接
| 名稱 | 類型 | 備注 |
|---|---|---|
| driverId | Int | 司機(jī)ID |
| 名稱 | 類型 | 備注 |
|---|---|---|
| clientId | string | Mqtt 客戶端ID |
| userName | string | 用戶名 |
| password | string | 密碼 |
| serverUri | string | 鏈接地址 |
| publishedTopic | String | 發(fā)布位置的Topic |
| subscribeOrderTopic | string | 訂單通道 |
| subscribeCalculateTopic | string | 算力訂閱通道 |
| subscribeGeneralTopic | string | 與區(qū)域相關(guān)的通用通知通道 |

發(fā)布位置
| 名稱 | 類型 | 備注 |
|---|---|---|
| driverId | Int | 司機(jī)ID |
| longitude | string | 經(jīng)度(換算成double) |
| latitude | string | 緯度(換算成double) |
| processState | int | 行程狀態(tài),0是位置,1是行程開始(暫定) |
| <em>orderId</em> | int | 訂單ID<行程中,需要傳,其他不需要傳> |
訂閱訂單
| 名稱 | 類型 | 備注 |
|---|---|---|
| orderId | Int | 訂單Id |
| orderNum | string | 訂單編號(hào) |
| passengerId | string | 乘客ID |
| passengerName | string | 乘客名 |
| see | String | 預(yù)估算力 |
| passengerPrice | int | 分(需要端上轉(zhuǎn)換)預(yù)估價(jià)錢 |
訂閱預(yù)約訂單(不放第一迭代)
搶單
/trago/order/initiative
| 名稱 | 類型 | 備注 |
|---|---|---|
| orderId | Int | 訂單Id |
| passengerId | string | 乘客ID |
| driverId | Int | 司機(jī)ID |
- 發(fā)起搶單
- server接到請(qǐng)求,更改訂單狀態(tài)
- 如果訂單狀態(tài)已經(jīng)是搶單中則不修改
- 投遞到搶單隊(duì)列
- 搶單對(duì)列進(jìn)行判斷,一單此單Mailbox已經(jīng)滿了,就直接返回?fù)寙问?/li>
- 沒滿,投遞到隊(duì)列,并排序。
- 隊(duì)列滿了之后,選出最優(yōu)司機(jī)
- 發(fā)送【Topic】告知隊(duì)列中所有司機(jī)搶單結(jié)果。
- 發(fā)送【Topic】告知乘客搶單結(jié)果
備注:第一期迭代建議不做復(fù)雜邏輯直接搶單成功。
搶單結(jié)果推送
| 名稱 | 類型 | 備注 |
|---|---|---|
| orderId | Int | 訂單Id |
| success | int | 0失敗 1成功 |
整體流程

乘客端基礎(chǔ)服務(wù)
立即下單
請(qǐng)求
| 名稱 | 類型 | 備注 |
|---|---|---|
| passengerId | string | 乘客ID |
| passengerName | string | 乘客名 |
| passengerSee | String | 預(yù)估算力 |
| passengerPrice | int | 分(需要端上轉(zhuǎn)換) |
返回
| 名稱 | 類型 | 備注 |
|---|---|---|
| orderId | int | 訂單Id |
輪訓(xùn)訂單
/trago/passenger/query_order
請(qǐng)求
| 名稱 | 類型 | 備注 |
|---|---|---|
| orderId | int | 訂單Id |
| passengerId | int | 乘客ID |
| longitude | string | 經(jīng)度(換算成double) |
| latitude | string | 緯度(換算成double) |
| processState | int | 行程狀態(tài),0是位置,1是行程開始(暫定) |
返回
| 名稱 | 類型 | 備注 |
|---|---|---|
| orderId | int | 訂單Id |
| orderState | int | [具體根據(jù)產(chǎn)品的文檔定狀態(tài),測(cè)試階段,只涉及0,1] |
| <em>driverId</em> | string | 經(jīng)度(換算成double) |
乘客流程

內(nèi)部BROKER設(shè)計(jì)
Toplic規(guī)范
- 反斜線分隔
- 第一位:drivers 、 passengers 、orders 代表角色
- 第二位:區(qū)域 1代表香港
- 第三位:事件 1代表位置 2代表訂單消息,3代表算力消息,4代表通用消息
- 第四位:業(yè)務(wù)標(biāo)記(driverid,passengerid,orderid)
Messag規(guī)范
第一期都用 application/json 內(nèi)容協(xié)議
Broker規(guī)范
- 每一個(gè)Broker 有一個(gè)單獨(dú)的ID
- Broker需要把本Broker訂閱的所有Topic持久化
- Broker要避免不同Broker同時(shí)訂閱同一個(gè)Topic
司機(jī)LBS實(shí)體
| 名稱 | 類型 | 備注 |
|---|---|---|
| clientId | string | Mqtt 客戶端ID |
| driverId | Int | 司機(jī)ID |
| longitude | string | 經(jīng)度(換算成double)最新 |
| latitude | string | 緯度(換算成double)最新 |
| publishedTopic | String | 發(fā)布位置的Topic |
| subscribeOrderTopic | string | 訂閱訂單Topic |
| subscribeCalculateTopic | string | 算力訂閱通道 |
| 其他LBS信息 | string | 后補(bǔ)充 |
乘客LBS實(shí)體
| 名稱 | 類型 | 備注 |
|---|---|---|
| passengerId | int | 乘客Id |
| orderId | Int | 司機(jī)ID |
| longitude | string | 經(jīng)度(換算成double)最新 |
| latitude | string | 緯度(換算成double)最新 |
| orderState | int | 狀態(tài) |
| publisedOrderTopic | string | 訂閱訂單Topic |
| 其他LBS信息 | string | 后補(bǔ)充 |
行程中軌跡
| 名稱 | 類型 | 備注 |
|---|---|---|
| orderId | int | 訂單Id |
| passengerId | int | 乘客ID |
| driverId | int | 司機(jī)ID |
| location | ||
| <em>type </em> | string | line 保持與mongo格式一致 |
| <em>latitude </em> | string | 緯度(換算成double) |
| <em>latitude </em> | string | 緯度(換算成double) |
立即下單發(fā)布
請(qǐng)求
| 名稱 | 類型 | 備注 |
|---|---|---|
| passengerId | int | 乘客Id |
| orderId | Int | 訂單ID |
| longitude | string | 經(jīng)度(換算成double)最新 |
| latitude | string | 緯度(換算成double)最新 |
| orderState | int | 狀態(tài) |
| publisedOrderTopic | string | 訂閱訂單Topic |
| 其他LBS信息 | string | 后補(bǔ)充 |
訂單狀態(tài)同步發(fā)布
請(qǐng)求
| 名稱 | 類型 | 備注 |
|---|---|---|
| passengerId | int | 乘客Id |
| driverId | Int | 司機(jī)ID |
| orderId | Int | 訂單ID |
| orderState | int | 狀態(tài) |
| publisedOrderTopic | string | 訂閱訂單Topic |