有人可以指导我在抛出异常或发生错误时如何重试 Gearman 吗?
我在 Django 应用程序中使用 python gearman 客户端,我的工作人员作为 Django 命令启动。我从这篇博客文章中读到,从错误条件中重试并不是直截了当的,它需要 sys.exit 从工作人员端。
是否已修复此问题以使用 sendFail 或 sendException 重试?gearman 也支持使用指数算法重试——比如 SMTP 失败是否在 2、4、8、16 秒后重试等?
据我了解,Gearman 采用了一种非常“不关我的事”的方法——例如,它不会干预执行的工作,除非工人崩溃。任何成功/失败消息都应该由客户端处理,而不是 Gearman 服务器本身。
在前台作业中,这意味着所有sendFail()
/sendException()
和 othersend*()
都指向客户端,由客户端决定是否重试该作业。这是有道理的,因为有时您可能不需要重试。
在后台作业中,所有send*()
函数都失去了意义,因为没有客户端会监听回调。结果,发送的消息将被 Gearman 忽略。重试作业的唯一条件是工人崩溃(可以通过exit(XX)
命令模拟,其中XX
是非零值)。当然,这不是您想要做的事情,因为工作人员通常应该是长时间运行的进程,而不是在每次不成功的工作后必须重新启动的进程。
就个人而言,我通过扩展默认的 GearmanJob 类解决了这个问题,我在其中拦截对send*()
函数的调用,然后自己实现重试机制。本质上,我将所有与重试相关的数据(最大重试次数、已重试次数)与工作负载一起传递,然后自己处理所有事情。这有点麻烦,但我理解为什么 Gearman 会这样工作——它只允许您处理所有应用程序逻辑。
最后,关于重试具有指数超时(或任何超时)的作业的能力。Gearman 具有添加延迟作业的功能(SUBMIT_JOB_EPOCH
在协议文档中查找),但我不确定它的状态 - PHP 扩展,我认为 Python 模块不支持它,文档说它可以在未来。但我知道它目前有效 - 您只需向 Gearman 提交原始套接字请求即可实现它(并且指数部分也应该在您这边实现)。
但是,这篇博文认为 SUBMIT_JOB_EPOCH 实现不能很好地扩展。他使用 node.js 并setTimeout()
使其工作,我看到其他人使用 unix 实用程序at
来做同样的事情。无论如何——Gearman 不会为你做这件事。它将专注于可靠性,但会让您专注于所有逻辑。