熔断器/断路器是用来处理重复性故障的一种模式。它保护微服务免受反复调用失败的服务的困扰。断路器是管理交互的三态自动机(图4-4)。它从一个关闭(closed)的状态开始,在这个状态中断路器执行正常的操作。如果交互成功,则什么也不会发生。然而,如果它失败了,断路器会记录下故障。一旦故障数量(在更复杂的情况下可以是故障频率)超过了阈值,断路器就会切换到一个开放(open)状态。在这种状态下,对断路器的调用会立即失败,而不会试图执行与底层的交互。虽然不执行对底层的调用操作,但是断路器可能执行回退(fallback),即提供一个默认的结果。经过配置的一段时间后,断路器认为现在操作有可能会成功,所以它进入半开放(half-open)状态。在这个状态下,对断路器的下一个调用执行底层的交互。根据这个调用的结果,断路器重新设置并返回到关闭(close)状态,或返回到开放(open)状态,直到另一个超时结束。
图4 -4: 断路器状态
Java最知名的断路器实现是Hystrix(https://github.com/Netflix/Hystrix\)。尽管你可以在一个Vert.x微服务中使用Hystrix\(它使用一个线程池\),但是您需要显式地切换到Vert.x的事件回环来执行不同回调。或者,你也可以使用Vert.x为异步操作而构建的断路器,并强制实施Vert.x非阻塞异步开发模型。
让我们想象一个失败的hello microservice。消费者应保护与此服务的交互,并使用断路器如下:
CircuitBreaker circuit = CircuitBreaker.create("my-circuit",
vertx, new CircuitBreakerOptions()
.setFallbackOnFailure(true) // Call the fallback
// on failures
.setTimeout(2000) // Set the operation timeout
.setMaxFailures(5) // Number of failures before
// switching to
// the 'open' state
.setResetTimeout(5000) // Time before attempting
// to reset
// the circuit breaker
);
// ...
circuit.rxExecuteCommandWithFallback(
future ->
client.get(path)
.rxSend()
.map(HttpResponse::bodyAsJsonObject)
.subscribe(future::complete, future::fail),
t -> new JsonObject().put("message", "D'oh! Fallback")
).subscribe(
json -> {
// Get the actual json or the fallback value
System.out.println(json.encode());
}
);
在此代码中,HTTP交互受断路器保护。当故障数量达到配置的阈值时,断路器将停止调用微服务,转而调用一个fallback。周期性地,断路器会让一个调用通过断路器,检查微服务是否回到正轨并相应地采取行动。这个例子使用一个web客户端,但是任何交互都可以通过一个断路器进行管理,并保护您不受不稳定的服务、异常和其他类型的故障的影响。
切换到开放(open )状态的断路器需要由您的运营团队来监控。Hystrix 和Vert.x的断路器都有监控能力。