滴滴出行平臺業務架構演進

**桔妹導讀:**爲了滿足不同用戶在價格、體驗等方面的差異化訴求,滴滴提供了越來越豐富的品類,這些品類大體流程是類似的,在一些細節體驗上有差異,一套架構如何兼顧隔離和複用,同時支持這些品類,且看滴滴服務端技術的灣流平臺怎麼做。

**1. **

項目背景

在滴滴打車業務中,服務端 API 向上接收端上請求並組裝返回,向下串接訂單、計價、收銀等業務中臺的各個系統,完成整個打車流程,灣流平臺項目期望在服務端 API 層打造一個「出行中臺」。在已有業務中臺的情況下,爲什麼還要在業務「前臺」API 層打造一個「出行中臺」,這和出行業務的流量模式是分不開的。

****1.1 ****流量模式

1.1.1 傳統和業界常規的 “錐狀” 流量分配模式

傳統的典型中臺架構是 “大中臺小前臺”,造就這種架構的原因與流量分配模式相關。以電商領域爲例,中臺抽象了電商相關的業務實體如:訂單、收銀臺、商品等,而不同業務線之間的流量入口是分開的,不同 BU 間能夠以小前臺的方式閉環實現。這種“大中臺小前臺” 的架構,可以支持快速構建原型產品進行試錯探索,中臺提供電商標準的基礎能力,前臺各自閉合實現 B2C、C2C 等業務,而業務間互不影響。

流量分配模式表現爲:多業務(或品類)開放的前臺流量接入,轉化至統一有限的業務中臺,最終落至基礎平臺。

1.1.2 網約車獨特的 “菱形” 流量分配模式

滴滴網約車業務核心是打車,爲了滿足不同用戶的需求(定價、應答率、體驗等),通過品類區分提供差異化服務能力,從最初的出租車、專車、快車延展到了如今幾十個品類。而入口始終圍繞在司乘兩端、開放平臺。

流量分配模式表現爲:多品類由統一的端接入流量入口(API)並完成各品類的主要業務邏輯處理,再交由統一的業務中臺,最終落至基礎平臺

網約車的「菱形」流量分配模式註定:服務端 API 一方面需要支持一些跨 BU 的平臺級需求,如:春節服務費、疫情停開服等;另一方面也要支持不同 BU 間的差異化需求,如出租車使用打表計價不用線上計價等。

隨着品類越來越豐富,這些差異邏輯也越來越多,導致系統越來越臃腫,複雜度越來越高,迭代效率下降。所以需要將服務端 API 通用的部分下沉,並且開放差異定製的機制,同時兼顧隔離和複用,灣流平臺項目應運而生。

1.2 服務端 API 職責定位

在開始前,需要先明確服務端 API 的核心職責。


****◎ 核心職責

****◎ 終極問題

1.3 灣流平臺演進


在過去幾年時間裏,基於上述背景我們一直在不斷探索,以下簡單介紹下灣流平臺項目前兩個版本迭代的情況。

1.3.1 灣流平臺 1.0(2017-2018)

1.0 階段主要解決的是快速增加新品類和不同 BU 間代碼隔離的問題,使用配置化插件化解決。配置化主要是統一了上下游產品描述協議,形成產品描述 N 元組,並抽象一套通用的 N 元組到功能的映射規則;插件化利用插件包隔離不同 BU 間的代碼,運行時插件選擇器根據流量特徵分發到對應插件包。

****◎ 遺留問題

  1. 配置化依賴於功能抽象,需要一套統一的抽象方法

  2. 插件化依賴於穩固的流程,以及清晰的功能邊界。按差異開放插件點會導致插件定義不明確、粒度無法把控、插入點不穩定等問題,長期維護困難。

1.3.2 灣流平臺 2.0(2018)

2.0 一方面要解決 1.0 遺留的功能抽象、流程固化等問題,一方面還要面臨複雜度越來越高的服務端 api 系統。爲此我們借鑑了 DDD 的思路,開啓了灣流平臺 2.0 的改造。

****◎ 遺留問題

  1. 未做系統性的框架約束,迭代容易破壞原有結構

  2. 側重於分治和抽象,未同步考慮品類間隔離問題

**2. **

灣流平臺 3.0 詳細方案

2.1 總體思路

前面也提到,灣流平臺核心要解決隔離和複用的問題。3.0 整體思路是把服務端 API 的業務邏輯分爲兩層,一層是用於串接狀態流轉的流程層,一層是用於完成各個垂類功能的能力組件層。流程層既包含從預估、發單到完單的宏觀打車流程,也包含每個接口的執行流程。宏觀的打車流程基本品類間是統一的,與端的交互協議也是統一的;每個接口執行流程不同品類間由於業務形態差異,會有部分不一致。我們把接口的執行流程做環節抽象,形成一個個的 step,沉澱一套接口標準通用的執行 step,品類可以根據各自的差異,重載 step。

