NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

Ousta 如何在两分钟的测试周期内模拟客流

  • 2016-12-05
  • 本文字数:3432 字

    阅读完需:约 11 分钟

主要结论

  • Ousta 的模拟服务会监听系统事件,并通过司机专用应用程序的 API 模拟车队司机做出回应。
  • 事件驱动的架构使用了“发布 - 订阅”模式,一个发布方可以有一个或多个订阅方。
  • 用微服务代表系统中每个可测试和可部署的单位,提供不同功能。
  • 弱耦合的系统在测试方面的操作更简单。

Ousta 是埃及领先的 Ride hailing 公交公司(译注:这是一种不设立固定站点,乘客随上随下的公交运营模式。详见: https://en.wikipedia.org/wiki/Hail_and_ride ),该公司的乘客数和车辆数正在经历飞速增长。我们的系统包含两个移动应用,应用可以与基于微服务的事件驱动的架构进行交互。我们通过配合使用 EDA 和微服务搭建了自动化的模拟系统,借此打造了一个可供我们快速演进的环境。

定义问题

我们分别针对乘客和司机开发了两个应用。在开始实现这些应用时,我们决定先从面向客户的乘客应用着手,乘客可以通过这个应用约车。

开发可以实时更新的应用程序会遇到额外的挑战。每次需要对约车过程进行测试时,都需要模拟下列高层事件:

  • 需要由司机应用接受约车请求
  • 车辆抵达时通知乘客
  • 将乘客送达目的地
  • 结束行程

每次移动应用或后端服务发生变化后,我们往往很难对整个流程进行测试,因为我们手头只有乘客应用和 API。

自动化!

我们开始考虑通过自动化解决方案在测试环境中测试整个流程。可是该如何针对乘客应用中进行的操作执行司机 API?我们曾考虑使用外部微服务执行司机 API,监听由于乘客操作产生的系统事件。在我们所用的事件驱动的架构帮助下,这一切可以很容易地实现。

事件驱动的架构

事件驱动的架构极为强大,针对系统执行的每个操作都会产生一个 JSON 对象形式的事件,其中包含了所需的全部信息。

例如约车请求会产生一个事件,其中包含了乘客信息、上车位置、价格等信息。JSON 事件内容如下:

复制代码
{
// Meta part contains information about the event type and category.
"meta":{
"messageCategory":"event_TripInfo",
"messageType":"newTrip"
},
"body":{
"tripId":"d2eac36c-8131-4409-8c37-863b0725fb4d",
"status":"processing",
"riderId":"4524b80a-f82a-4f1c-ad77-69a620c5c628",
"requestTime":"2016-09-09T15:42:32+0000",
"requestTimestamp":1473435752,
"currencyCode":"EGP",
"rider":{
"riderId":"4524b80a-f82a-4f1c-ad77-69a620c5c626",
"firstName":"Mostafa",
"lastName":"Saeed",
"emailAddress":"msaeedatteya@gmail.com",
"mobileNumber":"+201272509147",
"pictureUrl":null,
"rating":"5"
},
"service":{
"serviceId":"7f888b1f-14e4-4b7e-8f8d-1c1ee1df074c",
"displayName":"Super Saver",
"description":"Ousta super saver service",
"code":"Super Saver",
"image":"https:\/\/s3-eu-west-1.amazonaws.com\/oustaridersapp\/services\/ico_cartype_economy.png",
"carPictureUrl":"https:\/\/s3-eu-west-1.amazonaws.com\/oustaridersapp\/services\/img_onmap_car_taxi.png",
"priceDetails":{
"costPerDistance":"1.45",
"costPerMinute":"0.25",
"distanceUnit":"KM",
"base":"4.0",
"cancellation":"10",
"minimum":"10",
"currencyCode":"EGP",
"commissionPercentage":"0.2",
"commissionFees":"0",
"commissionType":"percentage"
}
},
"city":{
"name":"Cairo",
"code":"CA",
"location":{
"latitude":"30.0594699",
"longitude":"31.1884239"
}
},
"pickupLocation":{
"latitude":"30.067615031955",
"longitude":"31.210990101099",
"text":"Tahrir Square, Meret Basha, Qasr an Nile, Cairo Governorate"
},
// Driver & vehicle are null because ride is not accepted by a driver yet.
"driver": null,
"vehicle": null,
"paymentInfo":{
"paymentMethodId":"4496839d-8cd2-4f98-98bb-e059ca7ac5c1",
"type":"cash",
}
}
}

该事件将由多个其他微服务来处理,例如发送推送通知、短信、邮件,或处于分析需要将乘客信息存储在其他位置。我们使用 Amazon SNS 发布事件,使用 Amazon SQS 接收事件,并将消息队列中的客户事件持久存储。

  1. 使用 Amazon SNS(Simple Notification Service):AWS SNS 是亚马逊提供的发布订阅服务,可用于创建与系统逻辑有关的话题(Topic),随后可在发生特定事件后使用 AWS SDK 将事件发布到这些话题。例如当乘客需要约车时,负责预定车程的微服务为该事件创建 JSON 对象,并将事件发布至 TripEvents SNS 话题。
  2. 使用 Amazon SQS(Simple Queueing Service):AWS SQS 是一种消息队列服务,可用于订阅特定 SNS 话题,这样发布到该话题的任何消息即可持久保存在消息队列中,直到最终被服务使用。

下图展示了系统中的事件从发布到最终被不同微服务处理的完整事件流过程。

(点击放大图像)

如图所示,事件驱动的架构使得我们可以轻松地在系统中加入不同用途的新增微服务,整个过程只需要下列步骤:

  1. 新增一个 SQS 队列
  2. 将该队列订阅至特定 SNS 话题
  3. 新增监听该队列的微服务

模拟器微服务

我们曾实现过一种模拟器微服务。通过侦听 TripEvents SNS 话题,该服务可以很容易地根据产生的事件执行必要的操作。例如当收到的事件表示某位司机准备接受或拒绝某个约车请求后,该服务会通过调用 API 代表司机应用接受该行程,具体过程如上图所示。

最开始我们只实现了一种较为简单的版本,涵盖了从乘客发出请求到行程结束的整个过程。不同调用按顺序执行,每个调用之间等待 10 秒钟。完整的行程过程如下所示:

(点击放大图像)

遍布 Qusta 总部四周的“假”司机

我们希望让模拟的过程更真实,因此开始通过模拟司机在不同街道上的活动对模拟器进行优化:

  • 接到乘车请求之前
  • 行驶至上车位置
  • 到达乘客的目的地

随后我们考虑到可以在测试环境中模拟在我们位于开罗市区的总部周围四处行驶的司机。我们希望每隔 x 秒调用一次司机 API,借此向后端系统告知司机当前位置的经纬度。

模拟司机的驾驶过程

由于希望让模拟的过程显得更真实,我们还对模拟服务进行了优化,用一系列代表经纬度的坐标点代表实际路程,这些坐标点代表了从司机接受行程时的位置到乘客上车位置的全过程,以及从上车位置到乘客(请求者)在应用程序中指定的最终目的地的全过程。为此我们使用 Google Distance Matrix API 获取坐标点列表形式代表的两点间完整路径,这样在司机从 A 点到 B 点的行驶过程中模拟器就可以按顺序发送这些点的坐标。

位置更新触发器

最麻烦的部分在于,该如何设置安排好的触发器,以便将每 x 秒一次的位置更新发送给每位模拟的司机。我们考虑了一种解决方案,使用一个可自动触发给服务的 Cron 作业,但这种方式存在局限,最小间隔为一分钟。因此我们需要用一种特殊的方法使用 Amazon SQS。SQS 提供了一个名为 Delay Queues 的强大功能,使得加入队列的消息可以在实际使用前维持 x 秒的不可见状态。下图展示了我们使用这一功能模拟司机行驶过程的方法。

(点击放大图像)

位置更新的采样率

根据应用程序的需求,我们选择了每四秒一次的采样率。精确频繁的位置更新对我们的应用程序和乘车体验很重要,因为我们需要通过这样的更新计算行程的实际距离。

模拟流程总结

(点击放大图像)

独立进行的应用程序测试

模拟服务使得我们可以在将司机应用程序开发完成之前随时测试乘客应用程序的所有功能,这一特性解决了我们开发工作中一个非常大的依赖性问题,无需同时使用这两个应用程序就可以对整个行程进行测试。

两分钟内完成整个测试周期

借助上述方法,我们打造了一个完整的自动化测试解决方案,可以帮助我们更放心地发布新功能,应用变更,修复现有问题,并让每天多次的生产部署变为可能。

关于本文作者

Mostafa Saeed是 Ousta 公司的软件架构师,这是一家位于埃及,正在经历飞速增长的公交公司。Mostafa 领导着开发团队打造了一套事件驱动,可容错,基于微服务的架构。同时他也是 AWS 顾问,帮助大量初创公司应用有关高可用云,以及缩放能力方面的最佳实践。

作者 Mostafa Saeed 阅读英文原文 How Ousta Simulates Rides within a Two-Minute Test Cycle

2016-12-05 17:011262
用户头像

发布了 283 篇内容, 共 102.1 次阅读, 收获喜欢 61 次。

关注

评论

发布
暂无评论
发现更多内容

大部分两三年经验的程序员水平是怎样的?

Java架构师迁哥

跟着华为大佬学习—Java亿级高并发,第一天

Java架构师迁哥

姚翔:递归零知识证明,如何打造简洁的区块链?

CECBC

区块链

必看:Kubernetes 开发环境对比

百度开发者中心

Kubernetes #技术课程#

精选Hive高频面试题11道,附答案详细解析

五分钟学大数据

大数据 hive 5月日更

打破思维定式(六)

Changing Lin

5月日更

详解百度富媒体检索比对系统的关键技术

百度Geek说

大数据 后端 检索 #富媒体#

自己动手丰衣足食——自定义下拉框vue组件

空城机

vue.js 大前端 vue cli 5月日更 编写组件

【欢乐叫地主流程】需求分析/用例设计+游戏测试工作流程/测试计划

程序员阿沐

软件测试 需求分析 测试用例 游戏测试 测试计划

微服务的灾难

Xargin

架构 微服务 microservice

​ 如何保护IP并预防IP泄露

SaaS的前世、今生与未来 [上篇]

LigaAI

SaaS

腾讯云大神亲码“redis深度笔记”,从基础到源码,应有尽有

Java 编程 程序员 架构

腾讯T6大牛体系化带你学习Java面向对象,网友:这详解,太清晰了

牛哄哄的java大师

Java 面向对象 面向对象编程

七面阿里险幸上岸,入职就是40*16K。网友:Java 面经交出来

Java 程序员 架构 面试 计算机

全新 EMQ X Cloud:升配、降费、增效,助力企业智能化升级

DT极客

70%读写性能提升!基于UCloud对象存储US3的用户态文件系统设计

UCloud技术

对象存储

iOS 开发:第三方开源库(Swift版)

迪安

移动开发 Framework iOS Developer Open Source

开发者必看,面试官心中的最佳数据库人才模型是什么样?

华为云开发者联盟

面试 开发者 华为云数据库 数据库人才

网页视频下载教程(腾讯, B站, 优酷, 爱奇艺)

科技猫

经验分享 教程 视频处理 工具分享 网页视频下载

lowcode 和 nocode 没有穿衣服

Xargin

lowcode nocode

一个朋友学会Java泛型后直接薪资翻倍!

北游学Java

Java 泛型

整天用对象,你知道Java中对象的内存布局吗?

码农参上

Java JVM 签约计划第二季

5月,腾讯最新职级技术要求曝光,Linux炸了。

linux大本营

c++ Linux 后台开发 架构师 服务器开发

Python监控打印机队列

IT蜗壳-Tango

IT蜗壳 IT蜗壳教学 5月日更

新场景+新模式,西安雁塔区打造数字人民币示范区

CECBC

XML 文件解析

xcbeyond

XML配置 5月日更

​ 备份测试:备份为什么如此重要

大数据实战:网站流量日志数据分析

大数据技术指南

大数据 5月日更

高德 Serverless 平台建设及实践

阿里巴巴云原生

Serverless 运维 云原生 监控 中间件

两年半,50W的offer,三本,普通前端如何打好自己的牌

月哥

面试

Ousta如何在两分钟的测试周期内模拟客流_语言 & 开发_Mostafa Saeed_InfoQ精选文章