【问题标题】:Error conditions and retries in gearman?gearman 中的错误条件和重试?
【发布时间】:2025-11-21 07:40:02
【问题描述】:

有人可以指导我在出现异常时 Gearman 如何重试 抛出或发生错误时?

我在 Django 应用程序中使用 python gearman 客户端,我的工人是 作为 Django 命令启动。我从这个blog post 读到重试 从错误条件不是直截了当的,它需要 sys.exit 从工作端退出。

此问题是否已修复为使用 sendFail 或 sendException 重试? gearman 也支持使用指数算法重试 - 说如果 SMTP 失败会在 2、4、8、16 秒后重试吗?

【问题讨论】:

  • sys.exit() 对于 Gearman 来说是个坏主意 - 通常它会永远重试任何此类作业(除非您在守护进程启动时设置了作业重试)。只需对作业的任何状态/结果执行return stringvar(例如,键入数据库行或使用真实信息进行缓存。)

标签: gearman


【解决方案1】:

据我了解,Gearman 采用了一种非常“不关我的事”的方法 - 例如,它不会干预执行的工作,除非工人崩溃。任何成功/失败消息都应该由客户端处理,而不是 Gearman 服务器本身。

在前台作业中,这意味着所有sendFail() / sendException() 和其他send*() 都指向客户端,由客户端决定是否重试该作业。这是有道理的,因为有时您可能不需要重试。

在后台作业中,所有send*() 函数都失去了意义,因为没有客户端会监听回调。结果,发送的消息将被 Gearman 忽略。重试作业的唯一条件是工人崩溃(可以通过exit(XX) 命令模拟,其中XX 是一个非零值)。当然,这不是您想要做的事情,因为工作人员通常应该是长时间运行的进程,而不是在每次不成功的作业后必须重新启动的进程。

就我个人而言,我通过扩展默认的 GearmanJob 类解决了这个问题,在该类中我拦截了对send*() 函数的调用,然后自己实现了重试机制。本质上,我将所有与重试相关的数据(最大重试次数、已重试次数)与工作负载一起传递,然后自己处理所有事情。这有点麻烦,但我理解为什么 Gearman 会以这种方式工作 - 它只是允许您处理所有应用程序逻辑。

最后,关于以指数超时(或任何超时)重试作业的能力。 Gearman 具有添加延迟作业的功能(在 protocol documentation 中查找 SUBMIT_JOB_EPOCH),但我不确定它的状态 - PHP 扩展,我认为 Python 模块不支持它,文档说将来可以删除。但我知道它目前有效 - 您只需向 Gearman 提交原始套接字请求即可实现它(并且指数部分也应该在您这边实现)。

但是,this blog post 认为 SUBMIT_JOB_EPOCH 实现不能很好地扩展。他使用 node.js 和 setTimeout() 使其工作,我见过其他人使用 unix 实用程序 at 来做同样的事情。无论如何——Gearman 不会为你做这件事。它将专注于可靠性,但会让您专注于所有逻辑。

【讨论】:

  • 我知道这是对一个老问题的回答,但我看到很多人都在同一个问题上苦苦挣扎,我相信值得一劳永逸地提供完整的图片。