能力組件抽象聚合了一些垂直的功能,組件內部按照策略模式,根據不同的品類場景使用不同的策略完成組件行爲。如播單組件,提供了延遲播單、實時播單、輪次播單等模式,專車預約採用延遲播單,這種是在播單組件中通過配置實現。如果一些有特別大的差異,比如出租車要實現一個全新的播單模式並且不具備通用性,也可以由出租車實現這個新的模式,通過插件的形式掛載進來。

經過這樣改造之後,同時配套誕生了一些平臺產品,輔助提高開發效率。如流程編排中心,可以根據不同的品類場景,對接口流程環節進行編排;特徵管理平臺,統一管控業務特徵,保持業務描述統一;品類配置中心,從品類場景視角,配置不同能力的行爲模式,快速上線新品類場景。

****2.2 ****框架介紹

爲了實現總體思路,我們開發了一套代碼運行框架,命名爲 DuKang,何以解憂,唯有 DuKang!依託 DuKang 框架,解決我們隔離和複用的難題。

DuKang 框架,針對每個接口,按照下圖流程執行調度,涉及 InputSource、Transport、TransportFactor、StepRuntime、Step、Ability 等核心概念。

其中核心的要點是,Transport 作爲流程承載器,提供了一個 base 的基礎流程實現,不同品類可繼承 BaseTransport,然後可以針對差異的流程環節 step 進行重載,但整個流程是由流程驅動引擎調度,各品類保持一致。ability 是能力組件,組件內部提供了一組通用的 mode,不同品類場景通過配置化方式複用這些 mode,同時也向業務開放了定製 mode 的機制,業務可以通過使用 biz 定製自己獨有的 mode,掛載到 ability 下,實現差異化功能。

服務端 API 語言棧以 php 和 golang 爲主,其中老的服務主要是用 php 寫的,整體逐步在往 golang 上遷移,新服務都是直接採用的 golang。Dukang 框架同時支持了 php 和 golang 兩個版本,下面以 php 版本,成單接口爲例,展示 dukang 框架的運行過程:

//配置文件,管理流程環節,以及提供給不同品類註冊各自transport
{
  "name": "ConfirmOrder,
  "transports": {
    "default": "\\DuKang\\Transport\\ConfirmOrderaseTransport",
    "express": "\\DuKang\\Express\\Transport\\ConfirmOrderExpressTransport",
    "luxury": "\\DuKang\\Luxury\\Transport\\ConfirmOrderLuxuryTransport",
    "taxi": "\\DuKang\\Taxi\\Transport\\ConfirmOrderTaxiTransport",
},
  "steps": [
    {
      "step_id": "fetchInfoStep",
      "description": "獲取基本信息"
    },
    {
      "step_id": "confirmTravelStep",
      "description": "確認行程信息"
    },
    {
      "step_id": "confirmBillStep",
      "description": "確認計價信息"
    },
    {
      "step_id": "checkStep",
      "description": "成單檢查"
    },
    {
      "step_id": "fillOrderDetailStep",
      "description": "訂單維度填充"
    },
    {
      "step_id": "sendOrderCommandStep",
      "description": "訂單處理操作"
    },
    {
      "step_id": "sendDriverCommandStep",
      "description": "司機處理操作"
    },
    {
      "step_id": "sendSchedulingCommandStep",
      "description": "調度處理操作"
    },
    {
      "step_id": "buildResponseStep",
      "description": "構建響應"
    },
    {
      "step_id": "asyncOperationStep",
      "description": "異步操作"
    },
    {
      "step_id": "writeLogStep",
      "description": "日誌處理"
    }
  ]
}
// dukang框架核心執行過程
try {
    // 加載並解析接口配置,包括BizConfig、StepConfig
    $oBizConf = BizConfig::load($sConfigStr);
    // 獲取輸入源數據,包括Request和基礎數據獲取
    $oInputSource = new ConfirmOrdernputSource();
    // 構造StepRuntime
    $oStepRuntime = new ConfirmOrdertepRuntime($oInputSource);
    // 將接口配置對象、StepRuntime放入流程調度器
    $oFlowScheduler = new FlowScheduler($oBizConf, $oStepRuntime);
    // 初始化傳輸器路由因子
    $oTransportSelectFactor = new ConfirmOrderTransportSelectFactor($oInputSource);
    if($oFlowScheduler->selectTransport($oTransportSelectFactor))
    {
        // 執行流程調度
        $oFlowScheduler->run();
    }
    // 異常處理原則:接口外層只處理DuKangException和Exception,Step或者Ability處理異常則先處理邏輯再拋異常
} catch (DuKangException $e) {
    $aResp = [
        'errno'  => $e->getCode(),
        'errmsg' => $e->getMessage(),
    ];
    echo json_encode($aResp);
} catch (\Exception $e) {
    $aResp = [
        'errno'  => $e->getCode(),
        'errmsg' => $e->getMessage(),
    ];
    echo json_encode($aResp);
}

