背景
你已经使用了微服务架构。有时服务结合起来处理请求。当一个服务同步条用另一个服务时,总有肯呢个出现其他服务不可用或者出现很高的延迟而基本不可用。前一个服务的资源,比如线程,可能在等待其他服务的响应时被占用。一个服务的失败潜在的级联影响到应用中其他服务的吞吐量。
问题
如何阻止网络或服务的失效级联影响到其他的服务?
限制
解决方案
服务客户端应该通过一层代理访问远程服务,这个店里提供了类似电路断路器的功能。当连续失败的次数超出阈值,断路器跳闸,在一个超时周期范围内所有尝试请求远程服务的请求都快速失败。当超时时间到达后,断路器允许一定数量的测试请求通过。如果这些请求成功,断路器恢复正常操作。否则,如果出现失败,则上述超时周期又重新开始。
示例
微服务示例应用 中的 RegistrationServiceProxy
是一个示例组件,采用Scala编写,使用断路器处理调用远程服务的失败。
@Component
class RegistrationServiceProxy @Autowired()(restTemplate: RestTemplate) extends RegistrationService {
@Value("${user_registration_url}")
var userRegistrationUrl: String = _
@HystrixCommand(commandProperties=Array(new HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="800")))
override def registerUser(emailAddress: String, password: String): Either[RegistrationError, String] = {
try {
val response = restTemplate.postForEntity(userRegistrationUrl,
RegistrationBackendRequest(emailAddress, password),
classOf[RegistrationBackendResponse])
response.getStatusCode match {
case HttpStatus.OK =>
Right(response.getBody.id)
}
} catch {
case e: HttpClientErrorException if e.getStatusCode == HttpStatus.CONFLICT =>
Left(DuplicateRegistrationError)
}
}
}
@HystrixCommand
安排了使用断路器来处理对 registerUser()
的调用。
通过在 UserRegistrationConfiguration
类上添加 @EnableCircuitBreaker
模式,启用断路器功能。
@EnableCircuitBreaker
class UserRegistrationConfiguration {
结果
这个模式有如下优势:
- 服务处理了它们调用远程服务产生的错误
这个模式有如下问题:
- 选择合适的超时时间,不带来误报或引入更多的延迟,是有挑战性的。
相关模式
参见
- Netflix Hystrix 是实现了这个模式的一个示例库
网友评论