前言
大家好,一直以来我都本着用最通俗的话理解核心的知识点, 我认为所有的难点都离不开 基础知识 的铺垫。目前正在出一个SpringCloud
长期系列教程,从入门到进阶, 篇幅会较多~
适合人群
- 有一定的Java基础
- 想尝试微服务开发
- 有SpringBoot开发基础
- 想学习或了解SpringCloud
- 想提高自己的同学
大佬可以绕过 ~
背景
如果你是一路看过来的,很高兴你能够耐心看完。之前带大家学了Springboot
这门框架,熟练掌握了单体应用
的开发,如今微服务
开发盛行,对我们的技术要求也是越来越高,薪资也是令人兴奋。这个系列将会带大家学习SpringCloud
微服务开发,我会带大家一步一步的入门,耐心看完你一定会有收获
~
情景回顾
上期带大家一起认识了如何基于rest的服务远程调用
以及带大家学习了restTemplate
的常见用法,本期带着上期遗留下来的问题学习hystrix
,我们一起来看一下吧~
hystrix 是啥
我们上期结尾的时候提到过服务间调用会产生一些问题,试想一下,会有哪些问题。我们先抛开服务间调用, 拿正常的前端去请求服务端来讲, 有时候我们会发现有的接口会很慢导致接口超时
, 如果服务端或者前端不去处理的话,会一直处于等待
状态, 当大批量的请求过来时,发现服务就被堵在那了,最终导致服务不可用甚至挂掉
。微服务之间调用同样的也会产生这种问题,甚至还会有雪崩效应,因为服务之间都是关联的,那么怎么解决呢?下面就是我要给大家介绍的SpringCloud
的另一个核心组件 Hystrix
同样的,我们先认识一下它是啥?Hystrix
可以让我们对服务间的调用进行控制,提供了容错机制。Hystrix
通过将依赖服务进行资源隔离,进而阻止某个依赖服务出现故障时在整个系统所有的依赖服务调用中进行蔓延;同时Hystrix
还提供故障时的 fallback 降级机制
, 它可以帮助我们提升服务的可用性和稳定性
环境搭建
首先我们新建一个项目模块方便测试, 大家自行创建, 紧接着修改pom.xml
<!-- hystrix--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> 复制代码
- HelloController
@RestController @RequestMapping("/hello") public class HelloController { @Autowired private UserService userService; /** * 服务容错测试 * @return */ @RequestMapping("/hello/user/hyx") @ResponseBody public User hello2() { return userService.hello("HystrixCommand"); } } 复制代码
- User
@Data public class User { private String username; } 复制代码
- UserService
@Service public class UserService { public User hello(String name) { Map<String, Object> params = new HashMap<>(); params.put("name", name); User u = restTemplate.getForObject("http://provider/hello/app/{name}", User.class, params); return u; } } 复制代码
核心部分就是这个UserService
,下面我们看下怎么去使用
常用方法
此外,我们还需要再开启producer
服务(上期中已实现)
服务熔断配置
使用也很简单,只需要指定注解即可,下面给大家介绍常用的配置
@HystrixCommand( commandProperties= { @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "5000"), // 如果5秒内,请求达到了4个,错误率达到50%以上,就开启跳闸, @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "4"), @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"), // 如果3秒以后再调用,会再执行一次业务方法 // 就会直接走fallback,业务代码将不再会调用 @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "3000"), // 信号隔离设置 - 在主线程执行 //只需要设置execution.isolation.strategy = SEMAPHORE即可 // 并设置并发数 @HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE"), @HystrixProperty(name="execution.isolation.semaphore.maxConcurrentRequests", value="10") } ) public User hello(String name) { Map<String, Object> params = new HashMap<>(); params.put("name", name); User u = restTemplate.getForObject("http://provider/hello/app/{name}", User.class, params); return u; } 复制代码
服务降级配置
@HystrixCommand( // 设置回调 - 请求错误时回调 // 还可以对降级的服务进行分组 fallbackMethod = "getUserDefault", commandKey = "getUserById", groupKey = "userGroup", threadPoolKey = "getUserThread", commandProperties= { @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "5000"), // 如果5秒内,请求达到了4个,错误率达到50%以上,就开启跳闸, @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "4"), @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"), // 如果3秒以后再调用,会再执行一次业务方法 // 就会直接走fallback,业务代码将不再会调用 @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "3000"), // 信号隔离设置 - 在主线程执行 //只需要设置execution.isolation.strategy = SEMAPHORE即可 // 并设置并发数 @HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE"), @HystrixProperty(name="execution.isolation.semaphore.maxConcurrentRequests", value="10") } ) public User hello(String name) { Map<String, Object> params = new HashMap<>(); params.put("name", name); User u = restTemplate.getForObject("http://provider/hello/app/{name}", User.class, params); return u; } // 如果该方法抛出错误 就会降级到 getUserDefault1 , 也可以通过 ignoreExceptions 去忽略某些异常 @HystrixCommand(fallbackMethod = "getUserDefault1", ignoreExceptions = {NullPointerException.class}) public User getUserDefault(String name, Throwable e) { // 获取异常信息 System.out.println(e.getMessage()); // 测试服务降级 - 该方法会错误 回调 getUserDefault1 // String a = null; // a.toString(); User user = new User(); user.setUsername("defaultUser"); return user; } public User getUserDefault1(String name) { User user = new User(); user.setUsername("defaultUser 1"); return user; } 复制代码
结束语
本期到这里就结束了, 总结一下,本节主要讲了,服务之间如何进结合hystrix
进行降级和熔断处理,其实yml
中也可以做一些配置,这个留给大家自己实践了, 建议大家自己多去尝试 ~
下期预告
我们知道,微服务场景下,服务不可能就跑一个,需要结合应用场景来跑多个,那么如何去做负载均衡呢❓。 下期,给大家讲另外一个组件 ribbon
, 关注我,不迷路, 下期不见不散 ~