滴滴出行平台业务架构演进
点击上方“服务端思维”,选择“设为星标”
回复”669“获取独家整理的精选资料集
回复”加群“加入全国服务端高端社群「后端圈」
桔妹导读:为了满足不同用户在价格、体验等方面的差异化诉求,滴滴提供了越来越丰富的品类,这些品类大体流程是类似的,在一些细节体验上有差异,一套架构如何兼顾隔离和复用,同时支持这些品类,且看滴滴服务端技术的湾流平台怎么做。
▎1.1.2 网约车独特的“菱形”流量分配模式
▍1.2 服务端API职责定位
在开始前,需要先明确服务端API的核心职责。
流量染色:识别和定义接入流量中的品类、场景、功能,并转义标识为统一的业务特征。
流程串接:根据不同事件/请求按照相应的逻辑和流程调用下游服务,以完成具体的功能。
数据渲染:将处理结果数据按不同的端或品类/场景要求渲染成对应的数据视图。
复用:what(复用什么,复用到什么级别), how(怎么实现复用)
隔离:what(隔离的是什么),how(隔离机制是什么)
▍1.3 湾流平台演进
▎1.3.1 湾流平台1.0(2017-2018)
配置化依赖于功能抽象,需要一套统一的抽象方法
插件化依赖于稳固的流程,以及清晰的功能边界。按差异开放插件点会导致插件定义不明确、粒度无法把控、插入点不稳定等问题,长期维护困难。
▎1.3.2 湾流平台2.0(2018)
宏观上,根据核心数据&职能对服务进行了拆分,将一个大模块拆分成多个垂直闭环的子模块,即领域化。通过分治的方式,降低了整体的复杂度,同时也解决了所有团队成员在一个模块开发导致的上线冲突和排队情况。
微观上,按流程和功能对领域服务进一步分析,进行功能聚合与抽象,即组件化。提高复用性,解决业务扩展性和开发效率的问题。
未做系统性的框架约束,迭代容易破坏原有结构
侧重于分治和抽象,未同步考虑品类间隔离问题
//配置文件,管理流程环节,以及提供给不同品类注册各自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的一些核心概念进行讲解
◎ 定义
针对单接口内不同运力(或品类)进行抽象得来的流程载体
任一业务必有其承载的流程和执行顺序
◎ 约束
BaseTransport覆盖当前接口业务的通用流程
任一接口内有且只有一个BaseTransport
XxxTransport覆盖不同运力(或品类)的差异化实现
任一接口内的差异化XxxTransport必须继承自BaseTransport
任一Transport至少包含一个StepTransport <=> [N]Step (N >= 1)
▎2.2.2 Step - 流程环节
◎ 定义
针对单接口内的业务进行抽象出来的环节载体
单一Step是某一段业务环节或功能的具体实现
◎ 特性
单一Step是大粒度差异化(如豪华车/出租车)的有效手段, 可通过Override Step实现
Step间的通信通过统一运行时数据总线StepRuntime串联,理论上可实现热拔插
◎ 图例
业务流程驱动型接口:以串联各个处理流程为主
数据驱动型接口:以构建业务特征数据为主
▎2.2.3 StepRuntime - 运行时数据总线
◎ 定义
流程串联运行时数据总线
◎ 约束
StepRuntime只能作为Ability的输入,不能在Ability及下层逻辑中对StepRuntime的业务特征和数据进行修改
▎2.2.4 InputSource - 输入源
◎ 定义
外部输入数据源,为TransportFactor准备数据
用于消除外部执行环境差异化,隔离外部入参
◎ 约束
进入Step之后具有只读属性,被StepRuntime引用,后续业务逻辑不可修改其包含的所有特征及数据内容
▎2.2.5 Transport Factor - 传输器因子
◎ 定义
业务传输器Transport决策因子
不同接口可能会采取不同的因子进行Transport决策
目前实现的有针对订单维度product_id,针对司机维度car_level
可选择端来源作为决策因子,如滴滴出行app、开放平台、礼橙专车app等
◎ 约束
Factor必须是确定可选择的几类因子,不能由RD同学自由编写
同类业务接口原则上TransportFactor要尽量保持一致
▎2.2.6 Ability - 能力组件
▏2.2.6.1 概念描述
◎ 定义
以特征数据为视角,对聚焦业务进行提炼和抽象,形成能力组件
◎ 设计原则
面向可复用设计
面向可扩展差异化设计
▏2.2.6.2 业务特征
业务表达:播单计划 = $sStartAddDuseTime + $bIsDelayBroadcast + $bIsRepeatAssign+ $iBroadcastAssignType + $iBroadcastExpire
规范业务属性或字段语义,避免歧义和未知语义
定义:业务 = 有序流程 * 控制(特征X, 特征Y, 特征Z, ...), 控制 = 染色 | 填充 | 复写 | 合并 | 标记
▏2.2.6.3 能力组件抽取过程
▍2.3 应用框架目录结构
// 模块根目录
├── 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 // 框架代码
— 本文结束 —
关注我,回复 「加群」 加入各种主题讨论群。
对「服务端思维」有期待,请在文末点个在看
喜欢这篇文章,欢迎转发、分享朋友圈