如何设计亿级用户网约车系统
《如何设计亿级用户网约车系统》共 0.5 万字,通篇围绕 Redis、微服务、数据库、并发 展开,归在「后端与系统架构」这一层。
适合给 AI 系统搭底座、要管得住的人
目录骨架(8 节)
- 业务介绍
- 需求分析
- 概要设计
- 详细设计
- 长连接管理
- 距离计算
- 派单算法
- 订单状态模型
分享内容
- 网约车业务介绍
- 网约车系统需求分析
- 网约车系统概要设计(乘客端、司机端)
- 网约车系统详细设计(长连接管理、距离计算、派单算法、订单状态模型)
业务介绍
网约车的官方定义是:“以互联网技术为依托,构建服务平台,整合供需信息,使用符合条件的车辆和驾驶员,提供非巡游的预约出租汽车服务的经营活动。” 通俗地说就是:利用互联网技术平台,将乘客的乘车信息发送给合适的司机,由司机完成接送乘客的服务。网约车包含专车、快车、拼车等多种形式。
中国目前网约车用户规模约 5 亿,我们准备开发一个可支撑目前全部中国用户使用的网约车平台,应用名称为 “Udi”。
需求分析
Udi 是一个网约车平台,核心功能是将乘客的叫车订单发送给附近的网约车司机,司机接单后,到上车点接乘客并送往目的地,到达后,乘客支付订单。根据平台的分成比例,司机提取一部分金额作为收益,用例图如下:

Udi 平台预计注册乘客 5 亿,日活用户 5 千万,平均每个乘客 1.2 个订单,日订单量 6 千万。平均客单价 30 元,平台每日总营收 18 亿元。平台和司机按 3:7 的比例进行分成,那么平台每天可赚 5.4 亿元。
另外,平台预计注册司机 5 千万,日活司机 2 千万。
概要设计
网约车平台是共享经济的一种,目的就是要将乘客和司机撮合起来,所以需要开发两个 App 应用,一个是给乘客的,用来叫车;一个是给司机的,用来接单。Udi 整体架构如下图:

相应的,Udi 的系统也可以分成两个部分,一个部分是面向乘客的。乘客通过手机 App 注册成为用户,然后就可以在手机上选择出发地和目的地,进行叫车了。乘客叫车的 HTTP 请求首先通过一个负载均衡服务器集群,到达网关集群,再由网关集群调用相关的微服务,完成请求处理,如下图:

网关处理叫车请求的过程是:网关首先调用订单微服务,为用户的叫车请求创建一个订单,订单微服务将订单记录到数据库中,并将订单状态设置为 “创建”。然后网关调用叫车微服务,叫车微服务将用户信息、出发地、目的地等数据封装成一个消息,发送到消息队列,等待系统为订单分配司机。
Udi 系统的另一部分是面向司机的,司机需要不停将自己的位置信息发送给平台,同时,还需要随时接收来自平台的指令。因此,不同于用户通过 HTTP 发送请求给平台,司机 App 需要通过 TCP 长连接和平台服务器保持通信,如下图:

Udi 司机 App 每 3 秒向平台发送一次当前的位置信息,包括当前车辆经纬度,车头朝向等。位置信息通过 TCP 连接到达平台的 TCP 连接服务器集群,TCP 连接服务器集群的作用类似网关,只不过是以 TCP 长连接的方式向 App 端提供接入服务。TCP 连接服务器将司机的位置信息更新到地理位置服务。
对于前面已经写入到消息队列的乘客叫车订单信息,分单子系统作为消息消费者,从消息队列中获取并处理。分单子系统首先将数据库中的订单状态修改为 “派单中”,然后调用派单引擎进行派单。派单引擎根据用户的上车出发地点,以及司机上传的地理位置信息进行匹配,选择最合适的司机进行派单。派单消息通过一个专门的消息推送服务进行发送,消息推送服务利用 TCP 长连接服务器,将消息发送给匹配到的司机,同时分单子系统更新数据库订单状态为 “已派单”。
详细设计
关于 Udi 的详细设计,我们将关注网约车平台一些独有的技术特点:长连接管理、派单算法、距离计算。此外,因为订单状态模型是所有交易类应用都非常重要的一个模型,所以我们也会在这里讨论 Udi 的订单状态模型。
长连接管理
因为司机 App 需要不断向 Udi 系统发送当前位置信息,以及实时接收 Udi 推送的派单请求,所以司机 App 需要和 Udi 系统保持长连接。因此,我们选择让司机 App 和 Udi 系统直接通过 TCP 协议进行长连接。
TCP 连接和 HTTP 连接不同。HTTP 是无状态的,每次 HTTP 请求都可以通过负载均衡服务器,被分发到不同的网关服务器进行处理,正如乘客 App 和服务器的连接那样。也就是说,HTTP 在发起请求的时候,无需知道自己要连接的服务器是哪一台。
而 TCP 是长连接,一旦建立了连接,连接通道就需要长期保持,不管是司机 App 发送位置信息给服务器,还是服务器推送派单信息给司机 App,都需要使用这个特定的连接通道。也就是说,司机 App 和服务器的连接是特定的,司机 App 需要知道自己连接的服务器是哪一台,而 Udi 给司机 App 推送消息的时候,也需要知道要通过哪一台服务器才能完成推送。
所以,司机端的 TCP 长连接需要进行专门管理,处理司机 App 和服务器的连接信息,具体架构如下图。

