【问题标题】:Microservices/REST - How to store references to resources in other service微服务/REST - 如何在其他服务中存储对资源的引用
【发布时间】:2019-04-11 08:39:39
【问题描述】:

假设来自 rest-service A 的资源 X(http://example.com/a/foo/7) 需要持有对来自 rest-service B 的第二个资源 Y(http://example.com/b/bar/1) 的引用。

如何保持引用?

目前我将 Y 的整个 URI(作为字符串)存储在服务 A 的持久层中。这是一种常见/有效的方法吗? 从 Y 的 URI 中提取 id(1) 对我来说似乎是错误的,因为我会在服务 A 中实现关于服务 B 的 URI 结构的假设。这是正确的吗?

你如何解决这个问题?

谢谢!

【问题讨论】:

    标签: rest microservices


    【解决方案1】:

    让我们与一些实际的业务领域讨论它,然后答案就会有意义。

    第一个例子:

    X 代表亚马逊订单服务中的订单实体,Y 代表客户服务中的客户。

    现在,在通过 Order Service 从 Amazon 获取订单时,您还希望显示一些基本的客户详细信息并链接到客户对象以转到客户详细信息页面。

    在这种情况下,我要做的是在创建订单时复制订单实体中客户的一些基本属性(customerName、customerArea)。

    还存储 customerId、customerType。由于获取客户的 API 是公开的,并且还暴露给各种内部服务,Order Service 将进行服务发现并创建 URL 和调用。在这些情况下,客户服务通常不会停止支持旧方式(即使他们正在构建新方式)。

    所以只存储 id 是一种解决方案。

    案例 2:

    亚马逊订单实体想要存储送货细节,而送货合作伙伴是像 DHL 这样的第三方实体,那么如果 DHL 提供了一个 URL 来获取订单的送货更新,在这种情况下,我将只存储该 URL。

    一般来说,我更喜欢存储 id 和服务类型以及一些基本细节,以创造良好的客户体验,同时避免使用额外的服务 api 来获取客户姓名等基本细节。

    当它是第三方 URL 时,存储直接 URL 是有意义的。

    另外,如果你能举出这样的商业案例的例子,我们可以更好地讨论

    【讨论】:

    • 感谢@techagrammer 的回答! CASE2 很清楚-在这种情况下,我与您同在。但在第一种情况下,您是说我应该存储 customerId,而不是 URI。但是,如果服务没有在响应中公开这些内部信息怎么办?然后,imo,URI 是唯一可用的唯一资源标识符。但即使有这样的数据,为了重建 URI,我也需要知道如何基于 uri 模板进行构建。
    • @ibexit 在案例 1 中存在一定的假设,即团队知道其他服务的一些内部信息(如何发现服务并调用 API)。随着订单和客户服务的发展,整个组织都将遵守一些核心原则,这将有助于他们加快发展。如果你像 Lagom 和其他微服务框架这样的框架,他们会做这些服务发现,而且都是开箱即用的。此外,imo 构建服务使得一个人对同一组织中的另一个人一无所知并不是一个好主意,因为这会产生更大的开销
    • 嘿@techagrammer,很高兴见到你回到这里。只是为了使其更具体。假设服务 A 是 CategoryService,B 是 BookService。我们需要对书籍进行分类。要存储在一个类别中的一本书如下所示:GET http://example.com/books/123456 { “title“: “lorem ipsum“ } 。您将如何在 CategoryService 中存储对图书的引用?
    • @ibexit 在此假设类别中有书籍列表,并且书籍可以属于多个类别,还假设类别服务不是一个非常通用的服务,例如标签,您可以在其中标记任何内容,当我添加在我将调用 API“example.com/category/1/addBook”的类别中的书数据是 {“bookId”:“book-1”}。现在,当类别服务存储时,它将查询图书服务并使用类别服务中的 BookService 接口通过调用函数 getBook 获取图书详细信息 - (可能通过 REST 或使用 GRPC 在内部命中它)并保存 {bookId : book-1 , 书名:书名}。
    • 明白你的意思。但是你有没有看到,books 响应中没有 bookId?
    【解决方案2】:

    IMO 参考应按原样存储。您如何从参考中获取实际数据不应该是数据的一部分,而是可能会不时改变的逻辑。 我会将它们存储为外部参考的参考(只是为了描绘参考在我们的服务之外)并将其与查询数据的逻辑相结合。

    网址非常不稳定,可能会发生变化。根据经验,你永远不应该在你的数据库中保留 url,并且应该依靠服务发现来识别服务在哪里,即使它在你自己的基础设施中。

    这不是假设,而是合同,可能会发生变化,如果发生变化,您的服务将是依赖服务并且必须做出适当的更改

    同样按照你的逻辑,即使你保留了 url,对它的响应仍然是你们双方都遵守的合同。

    【讨论】:

    • 非常感谢您的回复。我完全同意 URL 和响应可能会改变。我不(仅)将 URI 视为获取实体的引用或方式,而是将 URI 视为统一资源标识符。当然,这个URI不一定是特定服务实例的URI,而是基于API网关的URI。如果同一实体的 URI 发生更改,则旧 URI 上应该有永久重定向。现在我们将能够更新存储的 URI(如果需要)。这同样适用于响应更改 - 旧的表示应该仍然存在,可以作为新格式的投影。 ???
    • 这不仅仅是关于他们的变化。 URI 是获取数据的手段,也可能有其他手段。休息端点只是给你一个地址来敲门并询问数据以供参考,明天你可能想要这些通信的其他方式。 IMO 他们应该是分开的。此外,如果您可以控制更改应如何在服务中传播,您可以拨打电话,但如果您不是,我宁愿不想仅仅因为服务 Y 或 api 网关决定重命名端点而通过并更新 100 个条目.final 由您决定,如果您认为利大于弊,那就这样吧。
    猜你喜欢
    • 2015-07-28
    • 2019-11-15
    • 2017-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-31
    • 1970-01-01
    相关资源
    最近更新 更多