Qwen3 惊喜上线阿里云百炼,8款模型全开源!点击免费领取 800万 tokens! 了解详情
写点什么

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:011606
用户头像

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

关注

评论

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

如何有效改进erp管理系统?erp管理系统改进建议方向

优秀

ERP管理系统

邀你见证一本思维小册子的诞生:《豆哥宝典:思维模型》

豆哥

AI 思维模型 GPT 宝典

披荆斩棘的芒果 TV:基于 StarRocks 的云原生湖仓架构升级

StarRocks

云桌面如何部署?云桌面系统方案部署详细教程

青椒云云电脑

云桌面 云桌面系统

Python 实训教学,更便捷的学生邀请及内容分发|ModelWhale 版本更新

ModelWhale

人工智能 数据分析 在线编程 高等教育 云课堂

哪家强?Bitget Wallet vs Metamask 从安全性能角度全方位 PK

股市老人

数字时代的自我呈现:探索个人形象打造的创新工具——FaceChain深度学习模型工具

汀丶人工智能

人工智能 计算机视觉 图像生成

什么是多云? 为什么我们需要多云可观测性 (Observability)?

NineData

多云服务 多云架构 多云管理 多云 多云多源

持续测试新范式:拨压测一体化

阿里巴巴云原生

阿里云 云原生 压测 拨测

简单聊聊低代码

互联网工科生

低代码 数字化

语音识别技术:从传统到现代的飞跃

数据堂

​左手 Serverless,右手 AI,7 年躬身的古籍修复之路

阿里巴巴云原生

阿里云 Serverless 云原生

Zilliz X Dify.AI ,快速打造知识库 AI 应用

Zilliz

大模型 Zilliz LLM zillizcloud

语音识别技术的优化与发展趋势

数据堂

回归营销初心,2023金投赏鲸鸿动能专场聚焦品牌重塑

最新动态

算启新程 智享未来,英特尔携中国移动为行业数字化转型提供新动能

E科讯

ETL数据转换方式有哪些?

RestCloud

数据同步 ETL

SRM供应商招采系统(源码)

金陵老街

基于Vue构建的快速开发框架

树上有只程序猿

Vue 低代码

2023年10款好用的AI生成PPT软件盘点,干货建议收藏!

彭宏豪95

效率 软件 职场 PPT AIGC

LeetCode题解:1486. 数组异或操作,模拟,JavaScript,详细注释

Lee Chen

文心一言 VS 讯飞星火 VS chatgpt (111)-- 算法导论10.2 2题

福大大架构师每日一题

福大大架构师每日一题

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