重试模式 Retry Pattern
描述
应用程序请求服务或资源时,因为某些原因发生瞬时故障,应用程序可以通过透明的方式重试失败的操作来处理故障。
背景和问题
应用程序在云环境运行的时候可能会发生瞬间的故障导致服务不可用或请求超时。
这些故障一般是可以自动矫正的,延时重试也可能会成功的。
例如数据库服务,在连接数过多的情况下实现节流策略,暂时拒绝连接,到正常的情况下,重新连接即可。
解决方案
重试机制。
注意事项
- 如果故障不是瞬时的,重复多少次都不会成功的。
- 网络或服务可能在短时间被纠正,应用程序需要选择一个适合的等待时间。
- 等待时间可以使用的定时策略。如果尝试了最大尝试次数还是没有请求成功,应用程序应将故障设置为异常,并相应地处理它。
- 设置重试策略。例如最大3次重试,每次重试的延迟间隔时间指数增加。
- 重试的操作需要幂等。要考虑重试和事务之间的关系。
- 确保所有重试代码是完全针对各种故障条件下进行测试。
- 重试不能影响性能。
- 要尽量避免一个重试任务中调用另外重试任务的嵌套情况。
- 所有的故障都要记录。
何时使用
应用程序发生短暂的故障
结构中包含的角色
- Service 服务
- Application 应用程序
- RetryProxy 重试代理
可用到的设计模式思维
重试模式只是在原本业务的基础上增加一个重试的次数。可以使用代理模式处理。
最小可表达代码
class Service
{
public function debug()
{
var_dump('test...');
return rand(0, 1);
}
}
class Application
{
// 模拟请求
public function request()
{
return (new Service)->debug();
}
}
class RetryProxy
{
private $retryCount = 3;
private $application;
public function __construct()
{
$this->application = new Application();
}
public function request()
{
for ($currentRetry = 1 ; $currentRetry <= $this->retryCount; $currentRetry ++) {
if ($status = $this->application->request()) {
var_dump("请求成功");
break;
}
var_dump("请求失败,{$currentRetry}秒后重试...");
sleep($currentRetry); // 休眠。每次失败的等待时间间隔要比上次的长。
}
}
}
(new RetryProxy)->request();
推荐文章: