桔妹导读:为了满足不同用户在价格、体验等方面的差异化诉求,滴滴提供了越来越丰富的品类,这些品类大体流程是类似的,在一些细节体验上有差异,一套架构如何兼顾隔离和复用,同时支持这些品类,且看滴滴服务端技术的湾流平台怎么做。

1. 

项目背景

在滴滴打车业务中,服务端API向上接收端上请求并组装返回,向下串接订单、计价、收银等业务中台的各个系统,完成整个打车流程,湾流平台项目期望在服务端API层打造一个「出行中台」。在已有业务中台的情况下,为什么还要在业务「前台」API层打造一个「出行中台」,这和出行业务的流量模式是分不开的。

1.1 流量模式

1.1.1 传统和业界常规的“锥状”流量分配模式

传统的典型中台架构是“大中台小前台”,造就这种架构的原因与流量分配模式相关。以电商领域为例,中台抽象了电商相关的业务实体如:订单、收银台、商品等,而不同业务线之间的流量入口是分开的,不同BU间能够以小前台的方式闭环实现。这种“大中台小前台”的架构,可以支持快速构建原型产品进行试错探索,中台提供电商标准的基础能力,前台各自闭合实现B2C、C2C等业务,而业务间互不影响。

流量分配模式表现为:多业务(或品类)开放的前台流量接入,转化至统一有限的业务中台,最终落至基础平台。

1.1.2 网约车独特的“菱形”流量分配模式

滴滴网约车业务核心是打车,为了满足不同用户的需求(定价、应答率、体验等),通过品类区分提供差异化服务能力,从最初的出租车、专车、快车延展到了如今几十个品类。而入口始终围绕在司乘两端、开放平台。

流量分配模式表现为:多品类由统一的端接入流量入口(API)并完成各品类的主要业务逻辑处理,再交由统一的业务中台,最终落至基础平台

网约车的「菱形」流量分配模式注定:服务端API一方面需要支持一些跨BU的平台级需求,如:春节服务费、疫情停开服等;另一方面也要支持不同BU间的差异化需求,如出租车使用打表计价不用线上计价等。

随着品类越来越丰富,这些差异逻辑也越来越多,导致系统越来越臃肿,复杂度越来越高,迭代效率下降。所以需要将服务端API通用的部分下沉,并且开放差异定制的机制,同时兼顾隔离和复用,湾流平台项目应运而生。

1.2 服务端API职责定位

在开始前,需要先明确服务端API的核心职责。

◎ 核心职责

  • 流量染色:识别和定义接入流量中的品类、场景、功能,并转义标识为统一的业务特征。

  • 流程串接:根据不同事件/请求按照相应的逻辑和流程调用下游服务,以完成具体的功能。

  • 数据渲染:将处理结果数据按不同的端或品类/场景要求渲染成对应的数据视图。

◎ 终极问题

  • 复用:what(复用什么,复用到什么级别), how(怎么实现复用)

  • 隔离:what(隔离的是什么),how(隔离机制是什么)

▍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 - 业务传输器/承载器

◎ 定义

  • 针对单接口内不同运力(或品类)进行抽象得来的流程载体

  • 任一业务必有其承载的流程和执行顺序

◎ 约束

  • BaseTransport覆盖当前接口业务的通用流程

    • 任一接口内有且只有一个BaseTransport

  • XxxTransport覆盖不同运力(或品类)的差异化实现

    • 任一接口内的差异化XxxTransport必须继承自BaseTransport

    • 任一Transport至少包含一个Step
      Transport <=> [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 能力组件抽取过程

针对一组业务特征,将围绕这些业务特征的生产、修改操作聚合,形成能力组件。如围绕播单特征的播单组件、价格特征的计价组件等等

◎ 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


滴滴出行平台业务架构演进相关推荐

  1. 精华阅读第 9 期 |滴滴出行 iOS 客户端架构演进之路

    「架构都是演变出来的,没有最好的架构,只有最合适的架构!」最近,滴滴出行平台产品中心 iOS 技术负责人李贤辉接受了 infoQ 的采访,阐述了滴滴的 iOS 客户端架构模式与演变过程.李贤辉也是移动 ...

  2. 滴滴android架构演进,滴滴出行iOS客户端架构演进之路

    自从蘑菇街的李忠老师在移动前线群里做了一次关于iOS组件化的分享之后,大家对于iOS客户端的架构非常感兴趣,展开了热烈的讨论.我很认同一句话,架构都是演变出来的,没有最好的架构,只有最合适的架构,刚好 ...

  3. 滴滴出行的业务中台实践

    经历了 5 年的发展,滴滴出行现已拥有 4.5 亿用户.超过 2100 万车主,业务覆盖 400+ 城市. 在创业初期,为了快速拥抱业务,架构的建设在体系化.完善度等方面会有所不足.随着时间的推移,架 ...

  4. 迁移到MySQL的业务架构演进实战

    来自:DBAplus社群 作者介绍 杨建荣,dbaplus社群联合发起人,竞技世界资深DBA,前搜狐畅游数据库专家,Oracle ACE,腾讯云TVP.具有十多年数据库开发和运维经验,目前专注于开源技 ...

  5. 【SDCC讲师专访】吕毅:链家网大数据平台的架构演进

    2016年11月18日-20日,由CSDN重磅打造的年终技术盛会,SDCC 2016中国软件开发者大会将在北京举行,大会面向国内外的中高端技术人员,聚焦最前沿技术及一线的实践经验,从而助力企业的技术升 ...

  6. 全国城市一卡通一级TSM平台业务架构及意义

    [导读]TSM平台是一种具有鲜明行业属性的平台,因此,各行业都建立了本行业的TSM平台.为促进城市一卡通行业移动支付的快速发展,住房和城乡建设部也建立了全国城市一卡通行业一级TSM平台. 作为住建部标 ...

  7. 今晚直播预告 | CSDN 多场景直播平台的架构演进

    今年除了大会期间的技术分享,我们还邀请了更多在音视频.大前端.网络架构方面的技术牛人,从 9 月 22 日到 10 月17 日,给关注 RTC 技术的开发者们带来" 9 天 11 场&quo ...

  8. 滴滴出行的数据架构和信息流处理思路解析

     截止到今年7月,滴滴注册用户已超过5.5亿,年运送乘客达100亿人次,每日处理数据4875+TB,日定位数超过150亿,每日路径规划请求超过400亿次.       面对庞大的数据量,滴滴的实时计算 ...

  9. 分享哈啰出行小程序架构演进之路

    今天跟大家分享一下哈啰出行支付宝小程序的架构演进之路. 内容主要分四个部分.一是对支付宝小程序的简单介绍和我们的项目背景,二是我们遇到的问题和解决问题的思考,三是我们为了解决这些问题引出的哈啰小程序新 ...

最新文章

  1. servlet文件上传blob_servlet实现从oracle数据库的blob字段中读出文件并显示 | 学步园...
  2. 为什么说嵌入式开发比单片机要难很多?
  3. web网页的表单排版利器--960css
  4. 1206封装电容在物料可靠性设计比较低
  5. python如何表示代码块_如何在Python中重复代码块
  6. 信息学奥赛一本通(1177:奇数单增序列)——比较排序
  7. 无人驾驶(ncnn学习)
  8. 15寸计算机显示器,苹果确认15寸RMBP支持全球首款5K显示器
  9. pytorch tensor_Pytorch之Tensor操作
  10. QT编程入门之QT designer
  11. Warez出品的精品动画
  12. python平稳性检验程序_用python处理时间序列数据,检验平稳性跟纯随机性
  13. python学习2——if 条件检查
  14. html怎样使字数占相同位,《古对今》教案
  15. 植物大战僵尸修改关卡及金币
  16. EUI分页显示的设置
  17. 店铺营收未达标,是客单价的问题吗?
  18. 错误 CS8107 C# 7.0 中不支持功能“xxxxxx”。请使用 7.1 或更高的语言版本。
  19. 一文看懂Echo和Alexa,亚马逊如何用苹果的玩法在玩语音?
  20. extends和implements区别

热门文章

  1. 独享服务器与共享服务器的带宽概念分析
  2. 徐小平:既然你是创业公司老大,就得让兄弟们有肉吃
  3. CDA数据分析师发布官方吉祥物“赵安豆”
  4. Android Studio中R.java的文件路径
  5. ThreadPool.QueueUserWorkItem
  6. 2801 LOL-盖伦的蹲草计划
  7. 计算机教室是在音乐教室旁边吗英文,音乐教室的英文是什么
  8. 对计算机专业的认识英语翻译,英语翻译随着科学技术的不断提高,计算机科学日渐成熟,其强大的功能已为人们深刻认识,它已进入人类社会的各个领域并发挥着越来...
  9. WOW游戏世界浏览器
  10. 科兴大股东1GlobeCapital决定通过英国上诉解决新老董事会之争