这篇文章讨论了我在为 Here Mobility 工作时遇到的一个具体案例研究。它描述了为什么我们决定统一我们的两个服务,以及为什么我们最初将它们分开。我相信当你应该考虑统一两个微服务时它很好地展示了它,并希望它可以帮助其他人为未来的产品做出好的设计。这是一系列帖子中的第一篇。在我的下一篇文章中,我将分享我们如何实际统一服务的计划,同时继续为客户服务。

背景

我们开发的产品称为 Mobility Dispatch。 Mobility Dispatch 帮助出租车公司轻松管理司机、乘车和乘客。它通过直观的管理面板实现乘客和司机的匹配,包括实时可见性和跟踪车队和骑行状态。该产品包括一个网络应用程序和一个移动应用程序。出于本文的目的,我将重点介绍骑行创建的具体功能。用户可以创建两种类型的游乐设施 - 即时游乐设施,即发送给司机以立即开始,以及提前预订的游乐设施(我们从现在开始将其称为预预订),它们将在未来到期。

我们决定创建单独的服务来管理游乐设施和预订 - 分别是 Rides 服务和 Calendar 服务。由于以下产品功能和基础设施情况,我们做出此决定:

  1. 在实时地图上显示所有车辆的当前位置,以帮助轮班经理随时了解他的车队在哪里。这意味着将有大量来自客户端的调用——移动应用程序报告当前位置,而 Web 应用程序轮询更新的位置。因此,有一个专门的服务来处理负载是有意义的。

  2. 将预读本放在一张预读本专用的桌子上,以便轮班经理可以看到所有未来的游乐设施都集中在一个地方。这加强了一种感觉,即预订和游乐设施实际上是不同的逻辑实体。

  3. 新创建的与现有 prebook 相矛盾的 prebook,向 web 用户发送通知。因此,我们需要一个用于 prebooks 的约束管理器。游乐设施不需要这样的东西。这是对游乐设施和预购书是不同逻辑实体的概念的又一次强化。

  4. 在我们已经支持即时游乐设施之后引入了预订概念,并且我们已经有了实时游乐设施服务。乘车服务是一项过时的服务,它使用量身定制的状态机进行即时乘车。我们认为拥有一个干净的服务来支持新功能将需要更少的开发时间。

问题

分离的服务架构为我们服务了大约一年。在那一年中,我们遇到了几个让我们质疑设计的困难:

  1. API 的更改需要更改两个服务的代码库: 如果我们添加了一个像 “getAllRidesByAWhiteVehicle” 这样的调用,我们需要在两个服务中实现它,这使得添加新代码很麻烦并且消耗更多时间。这实际上表明,游乐设施和预订书并不是我们最初认为的异化实体。

  2. **两个服务之间的来回网络调用:**虽然一开始看起来_Rides_服务和_Calendar_服务之间有明显的分离,但我们遇到了很多服务需要通信的情况。最简单的例子是骑行的审计历史。

  3. 服务具有相似的代码库: Ride 和 Prebook 的数据模型相似 — 都具有相似的乘车限制,例如乘客数量、轮椅选项等。此外,这两种服务都使用状态机和一个可以类似实现的调度程序。

  4. **最后一根稻草 — 一个新的业务逻辑:**我们的产品满足了编辑主动骑行的要求,因此它变成了一个预订书,反之亦然。这打破了乘车和预订是异化实体的假设,将它们管理在不同的服务中,并保存在不同的数据库中,不再有意义。

上述前三个让我们渴望有机会统一这两个服务。添加新的业务逻辑是我们改进设计所需的机会,因为我们可以利用在基础架构更改中添加新功能。

我认为这个研究案例指出了微服务架构中的一些细微差别。在添加新功能时,我们应该质疑我们的架构是否仍然合理。在这种情况下,一开始似乎乘车和预订书有权作为独立的实体存在,因此具有独立的服务和数据库。随着越来越多的需求和特性的到来,很明显,服务分离造成了繁琐,需要加以处理。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