15.2 定义断路器
在声明断路器之前,您需要为服务添加 Spring Cloud Netflix Hystrix 的依赖。在 Maven pom.xml 中的依赖项如下所示:
作为 Spring Cloud 组件的一部分,您还需要声明依赖管理。在我写这篇文章的时候,最新的发布版本为 Finchley.SR1。因此,Spring Cloud 的版本应该设置一下,以下条目应出现在 pom.xml 文件的 <dependency-Management>
部分:
注意,创建项目时在 Initializr 中也可以通过勾选 Hystrix 复选框来添加依赖。如果使用 Initializr 将 Hystrix 添加到项目中,则依赖管理部分会自动为您创建好。
有了 Hystrix 依赖,接下来需要做的就是启用 Hystrix。这通过对每个应用程序的主配置添加 @EnableHystrix
注解来实现。例如,要在 ingredient 服务中启用 Hystrix,您可以这样注解 IngredientServiceApplication 类:
此时,应用程序中启用了 Hystrix,但这只意味着可以声明断路器了。您还没有在任何一个方法上声明使用断路器。这就要通过使用 @HystrixCommand
注解来实现。
任何用 @HystrixCommand
注解的方法都将被声明为具有断路器切面。例如,考虑下面这个方法,使用负载平衡的 RestTemplate 从 ingredient 服务查询 Ingredient 实体:
对 exchange()
的调用可能会引起问题。如果没有在 Eureka 中注册 ingredient-service
,或者由于一些原因请求失败了,那么将抛出 RestClientException
异常(未检查的异常)。因为异常没有使用 try/catch
处理,调用方必须处理这个异常。如果调用方不处理,那么它将继续向上抛出到调用堆栈的上游。如果上游也没有处理,错误就会级联抛出到任何上游微服务或客户端。
未捕获的异常在任何应用程序中都是一个挑战,在微服务中尤其如此。当涉及到失败时,微服务应该遵循维加斯规则——发生在微服务中的,只停留在微服务中。在 getAllIngredients()
方法上声明断路器以满足该规则。
您只需要对方法添加 @HystrixCommand
注解,然后提供一个降级方法。首先,让我们将 @HystrixCommand
添加到 getAllIngredients()
方法上:
有一个断路器保护它不发生故障,现在 getAllIngredients()
方法是故障安全的。无论出于何种原因,从 getAllIngredients()
中抛出未捕获的异常,断路器都将捕获它们,并将方法调用重定向到 getDefaultIngredients()
方法。
降级方法可以做任何您想让他们做的事情,但是目的是,在最初使用的方法无法使用时,提供备份行为。降级方法的唯一规则是它要具有与原方法相同的签名(除了方法名)。
要满足此要求, getAllIngredients()
方法必须也没有请求参数,并返回 List<Ingredient>
。getAllIngredients()
满足该规则并返回默认列表数据:
现在,如果 getAllIngredients()
方法失败了,断路器将调用 getDefaultIngredients()
,调用者将收到一个默认列表。
您可能想知道降级方法本身是否有断路器。尽管上面的 getDefaultIngredients()
实现不会出什么问题,但有可能其他实现会有潜在的失败点。在这种情况下,您可以为 getDefaultIngredients()
添加 @HystrixCommand
,并提供另一个降级方法。事实上,如果需要,您可以堆叠尽可能多的降级方法。唯一的限制是在降级的底部,必须有一个方法不发生故障且不再需要断路器的堆栈。
最后更新于