我使用Sidekiq队列来处理与不可靠的第三方API的通信。由于这个API通常会一次停机几分钟然后再次备份,所以Sidekiq非常方便。当发生连接问题时,会引发错误,并且Sidekiq会在一段时间过后将作业重新放回队列中以便稍后再次重试。
我使用NewRelic不仅可以帮助调试崩溃,还可以用于监控。我的问题是上面这个当前的方法在NewRelic中创建了错误。如果第三方API停机超过几分钟,则错误计数会累积到足以导致通过NewRelic发送通知。
我想做的只是在工作发生一定次数的重试时,从我的工作人员那里提出错误。我正在使用sidekiq_retries_exhausted
来执行此操作。我的问题是,我不太确定如何在没有引发错误的情况下将作业放回队列中。
Sidekiq是否提供了将作业返回到队列的任何工具,增加了作业的重试次数,并让它坐在那里直到它再次运行,就好像在工人类中引发了异常一样?
答案 0 :(得分:3)
您引发特定错误并告诉错误服务忽略该类型的错误。对于NewRelic:
答案 1 :(得分:1)
如果使用 Sidekiq Enterprise,另一种选择可能是使用一组可选的附加错误类型,这些类型将被视为 Sidekiq::Limiter::OverLimit
违规。
出于我的目的,我使用了一个新的错误类,然后将其添加到配置中的列表中。以下是 sidekiq-ent 代码(不在公共 sidekiq 存储库中)中关于如何修改配置文件的注释:
# An optional set of additional error types which would be
# treated as a rate limit violation, so the job would automatically
# be rescheduled as with Sidekiq::Limiter::OverLimit.
#
# Sidekiq::Limiter.errors << MyApp::TooMuch
# Sidekiq::Limiter.errors = [Foo::Error, MyApp::Limited]
在特定作业 you can specify the max_retries 内,否则将默认为 20:
sidekiq_options max_limiter_retries: 10
在工作中,我将挽救我不想完全忽略的“预期”间歇性错误,然后提出我已添加到列表中的错误,如下所示:
rescue RestClient::RequestTimeout => e
raise SidekiqSoftRetry.new(e.inspect)
end
这是我的初始化文件中的样子 - Mike Perham kind enough to respond 可以选择更新全局重试限制。
class SidekiqSoftRetry < RuntimeError
end
Sidekiq::Limiter::DEFAULT_OPTIONS[:reschedule] = 10
Sidekiq::Limiter.configure do |config|
config.errors.concat(
[
SidekiqSoftRetry,
]
)
end
答案 2 :(得分:0)
以下是我为AirBrake保留故意重试错误所做的工作:
+ curl https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py -O
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
^M 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0^M100 56093 100 56093 0 0 56093 0 0:00:01 --:--:-- 0:00:01 98929
+ chmod +x ./awslogs-agent-setup.py
+ ./awslogs-agent-setup.py -n -c /etc/awslogs/awslogs.conf -r us-west-2
Step 1 of 5: Installing pip ...^[[0mlibyaml-dev does not exist in system ^[[0m^[[92mDONE^[[0m
Step 2 of 5: Downloading the latest CloudWatch Logs agent bits ... ^[[0mTraceback (most recent call last):
File "./awslogs-agent-setup.py", line 1317, in <module>
main()
File "./awslogs-agent-setup.py", line 1313, in main
setup.setup_artifacts()
File "./awslogs-agent-setup.py", line 858, in setup_artifacts
self.install_awslogs_cli()
File "./awslogs-agent-setup.py", line 570, in install_awslogs_cli
subprocess.call([AWSCLI_CMD, 'configure', 'set', 'plugins.cwlogs', 'cwlogs'], env=DEFAULT_ENV)
File "/usr/lib/python2.7/subprocess.py", line 168, in call
return Popen(*popenargs, **kwargs).wait()
File "/usr/lib/python2.7/subprocess.py", line 390, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1025, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
告诉Airbrake忽略它:
class TaskWorker
include Sidekiq::Worker
class RetryNotAnError < RuntimeError
end
def perform task_id
task = Task.find(task_id)
task.do_cool_stuff
if task.finished?
@log.debug "Task #{task_id} was successful."
return false
else
@log.debug "Task #{task_id} will try again later."
raise RetryNotAnError, task_id
end
end
end
最好使你的异常名称显然不是一个错误(例如RetryLaterNotAnError),因为它仍然会出现在日志中等等,并且当你看到很多人时你不想让人们知道。
PS。也就是说,我真的喜欢看Sidekiq提供一个明确的,无错误的重试机制。