首页 文章

如何避免轮询耗时的异步REST请求

提问于
浏览
2

问题是如何设计REST Web服务,该服务执行耗时的工作(几秒和几分钟的数量级) .

最快的解决方案是按以下步骤进行:

  • 客户端向服务器发送POST请求(POST / job),答案的HTTP状态为202,并包含作业ID;

  • 客户端使用GET(GET / job /:id / status)定期询问作业状态;

  • 当作业完成时,客户端使用GET(GET / job /:id / result)请求结果 .

我不喜欢的是第2步,因为正在进行许多作业,服务器不必要地过载 . 为了避免这种情况,我想到了另外两个解

  • 当客户端执行第一个POST请求时,它还会提供一个URL,该URL可用作服务器的回调 . 当服务器结束时
    详细说明,它将使用GET / POST通过此URL通知客户端
    请求;

  • 服务器提供一个websocket,客户端可以在其中注册并在作业完成时获得"notifications";

所有这三个解决方案都有我不喜欢的方面:

  • 轮询:服务器超载;

  • 回调:客户端必须为服务器提供URL;

  • websocket:为什么要将另一个"tecnology"引入REST Web服务?也许,在那时,最好只使用websockets来完成所有请求 .

还有其他解决方案吗?如果不是,您认为哪三个更可靠?

2 回答

  • 0

    你几乎自己回答了你的问题 . 问题是,根据您的要求,您会选择哪种方法 . 你的所有建议都是你问题的解决方案,但你必须加重它们并自己决定 . 但是我觉得你对方法1过分夸大了 . 如果你制定了一个进展策略,比如不定期地进行民意调查(不是游泳池),可以说30秒后的第一轮民意调查,20分钟后的下一轮民意调查,10天后的民意调查,5天后的民意调查,那么也许重复那个序列,那么服务器就不会那么紧张了 .

    此外,如果您可以某种方式预测作业的复杂性,则您选择的间隔可能基于POST请求的响应 . 因此,如果工作需要几分钟,例如每5秒轮询就没有意义 . 您可以开发一个类似阵列的策略(以秒为单位的时间):[300,120,60,30,20,10],这意味着您将先等待5分钟,然后再等待2分钟,然后等待1分钟等等 - 您将获得它,你可以间隔10秒完成 . 由于工作本身可能需要几分钟,所以我认为如果结果延迟几秒钟就好了,即准备就绪,但没有准时服务 .

  • 0

    轮询往往非常容易实现,并且非常可靠 . 可靠性来自解决方案的简单性 . 轮询请求一般应该是非常便宜的请求 . 通过退回轮询频率并一次检查多个作业(例如,在一个请求中发送1000个ID),可以使轮询有效 .

    任何非民意调查解决方案都必须是有效通知的一种形式 . 您建议的HTTP回调解决方案要求客户端运行Web服务器 . 它可以做,但似乎没有必要 .

    Web套接字的想法也很明显 . 您将需要重新连接逻辑并处理在客户端碰巧断开连接时作业完成的情况 . 客户端代码可能涉及线程,因为您可能不希望每个作业有一个Web套接字连接 .

    比使用Web套接字更简单的想法是使用“彗星”HTTP请求 . 服务器保持HTTP请求打开,直到作业完成 . 这对于异步IO非常有效,因此在等待时不会阻塞任何线程 . 但是,如果断开连接,则必须实施一些重新连接策略 .

    您可以使服务器将消息写入客户端读取的队列 .

    所有这些通知解决方案往往比简单的轮询解决方案复杂得多 . 他们需要更多的开发人员时间,并且会更频繁地打破 生产环境 . 但它们可以降低延迟并减少资源使用 . 我试着让民意调查工作 . 可能它会工作,你很快就完成了 .

相关问题