借助微服务架构,我们可以构建灵活且可独立部署的软件模块或系统,这些模块或系统通过HTTP资源API等轻量机制相互通信并提供结果。与单一应用程序相比,它具有许多优势,因为许多应用程序正在转向云。马丁和詹姆斯在其网站上写了一篇很好的文章,“ 微服务“,我想你们会喜欢阅读。
作为企业分布式应用的一个特征,微服务架构中可以有多层服务调用。在下面的图表分析部分会帮助你有更多的想法。
我已经创建了一个简单的例子来编排你可以在GitHub上找到的微服务架构。
现在,如果由于网络故障或超时问题导致一个或多个服务停机或该特定服务中出现异常,该怎么办?由于在多个层上存在服务调用,因此在分布式系统上常见的是远程服务可能失败。这种故障可能级联到最终到达用户的层。
为了优雅地处理这种故障,我们需要有一种机制可以回退到其他服务调用或默认服务,以便错误的级联停止,用户不需要遇到系统故障。情况如下所示(来源:Spring Cloud Netflix):
使用回退防止错误级联。
现在,作为开发人员,我们不需要担心创建后备,因为我们有Netflix Hystrix。感谢Netflix开发出如此强大而精彩的容错库。
Netflix的Hystrix库实现了断路器设计模式,这意味着如果方法调用失败并且失败构建到阈值,Hystrix将打开电路,以便后续调用自动失败。当电路打开时,Hystrix重定向调用方法,并将它们传递给我们指定的回退方法。
我将使用MovieAPI作为我的远程服务,我在之前的文章“ 使用HATEOAS使你的应用程序更加丰富 ”中提到过。
我在我的例子中使用过Feign作为休息客户端。因此,要使用Hystrix启用断路器模式,只需在Spring Boot应用程序中添加依赖项和注释即可。
build.gradle
compile('org.springframework.cloud:spring-cloud-starter-hystrix')
ClientAppApplication.java
@EnableFeignClients(basePackages = {"com.eprogrammerz.examples"})
@EnableCircuitBreaker
@SpringBootApplication
public class ClientAppApplication {
public static void main(String[] args) {
SpringApplication.run(ClientAppApplication.class, args);
}
}
现在,Feign Rest客户端是:
@FeignClient(name = "movie-api", fallback = MovieApiFallback.class)
public interface MovieApi {
@RequestMapping(method = RequestMethod.GET, value = "/movies/{id}")
Movie getMovie(@PathVariable("id") Long id);
}
在这里,我创建了一个回退逻辑,如MovieApiFallback.class,如下所示:
@Component
public class MovieApiFallback implements MovieApi {
@Override
public Movie getMovie(@PathVariable("id") Long id) {
return new Movie("Avatar", "James Camerson", "8/10");
}
}
每当对/ movies / {id}的远程调用失败时,将调用fallback方法(具有相同名称且具有相同的参数以及接口中的返回类型)并返回静态响应。在实际情况中,您可以将服务调用重定向到其他服务。如果我们已经实现了:),您也可以从缓存中返回响应。您可以在此处找到使用Redis缓存的示例。
为了使示例更完整,我也希望包含服务和控制器层。
MovieService.java
@Service
public class MovieService {
@Autowired
MovieApi movieApi;
public Movie findMovie(Long id){
Movie movieOfTheDay = movieApi.getMovie(id);
return movieOfTheDay;
}
}
MovieController.java
@RestController
@Slf4j
public class RequestController {
@Autowiredprivate MovieService movieService;
@RequestMapping("/recommended")
public ResponseEntity<Movie> getRecommendedMovie(){
long movieOfTheDayId = getLuckyMovieId();
log.info("Calling MovieService:findMovie({})", movieOfTheDayId);
Movie movieRecommended = movieService.findMovie(movieOfTheDayId);
return new ResponseEntity<>(movieRecommended, HttpStatus.OK);
}
/**
* Helper method to provide the random long number
* @return long number between 1200 and 1
*/
private long getLuckyMovieId(){
return (int)(new Random().nextDouble() * 4) + 1200;
}
}
同时运行'movie-api'和'client-app',您将在'client-app'上的不同呼叫中获得不同的响应。对调用http://localhost:8082/recommended
的一个特别回应是:
{
"name": "In Search of Lost Time",
"directorName": "Marcel Proust",
"rating": "3.5/5"
}
现在,让我们通过停止'movie-api'来模拟远程呼叫失败。然后你也会收到回复,但这次是从后备回复:
{
"name": "Avatar",
"directorName": "James Camerson",
"rating": "8/10"
}
关于我在Hystrix库中应用程序可靠性的工作经验,还有很多我想提到的,我想在后面的文章中继续介绍。
但要点的是,Netflix Hystrix提供了最简单的方法来防止应用程序失败,只需要一些注释。不是很酷吗?
原文标题《Defend Your Application With Netflix Hystrix》
作者:Yogen Rai
译者:February
不代表云加社区观点,更多详情请查看原文链接
本文系外文翻译,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系外文翻译,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。