【问题标题】:How to RESTfully support the creation of a resource which is a collection of other resources and avoiding HTTP timeouts due to DB creation?如何 RESTful 支持创建作为其他资源集合的资源并避免由于 DB 创建导致的 HTTP 超时?
【发布时间】:2014-08-30 21:07:31
【问题描述】:

在我的应用程序中,我有 Draw 的概念,并且 Draw 必须始终包含在 Order 中。

Draw 有一组属性:background_color, font_size, ...

引用著名的 REST 论点:

任何可以命名的信息都可以是资源:文档或 图像,时间服务(例如“洛杉矶今天的天气”), 其他资源的集合,一个非虚拟对象(例如一个人), 等等。

所以,我在这里收集的其他资源将是一个订单。订单是一组抽奖(通常超过数千)。我想让用户创建一个带有多个 Draws 的订单,这是我的第一种方法:

{
    "order": {
      "background_color" : "rgb(255,255,255)", "font_size" : 10,
      "draws_attributes": [{
            "background_color" : "rgb(0,0,0)", "font_size" : 14
        }, {
           "other_attribute" : "value",
        },
       ]
       }
}

对此的响应如下所示:

"order": {
          "id" : 30,
          "draws": [{
                "id" : 4
            }, {
               "id" : 5
            },
           ]
           }
    }

这样用户就会知道在数据库中创建了哪些资源。但是,当请求中有很多抽奖时,由于所有这些抽奖都插入到数据库中,因此响应需要一段时间。想象一下,如果订单有 10.000 次抽奖,则执行 10.000 次插入。

由于我需要向用户提供刚刚创建的绘图的 ID(顺便说一下,创建但尚未完成,因为在处理订单时,我们实际上使用一些图像处理库构建了绘图),所以他们可以稍后获取它们,我看不到如何以 RESTful 方式处理此问题,避免使 HTTP 请求花费大量时间,但同时为用户提供某种用于抽奖的 Id,以便他们可以获取它们稍后。

遇到这种情况你是怎么处理的?

【问题讨论】:

    标签: web-services rest api-design nested-resources


    【解决方案1】:

    批发接受请求,排队处理,返回代表请求状态的状态 URL。当请求完成处理后,显示一个代表请求结果的 url。然后,投票。

    POST /submitOrder
    
    301
    Location: http://host.com/orderstatus/1234
    
    GET /orderstatus/1234
    
    200
    { status:"PROCESSING", msg: "Request still processing"}
    
    ...
    
    GET /orderstaus/1234
    
    200
    { status:"COMPLETED", msg: "Request completed", rel="http://host.com/orderresults/3456" }
    

    附录:

    嗯,有几个选择。

    1) 他们可以等待结果处理并在完成后获取 ID,就像现在一样。与我建议的不同之处在于,网络连接的状态与事务的成功或失败无关。

    2) 您可以在访问数据库之前预先分配订单 ID,然后将其返回给调用者。但请注意,这些资源还不存在(在处理完成之前它们不会存在)。

    3) 将您的系统加速到不存在超时问题的地方。

    【讨论】:

    • 感谢您的回答。但是,如果用户在执行请求时没有正确获得 ID,他们如何知道订单中的每个 Draw 是什么?现在,我给他们一个 ID,说你提交的第一个 Draw 有这个 ID,第二个有这个另一个 ID。我的意思是,假设由于某种原因无法处理其中一个 Draw,他们无法按顺序进行映射以找出哪个是哪个,对吧?
    • @Nobita:您可以在数据库中使用序列,也可以使用 guid,在数据库之外有几种机制可以做到这一点。关于排队,是的,您可以将整个文档推到队列中,然后让工作按时解决。
    • 我不确定我理解“数据库中的序列”或 guid 是什么意思。 Order POST 请求附带 N 次抽奖。如果我想为用户提供订单和所有抽奖的某种唯一 ID,而不必访问数据库,以便他们以后可以实际使用该 ID 来获取这些资源中的任何一个,你是怎么做到的?我想首先有必要查看传递的 JSON 中有多少个 Draws,这样你就知道你必须回馈多少个 ID,但我最关心的是:我怎么知道我应该给哪些 Id回来了吗?
    • 我看到的一个解决方案是让他们为每个 Draw 传递一个 ID,因此当我实际创建 Draw 并将它们返回给用户时,他们可以映射它们。你怎么看?
    • @HommerSmith:有几种机制可用于创建不加载数据库的标识符。例如,您可以有一个返回 ID 的简单服务,但每 100 个请求只更新一次数据库。一些 GUID 算法只是非常大的随机数,它们只是希望它们不会发生冲突。 (即碰撞是可能的,只是非常非常不可能)。其他人使用当前时间和本地标识符(如机器 ID 或 MAC 地址)的组合。有几种方案可以生成对数据库影响很小的 ID。
    【解决方案2】:

    我认为您暴露的粒度太细了-用户是否需要能够分别修改每个Draw?如果不是,则提供一个代表Order 的文档,其中自然包含Draws。

    您是否需要根据与Order 无关的特定条件从数据库中查询特定的Draws?如果不是,则将所有 Draws 表示为单个 blob,该 blob 是表示 Order 的行的一部分。

    【讨论】:

    • Tassos,用户必须能够在订单中获得特定的抽奖。如果当他创建带有嵌套 Draws 的 Order 时,我不给他提供 draws 的 ID,他将如何获得特定的 draw?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-31
    • 1970-01-01
    • 2019-07-15
    • 2014-10-21
    • 2013-11-01
    相关资源
    最近更新 更多