【问题标题】:How to monitor REST Endpoint for long running jobs如何监控 REST Endpoint 以获取长时间运行的作业
【发布时间】:2019-11-17 07:12:48
【问题描述】:

我有一个 API,它具有一系列端点,这些端点都执行非常长时间运行的作业,例如可能需要 48 小时才能完成的作业。

当然,我不能让客户等待 48 小时才能返回响应,所以我正在寻找处理这些情况的最佳解决方案。

我知道该怎么做,但我不确定这是否是一个值得的解决方案,或者在基于生产的应用程序中是如何完成的。此外,如果需要,我想实现一种方法来取消正在运行的作业,并更新/监控作业的整体进度。

我当前的设置如下:

  1. API 收到开始长作业的请求

  2. 作业信息的条目存储在 DB 中,作业状态设置为 PENDING

  3. 该作业信息放置在 Rabbit MQ 消息中并由 RabbitMQ Producer 发送出去

  4. 作业 ID 被返回到发起 API 调用的客户端,状态为 202,接受状态

  5. RabbitMQ Consumer 接收到带有作业信息的消息并调用负责执行长时间运行作业的类,作业状态更新为 IN-PROGRESS

  6. 现在客户端可以通过另一个接受作业 id 并返回当前状态/信息的端点检查作业的状态

我认为这种方法可行,而且似乎可扩展,但我有一些担忧,也许有人可以提供一些见解或帮助我解决:

A.如果需要,我希望能够从另一个暴露的端点杀死工作,完成这种事情的最佳方法是什么?我在想,当服务将状态更新为 IN-PROGRESS 并开始处理时,也许我还可以在步骤 5 中将线程 ID 与作业信息一起保存。然后,当我点击取消作业端点时,我可以只给它作业 ID,然后终止关联的线程。这是一个可行的解决方案还是有更好的方法来处理它?

B.我想实施一个更新策略,让我可以量化工作的整体进度,因此我可以看到工作完成的百分比,而不是仅仅从前端看到 IN PROGRESS 或 PENDING。前端将是一个桌面应用程序,所以最终我想用这个信息来支持一个进度条。但是,我担心性能,因为每次进度增加时我都需要不断地写入作业表,并且当端点检查状态被客户端击中时,我还需要不断地从表中读取(我我每 10 秒左右思考一次)是否有更好的解决方案来根据给定的信息处理这个问题?

如果有任何区别,一次只能处理一项工作......这是针对管理门户的,因此只有少数人可以访问此功能,并且如果特定工作类型已经在进行中,那么在 COMPLETE、CANCELLED 或 FAILED 之前,不允许使用该类型的另一个

【问题讨论】:

  • 如果只有一个线程,不需要存储它的ID。您可以将 正在运行的任务存储在某个单例 bean 中并中断它。如果你的工作运行了 48 小时,那么每 10 秒更新/读取一次它的进度看起来有点过头了。每半小时更新/阅读一次会获得 96 次更新,因此每半小时大约增加 1%。您通常不需要比进度条更好的精度。也就是说,每 10 秒更新/读取一行的一列不会产生任何重大影响。您还可以将进度与您的任务一起保存在内存中。
  • 我真的不明白通过 RabbitMQ 只是为了在同一台服务器上启动一个线程。这似乎也太过分了。如果目标是让它在集群的任何服务器上运行,那么你中断任务的计划就行不通了。
  • 我明白你在说什么,其中很多都是有道理的。我想我需要重新评估如何取消任务。目前我只相信我需要运行一个微服务实例,但我希望这样做的方式是我可以在需要时启动另一个实例并且它仍然可以正常运行。

标签: java rest spring-boot design-patterns microservices


【解决方案1】:

当 API 收到启动作业的请求时,可能的解决方案是返回新创建作业的作业 ID。

拥有另一个端点来跟踪作业的状态并管理其生命周期。类似的东西

/Jobs/Status/<Job-ID> 

GET 将返回当前状态和完成百分比。 DEL 可以停止终止现有的正在运行的作业。

您可以每分钟/10 分钟轮询一次作业的状态。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-13
    • 1970-01-01
    • 1970-01-01
    • 2016-03-23
    • 1970-01-01
    • 1970-01-01
    • 2020-04-26
    相关资源
    最近更新 更多