断路器设计模式
断路器是一个现代软件开发的设计模式。用以侦测错误,并避免不断地触发相同的错误(如维护时服务不可用、暂时性的系统问题或是未知的系统错误)。
常用时机
假设有个应用程序每秒会与数据库沟通数百次,此时数据库突然发生了错误,程序员并不会希望在错误时还不断地访问数据库。因此会在等待TCP连线逾时之前直接处理这个错误,并进入正常的结束程序(而非直接结束程式)。简单来说,断路器会侦测错误并且“预防”应用程序不断地呼叫一个近乎毫无回应的服务(除非该服务已经安全到可重试连线了)。
概念
断路器有分简单与较进阶的版本,简单的断路器只需要知道服务是否可用。而较进阶的版本比起前者更有效率。进阶的断路器带有至少三个状态:
- 关闭:断路器在预设的情形下是呈现关闭的状态,而断路器本身“带有”计数功能,每当错误发生一次,计数器也就会进行“累加”的动作,到了一定的错误发生次数断路器就会被“开启”,这个时候亦会在内部启用一个计时器,一旦时间到了就会切换成半开启的状态。
- 开启:在开启的状态下任何请求都会“直接”被拒绝并且抛出异常讯息。
- 半开启:在此状态下断路器会允许部分的请求,如果这些请求都能成功通过,那么就意味着错误已经不存在,则会被“切换回”关闭状态并“重置”计数。倘若请求中有“任一”的错误发生,则会回复到“开启”状态,并且重新计时,给予系统一段休息时间。
效能考量
当安全是个益处,效能也就成为了实作断路器的一个负面考量。因为需要不断地检查一个服务是否安全,且服务不仅会有一个,甚至会以多个方向扩展。
实作范例
PHP
下面是一个以 PHP 来实作的范例。这个范例是将一个 MySQL 服务器的可用状态处存进共享记忆体快取(APC)中并在之后以此判断是否可用。
检查
下列脚本能以工作排程来不断地在某时刻执行检查。
$db = mysql_connect('localhost','user','pass');
if ($db === false) {
apc_store('dbUp', '已斷線');
} else {
apc_store('dbUp', '可連線');
@mysql_close($db);
}
在应用程序中使用
if (apc_fetch('dbUp') === '已斷線') {
echo "資料庫目前不可用。請在數分鐘後嘗試。";
exit;
}
$db = mysql_connect('localhost', 'user', 'pass');
$res = mysql_db_query('database', 'SELECT * FROM table');
外部链接
- Example of PHP implementation with diagrams
- Example of C# implementation from Anders Lybeckers using Polly (页面存档备份,存于互联网档案馆)
- Polly NuGet package (页面存档备份,存于互联网档案馆)
- Example of C# implementation from Alexandr Nikitin (页面存档备份,存于互联网档案馆)
- Implementation in Python (页面存档备份,存于互联网档案馆)
- Stability patterns applied in a RESTful architecture (页面存档备份,存于互联网档案馆)