【问题标题】:External API async call with callback带回调的外部 API 异步调用
【发布时间】:2017-07-06 19:42:18
【问题描述】:

我使用 Angular 和 Spring 进行内部 API 通信。现在我需要调用外部 api 来获取一些数据。该外部 API 提供回调功能,因此我触发来自 Angular 的调用,调用 Spring rest 方法,该方法最后调用外部 API。 另一方面,我在我的回调方法(Spring rest 也)上获取数据,但我不知道如何将这些数据传输回 Angular。

websocket 是唯一的选择吗?

【问题讨论】:

  • 能否在外部 API 响应之前保持客户端和 webapp 之间的连接打开?对于单个请求,打开 WebSocket 连接会有点繁重。执行此操作的典型方法是在从外部 API 检索信息之前不让服务器响应。如果外部 API 使用回调功能,您可能会考虑让线程等待回调执行,尽管这可能会根据您预期的服务器负载而变得昂贵。
  • 应用部署在 Heroku 上,所以我没有保持连接的选项,因为来自外部 API 的响应通常 >30 秒,而 Heroku 中的请求超时为 30 秒。

标签: java spring angular


【解决方案1】:

如果内部 API 调用比允许的客户端超时时间长,那么您将需要找到一个 WebSocket 或类似 WebSocket 的替代方案。 WebSockets 的替代方案是使用long-polling(源代码here 的好例子),这实质上是让客户端反复发出请求,直到原始任务完成并且可以发送数据。无论哪种方式,您都需要使用某种pub/sub 机制来处理多个用户,这会使事情变得复杂。

Pub/sub 可能很复杂,我手头没有示例,但基本上您必须 (1) 让客户端使用唯一标识符订阅 频道(您可以通过服务通道与 CometD 一起使用),(2) 评估响应,(3) 将响应发布到客户端订阅的通道,最后 (4) 在通道不再使用时关闭通道。

CometD 作为一个简化发布/订阅频道管理的库,我很幸运,它提供了一个 good abstraction for asynchronous communication,尽管我没有在 Spring 上尝试过它,它可能对你想做的事情很重.

另一个我不太熟悉的选项是使用Spring with STOMP。这似乎来了recommended by others。 Spring 确实提供了使用 STOMP 向单个用户发送消息的方法:Sending message to specific user on Spring Websocket

我建议遵循上面的 STOMP 示例。

其他 STOMP 资源:

附带说明一下,在这里也可能需要进行节流,就像您可以从客户端生成长时间运行的线程一样。


如果您选择不使用 STOMP 或 CometD,那么更轻松的解决方案可能是使用 Spring 的 DeferredResult(如 Roger Hughes example)为这种单一情况推出您自己的 pub/sub,将订阅请求绑定到 long - 通过UUID 令牌的轮询请求,如果您选择禁止每个用户的并发请求,它也可能是会话 ID。在订阅时,系统可以将请求与 UUID 相关联,并将此 UUID 返回给客户端。然后客户端可以发出长轮询请求(再次,如Roger Hughes example),但附加了 UUID。服务器可以等待给定 UUID 的请求完成,然后通过客户端的活动长轮询请求将结果返回给客户端。

可以通过在DeferredResult 结果检索上清除通道并使用充当 GC 的单独线程移除孤立通道来完成通道管理(即请求/UUID 跟踪)——或者,也许更好的是,自动清除孤立通道如果不存在活动的侦听器,则在 DeferredResult 完成/超时时删除它们。如果您选择后一种选项,您需要确保客户端在其长轮询请求之间不会有任何延迟,以便DeferredResult 不会在没有侦听器的情况下意外完成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-03
    • 1970-01-01
    • 2014-11-20
    • 2017-03-10
    • 2013-09-12
    • 2016-09-14
    • 2015-01-20
    • 2016-03-30
    相关资源
    最近更新 更多