如何設計一個打車系統?

1. 引言

1.1 颱風來襲

深圳上週受颱風 “蘇拉” 影響,從 9 月 1 日 12 時起在全市啓動防颱風和防汛一級應急響應。

對深圳打工人的具體影響爲,當日從下午 4 點起全市實行 “五停”:停工、停業、停市,當日已經停課、晚上 7 點後停運。

由於下午 4 點停市,於是大部分公司都早早下班。其中有趕點下班的,像這樣:

有提前下班的,像這樣:

還有像我們這樣要居家遠程辦公的:

1.2 崩潰打車

下午 4 點左右,公交和地鐵都人滿爲患。

於是快下班(居家辦公)的時候就想着打個車回家,然而打開滴滴之後:

排隊人數 142 位,這個排隊人數和時長,讓我的心一下就拔涼拔涼的。

根據歷史經驗,在雨天打上車的應答時間得往後推半個小時左右。更何況,這還是颱風天氣!

滴滴啊滴滴,你就不能提前準備一下嘛,這個等待時長,會讓你損失很多訂單分成的。

但反過來想,這種緊急預警,也不能完全怪打車平臺,畢竟,車輛調度也是需要一定時間的。在這種大家爭相逃命(bushi 的時候,周圍的車輛估計也不太夠用。

捲起來

等着也是等着,於是就回到公司繼續看技術文章。這時我突然想到,經過這次車輛緊急調度之後,如果我是滴滴的開發工程師,需要怎麼處理這種情況呢?

如果滴滴的面試官在我眼前,他又會怎麼考量候選人的技術深度和產品思維呢?

2. 設計一個 “網約車系統”

面試官:“滴滴打車用過是吧!看你簡歷裏寫道會架構設計是吧,如果讓你設計一個網約車系統,你會從哪些方面考慮呢?”

2.1 需求分析

網約車系統(比如滴滴)的核心功能是把乘客的打車訂單發送給附件的網約車司機,司機接單後,到上車點接送乘客,乘客下車後完成訂單。

其中,司機通過平臺約定的比例抽取分成(70%-80% 不等),乘客可以根據第三方平臺的信用值(比如支付寶)來開通免密支付,在下車後自動支付訂單。用例圖如下:

乘客和司機都有註冊登錄功能,分屬於乘客用戶模塊和司機用戶模塊。網約車系統的另外核心功能是乘客打車,訂單分配,以及司機送單。

2.2 概要設計

網約車系統是互聯網 + 共享資源的一種模式,目的是要把車輛和乘客結合起來,節約已有資源的一種方式,通常是一輛網約車對多個用戶。

所以對於乘客和司機來說,他們和系統的交互關係是不同的。比如一個人一天可能只打一次車,而一個司機一天得拉好幾趟活。

故我們需要開發兩個 APP 應用,分別給乘客和司機打車和接單,架構圖如下:

1)乘客視角

如上所示:乘客在手機 App 註冊成爲用戶後,可以選擇出發地和目的地,進行打車。

打車請求通過負載均衡服務器,經過請求轉發等一系列篩選,然後到達 HTTP 網關集羣,再由網關集羣進行業務校驗,調用相應的微服務。

例如,乘客在手機上獲取個人用戶信息,收藏的地址信息等,可以將請求轉發到用戶系統。需要叫車時,將出發地、目的地、個人位置等信息發送至打車系統

2)司機視角

如上圖所示:司機在手機 App 註冊成爲用戶並開始接單後,打開手機的位置信息,通過 TCP 長連接定時將自己的位置信息發送給平臺,同時也接收平臺發佈的訂單消息。

司機 App 採用 TCP 長連接是因爲要定時發送和接收系統消息,若採用 HTTP 推送:

一方面對實時性有影響,另一方面每次通信都得重新建立一次連接會有失體面(耗費資源)。

司機 App:每 3~5 秒向平臺發送一次當前的位置信息,包括車輛經緯度,車頭朝向等。TCP 服務器集羣相當於網關,只是以 TCP 長連接的方式向 App 提供接入服務,地理位置服務負責管理司機的位置信息。

3)訂單接收

網關集羣充當業務系統的註冊中心,負責安全過濾,業務限流,請求轉發等工作。

業務由一個個獨立部署的網關服務器組成,當請求過多時,可以通過負載均衡服務器將流量壓力分散到不同的網關服務器上。

