【问题标题】:Is bad practice to mix REST and RPC together?将 REST 和 RPC 混合在一起是不好的做法吗?
【发布时间】:2014-04-14 20:56:35
【问题描述】:

我对 REST 网络服务还很陌生,并且非常习惯于 RPC。我通过阅读几篇文章(如this 一篇)了解 REST 的优势。

我正在使用 django-rest-framework 在 django 中开发服务器。

虽然有这个问题(或多个问题):

我有这个模型:

class Poll(models.Model):
    questionString = models.CharField(max_length=500, blank=True)
    timeToAnswer = models.IntegerField(default=30)
    startDate = models.DateTimeField(null=True, db_column='startDate', blank=True)
    token = models.CharField(max_length=20, blank=True, unique=True)

class PollAggregator(models.Model):

    name = models.CharField(max_length=135)
    description = models.CharField(max_length=500, blank=True)
    votersToken = models.CharField(max_length=20, null=True, blank=True)

class PollPollAggregatorRel(models.Model):
    pollAggregator = models.ForeignKey(PollAggregator, null=True, db_column='pollAggregatorId', blank=True)
    poll = models.ForeignKey(Poll, null=True, db_column='pollId', blank=True)

所以我可以进行一次投票,也可以在投票聚合器(即房间)中聚合一堆投票。

所以我创建了其余的调用:pollList、pollDetail、pollAggregatorList、pollAggregatorDetail。但是我在为 PollPollAgregatorRel 设计时遇到了问题。 当然,我可以拥有 PollPollAgregatorRelList 和 PollPollAgregatorRelDetail 并进行正常的发布、获取、更新、删除。因此,如果我想在 REST 风格的投票和投票聚合器之间建立新关系,我会这样做:

  • 检查 PollPollAgregator (list) 是否存在带有 get 并由 pollId 过滤的 poll id
  • 如果是这样,我会更新此项目以使用我的新 pollAggregator id
  • 如果不是,我创建一个带有帖子的新 PollPollAgregator

我的第一个问题是有没有更简单的方法来做到这一点?

如果我使用类似 RPC 的 Web 服务,我会执行以下操作:

  • 将民意调查与 pollAggregator 相关联,并为 PollPollAggregatorRel 使用 get_or_create。所以我更新或创建了一个新的 PollPollAggregatorRel 对象。

因此,使用类似 RPC 的方式,客户端只使用一次调用,而 REST 则需要调用 2 次。在这种情况下,将 RPC 用于服务器端和客户端似乎要简单得多。

第二个问题是:在同一个 API 中同时使用 REST 和 RPC 是不好的做法吗?

【问题讨论】:

    标签: django rest rpc django-rest-framework


    【解决方案1】:

    Q1:我认为提供 REST 样式的 POST 操作来返回现有聚合器或根据需要创建新聚合器是合理的。从逻辑上讲,这似乎与您的“RPC”服务没有什么不同。

    我认为你的部分困难可能是你在设计你的 REST“调用”(提示:它们不是“调用”,它们是“资源”)过于接近底层模型。这是我过去犯的一个错误。

    REST != CRUD。

    REST 的一个关键好处是它允许接口与模型分离,因此服务器可以更改其实现而不影响客户端。另一个关键好处是它最大限度地减少了客户为了执行某些操作而需要提前知道的信息量。例如。 REST 客户端应该能够通过与服务的“前端资源”(类似于“前端页面”)交互来发现它需要使用的所有资源 URI。

    所以我会考虑一种方法,其中以下资源涵盖了您上面描述的内容:

    1. 服务主页,其表示包含指向其他资源的链接(或链接模板)(或通过 HTTP 链接头返回链接)

    2. 一种“民意调查集合”资源,用于创建和访问单个民意调查(例如,GET 返回所有民意调查的列表,POST 创建一个新民意调查)

    3. 单个轮询,其 URI 通过与“轮询集合”的交互来发现。 GET、PUT、DELETE 执行您所期望的操作。我不确定您是否需要 POST 来处理这些内容。

    4. 将投票与聚合相关联的“聚合管理器”资源(投票可以属于多个聚合吗?-您的描述表明不属于)。包含 POLL URI 的对此资源的 POST 可以定位或创建一个聚合(或聚合?)或创建一个新的。 GET 可能会返回现有聚合的列表。

    5. 通过与聚合管理器资源交互发现其 URI 的单个聚合资源。

    在您的描述中,PollPollAggregatorRel 是您(当前)实现的一部分,而不是您通过 REST API 公开的东西。这使您可以灵活地更改内部实现,而不会影响客户端使用 API 的方式。这就是 REST 的意义所在。

    我不确定您是否认为这“更简单”,但这不是 REST 的重点。 Roy Fielding 将 REST 描述为“数十年规模的软件工程”,重点是创建一个允许客户端和服务器实现相对独立演进的接口,这对于以 Web 规模运行的应用程序至关重要。这样做是有代价的,即客户端必须与服务器交互以发现进行交互所需的信息。

    Q2:我认为在同一个 API 中混合使用 REST 和 RPC 是不明智的。 (将 REST 暴露给外部;客户端并在内部使用 RPC 或提供单独的 API 可能非常有意义。)

    我这样做的理由是,如果您有一个主要是 REST API,添加一个 RPC 元素可能会在客户端和服务器之间创建一个紧密耦合,而不是首先否定使用 REST 的意义。

    【讨论】:

    • 好帖子!谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-05
    • 2020-05-19
    • 2020-02-27
    • 1970-01-01
    相关资源
    最近更新 更多