【问题标题】:Designing microservice architecture for Object Storage为对象存储设计微服务架构
【发布时间】:2021-04-30 17:22:17
【问题描述】:

我正在尝试为对象存储设计一个微服务架构。我阅读了许多有关微服务的资源。但我还有一些问题。我有一些想法,我会解释,但如果我的设计有缺陷,请指出正确的方向。所以让我们从我的想法和问题开始。顺便说一下,我们可以使用 amazon s3 为例。就像 amazon s3 一样,我的用户将创建/更新/删除存储桶,将对象存储在这些存储桶中,并将执行其他对象操作,例如更新、删除、版本控制等。用户还可以创建 api 密钥和秘密来验证他们的请求。

由于这是我第一次使用微服务进行牛仔竞技表演,我想让事情变得简单。现在我脑子里有 3 个服务,分别是“Auth Service”、“Bucket Service”和“Object Service”。根据我的服务沟通方式,我实际上有 2 个设计理念。第一个是与休息交流。

这是我设计的一个非常基本的版本。

根据我阅读的资源,不建议使用单一数据库。我愿意为每项服务使用不同的数据库。假设用户发送了一个获取对象的请求。使用单体应用程序非常容易做到。

  • 用户发送请求。
  • 服务器通过使用 api 密钥做必要的事情来验证请求。
  • 服务器检查请求对象的存储桶(如果存在)。
  • 最后检查对象,如果存在则返回对象数据。

当我拥有这 3 种不同的服务时呢?当用户请求时,网关会将请求重定向到对象服务。对象服务将要求 Auth Service 对请求进行身份验证。如果一切正常,对象服务将询问存储桶服务是否存在存储桶。如果存储桶存在,对象服务将检查对象,如果对象也存在,则返回结果。 (如果您有更好的思路,请分享您的想法)当我有一个数据库时,这也很容易。通常对象表具有存储桶服务的外键。但是当我将它们分成 2 个独立的数据库时,我仍然会将 bucket_id 列保留在对象表中。当我需要有关存储桶的信息时,我将使用 id 前往存储桶服务。 这是正确的方法吗?

拥有微服务的一个原因是可扩展性。那么当我使用多个服务实例时会发生什么。

我应该为组中的每个服务实例创建一个数据库,还是为所有相同的服务创建一个数据库?

我可以将网关放在每个组的前面,这样我就不必处理大量的 IP 地址和负载平衡。同样的网关或另一个网关也可用于服务之间的通信。但显然,随着服务类型数量的增加,这些方法会出现问题。因此,正如我阅读的资源所建议的那样,我可以使用 RabbitMQ 之类的消息代理。

用户发送同步请求。但是一旦我使用消息代理,它就会变成异步的。我不想返回 202 接受并用另一个请求检查结果。如果用户想对存储桶或对象做某事,这很简单,用户应该立即得到响应。那么如何实现我们上面讨论的相同示例。

例如,当用户发送获取对象信息的请求时,网关会将这个请求重定向到对象服务。对象服务将发送类似“授权请求”的消息。身份验证服务将选择消息并执行必要的操作,然后发送“请求授权”之类的消息。然后在对象服务和存储桶服务之间会发生类似的事情,以获取存储桶信息或检查其是否存在。所以基本上对象服务将发送和接收消息。它需要保留用户请求直到它可以响应它吗?这样做的正确方法是什么?

另一个问题是当我有多个对象服务实例时,用户请求将仅由其中一个处理,但如果所有这些实例都在监听来自其他服务的消息,我将如何将消息发送到正确的一个?我应该将消息路由到特定服务吗?或者我应该将此消息发送给所有服务,但如果消息与服务实例相关,这些服务可能会检查给定的 id?

我可能需要另一个服务来处理流。例如,当用户想要上传或下载文件时。我打算使用像ceph这样的分布式文件存储解决方案。那么我的系统应该如何处理需要数据流的请求。如果有人能一步一步解释,那就太好了。

这些只是基于我的阅读的想法和问题。我想听听你的,即使它与我的相反。你将如何设计这样的系统?您将如何拆分服务?您会选择哪种通信类型来与服务通信?

如果我提供的示例和信息还不够,请随时在 cmets 中提出任何问题。 我很高兴收到你们的来信。谢谢!

【问题讨论】:

    标签: architecture microservices


    【解决方案1】:

    首先,我不会费心在桶服务前面放置另一个服务抽象。它已经是一项服务,您只是在借用复杂性,没有任何优势。

    现在,为了争论,让我们假设您应该有一个存储桶服务(不要),那么抽象它的方法是让您的存储桶有一个对使用它的人不透明的身份。它可能是“bucket_id”,但您可以稍微抽象一下并将其设置为 URI,以便将来如果您决定将存储桶概念存储在文件系统或数据库中,您可以转储它。无论如何,该标识符对对象服务是不透明的。

    如果您想购买异步的复杂性(不是说您应该或不应该),您正在推动将“体验”合并到必须处理请求/响应同步的某个层。这可能是调用服务(对象服务),可能是调用 API(给他们一个位置来回调以检索数据),或者它可以一直到最终用户(我们作为人类一直在同步异步体验)。这仅取决于您将等待异步体验完成的复杂性推到哪里。在您给出的示例中 (auth),您已将异步 -> 同步转换推送到您的调用服务中。

    为了响应异步请求,您可以将响应寻址,以便将其路由到正确的请求者(想想带有请求 ID 的主题队列),或者您可以同步返回客户端可以轮询的 URI回应。

    对于流,只需返回客户端可以打开以检索流的 URI。上传比较棘手,因为客户端可能没有可以提供的 URI,因此它可能无法正常工作。 HTTP 本质上是一个流,所以我不知道 value-prop 是什么。尝试深入了解 S3 以及他们如何处理这个问题,有很多模式可以解决您试图解决的问题。

    【讨论】:

    • 那么如果我理解正确的话,你说对象服务和桶服务可以合二为一吧?在我看来这很合理。另一件事是我不确定在等待来自消息队列的消息时是否保留请求。所以这是完全有效的事情吗?
    • 把 S3 想象成一个数据库,把它放在与任何其他数据库访问相同的层(而不是层)中。在某些情况下,您可以将数据库封装在没有业务逻辑的自己的服务中,但这些情况很少,并且仅适用于非常特定的情况(例如您需要同时透明地支持多个数据库)。是的,async->sync 解析必须发生在某个地方,要么它被推到更高层,要么它留在对象服务中。无论它被推到哪里都会有更多的复杂性和较差的扩展性。
    猜你喜欢
    • 2018-04-28
    • 1970-01-01
    • 2019-04-12
    • 2019-10-08
    • 2020-06-23
    • 2022-11-15
    • 2021-06-04
    相关资源
    最近更新 更多