當用戶打車時,通過負載均衡服務器將請求打到某一個網關服務器上,網關首先會調用訂單系統,爲用戶創建一個打車訂單(訂單狀態爲 “已創建”),並存庫。

然後網關服務器調用打車系統,打車系統將用戶信息、用戶位置、出發地、目的地等數據封裝到一個消息包中,發送到消息隊列(比如 RabbitMQ),等待系統爲用戶訂單分配司機。

4)訂單分配

訂單分配系統作爲消息隊列的消費者,會實時監聽隊列中的訂單。當獲取到新的訂單消息時,訂單分配系統會將訂單狀態修改爲 “訂單分配中”,並存庫。

然後,訂單分配系統將用戶信息、用戶位置、出發地、目的地等信息發送給訂單推送 SDK

接着,訂單推送 SDK 調用地理位置系統,獲取司機的實時位置,再結合用戶的上車點,選擇最合適的司機進行派單,然後把訂單消息發送到消息告警系統。這時,訂單分配系統將訂單狀態修改爲 “司機已接單” 狀態。

訂單消息通過專門的消息告警系統進行推送,通過 TCP 長連接將訂單推送到匹配上的司機手機 App。

5)拒單和搶單

訂單推送 SDK 在分配司機時,會考慮司機當前的訂單是否完成。當分配到最合適的司機時,司機也可以根據自身情況選擇 “拒單”,但是平臺會記錄下來評估司機的接單效率。

打車平臺裏,司機如果拒單太多,就可能在後續的一段時間裏將分配訂單的權重分數降低,影響自身的業績。

訂單分派邏輯也可以修改爲允許附加的司機搶單,具體實現爲:

當訂單創建後,由訂單推送 SDK 將訂單消息推送到一定的地理位置範圍內的司機 App,在範圍內的司機接收到訂單消息後可以搶單,搶單完成後,訂單狀態變爲 “已派單”。

2.3 詳細設計

打車平臺的詳細設計,我們會關注網約車系統的一些核心功能,如:長連接管理、地址算法、體驗優化等。

1)長連接的優勢

除了網頁上常用的 HTTP 短連接請求,比如:百度搜索一下,輸入關鍵詞就發起一個 HTTP 請求,這就是最常用的短連接。

但是大型 APP,尤其是涉及到消息推送的應用(如 QQ、微信、美團等應用),幾乎都會搭建一套完整的 TCP 長連接通道。

一張圖看懂長連接的優勢:

圖片來源:《美團點評移動網絡優化實踐》

通過上圖,我們得出結論。相比短連接,長連接優勢有三:

  1. 連接成功率高

  2. 網絡延時低

  3. 收發消息穩定,不易丟失

2)長連接管理

前面說到了長連接的優勢是實時性高,收發消息穩定,而打車系統裏司機需要定期發送自身的位置信息,並實時接收訂單數據,所以司機 App 採用 TCP 長連接的方式來接入系統。

和 HTTP 無狀態連接不同的是,TCP 長連接是有狀態的連接。所謂無狀態,是指每次用戶請求可以隨意發送到某一臺服務器上,且每臺服務器的返回相同,用戶不關心是哪臺服務器處理的請求。

當然,現在 HTTP2.0 也可以是有狀態的長連接,我們此處默認是 HTTP1.x 的情況。

而 TCP 長連接爲了保證傳輸效率和實時性,服務器和用戶的手機 App 需要保持長連接的狀態,即有狀態的連接。

所以司機 App 每次信息上報或消息推送時,都會通過一個特定的連接通道,司機 App 接收消息和發送消息的連接通道是固定不變的。

因此,司機端的 TCP 長連接需要進行專門管理,處理司機 App 和服務器的連接信息,架構圖如下:

爲了保證每次消息的接收和推送都能找到對應通道,我們需要維護一個司機 App 到 TCP 服務器的映射關係,可以用 Redis 進行保存。

當司機 App 第一次登錄,或者和服務器斷開連接(比如服務器宕機、用戶切換網絡、後臺關閉手機 App 等),需要重連時,司機 App 會通過用戶長連接管理系統重新申請一個服務器連接(可用地址存儲在 Zookeeper 中),TCP 連接服務器後再刷新 Redis 的緩存。

3)地址算法

當乘客打車後,訂單推送 SDK 會結合司機所在地理位置,結合一個地址算法,計算出最適合的司機進行派單。