接下來,再展開對 dukang 的一些核心概念進行講解

2.2.1 Transport - 業務傳輸器 / 承載器

****◎ 定義

****◎ 約束

2.2.2 Step - 流程環節

****◎ 定義

****◎ 特性

****◎ 圖例

2.2.3 StepRuntime - 運行時數據總線

****◎ 定義

****◎ 約束

****◎ 圖例

2.2.4 InputSource - 輸入源

****◎ 定義

****◎ 約束

****◎ 圖例

2.2.5 Transport Factor - 傳輸器因子

****◎ 定義

****◎ 約束

2.2.6 Ability - 能力組件

2.2.6.1 概念描述

◎ 定義

◎ 設計原則

2.2.6.2 業務特徵

****◎ 業務特徵概念歸納

****◎ 業務特徵解決的問題

2.2.6.3 能力組件抽取過程

針對一組業務特徵,將圍繞這些業務特徵的生產、修改操作聚合,形成能力組件。如圍繞播單特徵的播單組件、價格特徵的計價組件等等

****◎ Ability 擴展性

支持以 Addtional 的業務擴展 Ability Mode,即前面提到的 biz 形式定製化 mode,從而達到不同品類在 Ability 上的隔離。

****◎ Ability + 品類場景配置最終思路

複用:基於品類 + 場景(N 元組)配置化,mode selector 靈活決策能力組件的執行模式

差異化:業務通過 biz 實現 mode 的定製,配置化動態加載

2.3 應用框架目錄結構


php 模塊目錄結構示例,golang 模塊整體類似

// 模塊根目錄
├── Dukang // 新引入的內容,區隔老代碼,未來將替代hermes
│   ├── Ability // 能力目錄
│   │   ├── Common // 公用能力
│   │   │   ├── DispatchOrder
│   │   │   │   └── DispatchOrderComponent.php
│   │   │   └── VirtualPhone
│   │   │       └── VirtualPhoneComponent.php
│   │   └── Express // 品類特有能力擴展
│   │       └── DispatchOrder
│   │           └── DispatchOrderComponent.php
│   ├── Config // 接口配置
│   │   └── ConfirmOrder.json
│   ├── InputSource // 接口輸入
│   │   └── ConfirmOrderInputSource.php
│   ├── StepRuntime // 全局數據總線
│   │   └── ConfirmOrderStepRuntime.php
│   ├── Model   // 公用model
│   │   ├── Dao
│   │   ├── Driver
│   │   │   └── DriverModel.php
│   │   └── Order
│   │       └── OrderModel.php
│   ├── Service  // 公用service
│   │   └── Driver
│   │       └── DriverService.php
│   ├── TransportFactor // Transport因子
│   │   └── ConfirmOrderTransportFactor.php
│   └── Transport // 流程串接
│       ├── Base
│       │   └── ConfirmOrderBaseTransport.php
│       └── Taxi
│           └── ConfirmOrderTaxiTransport.php
└── vendor
    └── dukang
        └── framework
            ├── idl  // 數據字典(Dimensions,標準dto)
            └── src  // 框架代碼

本文作者

滴滴服務端技術團隊是滴滴網約車核心後臺研發團隊,負責網約車核心出行、品類技術、開放平臺、業務架構與創新業務、業務中間件等公司級核心項目的研發,支持快車、專車、優步、優享、豪華車、拼車、出租車等出行業務。在這裏,你將面對高併發、大流量、複雜業務的極限挑戰;你將和頂級工程師一起打造分鐘級接入新業務、新功能的技術實現方案。

滴滴服務端技術團隊長期招高級後端研發工程師職位,歡迎有興趣的小夥伴加入,可投遞簡歷至 diditech@didiglobal.com,郵件請郵件主題請命名爲「姓名 - 投遞崗位 - 投遞團隊」。

內容編輯 | Hokka

聯繫我們 | DiDiTech@didiglobal.com

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