首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rest体系结构在实践中的应用

Rest体系结构在实践中的应用
EN

Software Engineering用户
提问于 2013-07-17 10:34:24
回答 3查看 892关注 0票数 1

我们维护一个API,作为其目的的一部分,调用外部API。这个外部API需要几秒钟才能满足我们对它提出的请求。在当前架构中,请求是同步进行的,这意味着我们返回给用户请求的http响应将被阻塞,直到我们的服务从外部API获得响应为止。

我正在考虑改变我们的架构,以便能够异步地处理请求.我的意思是在API中接受用户请求,并将消息放到队列中,这样返回http响应的速度要快得多。响应将包含可以找到完整/完整结果的地址。然后,后台任务将从队列中获取消息并对外部API进行调用,然后将结果存储在响应中提供的地址。然后,该地址可以由用户/客户端轮询,直到达到所需的呼吸资源状态(即,当后台任务完成调用外部api并存储结果时)。

这种建筑我主要是在练习书中从其他建筑中提出来的。然而,关键是我们的外部API只需2-3秒就可以返回响应。书中的例子描述了一个可能需要几分钟或几个小时的订购过程。这个建议的解决方案是否值得在如此短的响应时间内从外部依赖中增加复杂性?也就是说,应用程序是否仍将按照现有的同步架构进行扩展?

EN

回答 3

Software Engineering用户

发布于 2014-07-27 10:13:46

您所描述的情况(使用队列和轮询)肯定可以工作,但是只要您的外部API只需几秒钟就可以返回响应,我认为有一种更简单的方法:

正如您所描述的,让您的网页响应不包括来自外部API的数据是个好主意,因为这样可以更快地发送页面响应。我将按以下方式调用外部API:

  • 响应页面包含一段javascript,它对网站上的REST端点进行异步AJAX调用。
  • REST端点调用外部API,并阻塞直到它接收到响应。一旦接收到响应,就会将结果返回给调用方(即执行AJAX调用的浏览器)。
  • 当响应页javascript接收来自AJAX调用的数据时,它通过操作响应页面的HTML来显示结果。

这样,惟一需要异步的东西是来自浏览器的AJAX调用;这有效地启动了一个新的“后台线程”,并且在这个线程中运行的调用(从浏览器,到REST端点,到外部API,然后再回来)都可以同步执行。

显然,只有外部API足够快地返回其响应(不到一分钟左右),否则同步调用就会超时。只要您对这种情况有信心,我认为这个解决方案在满足您的需求的同时也不会那么复杂。

票数 2
EN

Software Engineering用户

发布于 2013-07-17 10:51:50

REST中没有什么可以阻止您在每个资源和方法组合中混合同步和异步解决方案。

例如,在我们的查询服务器中,由于资源/信息随时可用,我们几乎同步返回所有内容。只有当一个新的查询被发布时,我们才会选择生成一个标识符并返回一个“接受”或“查看其他”(303)响应的路径,该响应具有主体中查询结果资源的URI以及位置标头。再次同步地返回有关查询和查询结果本身的信息。

更新

在发布查询的结果数据可用之前,不要在平均延迟上有任何数字。我们仍在致力于其余的实现。然而,当前架构中的查询通常需要几毫秒才能完成(我们是一个内存中的数据库),尽管我们有一些客户知道有些查询需要20分钟才能返回结果。因此,从某种意义上说,异步性的需求并不是平均延迟,而是我们不希望有任何可能在任何严重的时间(> 1秒左右)阻塞连接的请求,而且客户可以发布运行时间更长的查询。

为了提供有关异步执行查询的更多细节:

  • “查询结果”是保存发布查询结果的基本信息的资源:标识符、状态(进度)、结果数据的uri (在可用之前为空/缺席)、这类东西。
  • 新的“查询结果”资源将在返回对POST的响应之前立即存储。
  • 查询过程用其进度并最终用结果数据中的行总数更新“查询结果”。

换句话说:新的“查询结果”资源一返回就可以查询。只是还没完成。轮询查询结果将显示状态和进度,一旦查询过程完成,状态将被完成,结果数据的uri将具有一个值。

票数 1
EN

Software Engineering用户

发布于 2014-07-27 14:05:55

如果出于任何原因,您确实希望将当前工作流与显示结果的位置分开,则可以在JSON响应中使用links-section。

代码语言:javascript
复制
{
    "name": "currentStep",

    ...

    "links": [ {
        "rel": "self",
        "href": "/api/job/currentStep"
    },
    {
        "rel": "previousStep",
        "href": "/api/job/previousStep"
    },
    {
        "rel": "result",
        "href": "/api/job/result"
    }
     ]
}

这意味着你现在在哪里,你以前在哪里,结果会在哪里。用这种方式来实现它,你就会表明你的意图,结果是在一个不同的位置。这样就解决了目前等待结果的问题。

这个解决方案没有涵盖的问题是,您和您的API的用户都不知道是否有结果,或者在给定的URL下结果何时可用。所以你的整体问题没有解决,只是被推迟了。当调用URL (在我的示例中为/api/作业/结果)时,它不确定是否有结果。

一方面,您有一个同步服务,平均持续2-3秒,在此之后,您将结果不中断地返回给用户,或者在另一方面,可能会出现空白,但立即回答。

如果没有对总体架构和用户基础的进一步了解,就很难说出任何东西。2-3秒有多关键?在金融领域,它可能是至关重要的,在其他部门,它可能是可以忽略的。

另一个解决方案出现在我的脑海中,但为此,我必须了解更多您的应用程序基础结构:

如果需要更多的服务调用,则可以使它们都是异步的。假设您有以下设置:

要组合整个请求,您必须执行步骤A、B.C和D。在本例中,D是对外部服务的调用,这需要2-3个步骤。所以,如果你把它们都按顺序做,你就有步骤A,用0.5s,B0.5s和C0.5s。那是1.5秒。其中增加了呼叫D的2s。这使得整个3.5倍的等待时间。

如果你同时做这些事情,你只需要等待最慢的。在这种情况下,这将是2s,这是显着地快。

更别提长轮询/彗星(“旧学校”)或websockets。有了websockets,您就有可能在有了websockets之后立即将结果从服务器推入管道。

票数 0
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/205160

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档