目前,手機收集地理位置一般是收集經緯度信息。經度範圍是東經 180 到西經 180,緯度範圍是南緯 90 到北緯 90。

我們設定西經爲負,南緯爲負,所以地球上的經度範圍就是 [-180, 180],緯度範圍就是 [-90,90]。如果以本初子午線、赤道爲界,地球可以分成 4 個部分。

根據這個原理,我們可以先將二維的空間經緯度編碼成一個字符串,來唯一標識司機和乘客的位置信息。再通過 Redis 的 GeoHash 算法,來獲取乘客附加的所有司機信息。

GeoHash 算法的原理是將乘客的經緯度換算成地址編碼字符串,表示在某個矩形區域,通過這個算法可以快速找到同一個區域的所有司機

它的實現用到了跳錶數據結構,具體實現爲:

將某個市區的一塊範圍作爲 GeoHash 的 key,這個市區範圍內所有的司機存儲到一個跳錶中,當乘客的地理位置出現在這個市區範圍時,獲取該範圍內所有的司機信息。然後進一步篩選出最近的司機信息,進行派單。

4)體驗優化

1. 距離算法

作爲線上派單,通過距離運算來分配訂單效果一定會比較差,因爲 Redis 計算的是兩點之間的空間距離,但司機必須沿道路行駛過來,在複雜的城市路況下,也許幾十米的空間距離行駛十幾分鍾也未可知。

所以,後續需綜合行駛距離(而非空間距離)、司機車頭朝向以及上車點進行路徑規劃,來計算區域內每個司機到達乘客的距離和時間。

更進一步,如果區域內有多個乘客和司機,就要考慮所有人的等待時間,以此來優化用戶體驗,節省派單時間,提升盈利額。

2. 訂單優先級

如果打車訂單頻繁取消,可根據司機或乘客行爲進行判責。判責後給乘客和司機計算信譽分,並告知用戶信譽分會影響乘客和司機的使用體驗,且關聯到派單的優先級。

司機接單優先級

綜合考慮司機的信譽分,投訴次數,司機的接單數等等,來給不同信譽分的司機分配不同的訂單優先級。

乘客派單優先級

根據乘客的打車時間段,打車距離,上車點等信息,做成用戶畫像,以合理安排司機,或者適當殺熟(bushi。

PS:目前有些不良打車平臺就是這麼做的 🐶  甚至之前爆出某打車平臺,會根據不同的手機系統,進行差異收費。

3. 小結

3.1 網約車平臺發展

目前,全球網約車市場已經達到了數千億美元的規模,主要競爭者包括滴滴、Uber、Grab 等公司。在中國,滴滴作爲最大的網約車平臺已經佔據了絕大部分市場份額。

網約車的核心商業邏輯比較簡單,利益關聯方主要爲平臺、司機、車輛、消費者。

平臺分別對接司機、車輛【非必選項,有很多司機是帶車上崗】和乘客,通過有效供需匹配賺取整個共享經濟鏈省下的錢。

具體表現爲:乘客和司機分別通過網約平臺打車和接單,平臺提供技術支持。乘客爲打車服務付費,平臺從交易金額中抽成(10%-30% 不等)。

據全國網約車監管信息交互平臺統計,截至 2023 年 2 月底,全國共有 303 家網約車平臺公司取得網約車平臺經營許可。

這些平臺一部分是依靠高德打車、百度地圖、美團打車爲代表的網約車聚合平臺;另一部分則是以滴滴出行、花小豬、T3 爲代表的出行平臺

3.2 網約車平臺現狀

隨着出行的解封,網約車平臺重現生機。

但由於部分網約車聚合平臺的准入門檻太低,所以在過去一段時間裏暴露出愈來愈多的問題。如車輛、司機合規率低,遇到安全事故,產生責任糾紛,乘客維權困難等等。

由於其特殊的模式,導致其與網約車運營商存在責任邊界問題,一直遊離在法律邊緣。

但隨着網約車聚合平臺的監管不斷落地,全國各地都出行了一定的監管條例。

比如某打車平臺要求車輛將司機和乘客的溝通記錄留檔,除了司機與乘客的在線溝通記錄必須保存以外,還需要一個語音電話或車載錄音轉換,留存一段時間備查。

有了這些人性化的監管條例和技術的不斷創新,網約車平臺或許會在未來的一段時間內,繼續蓬勃發展。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/XMKbpLKtGn-FDJMQrqkz8w