本文章是在网易云课堂的课程学习中编写,部分图片从网易云课堂ppt引用
一、微服务请求情况
1、请求处理情况
【请求处理】一个请求可能有多个微服务协同处理(相互依赖)
【服务超时】服务可能超时、网络不通,导致调用者出现阻塞
【系统雪崩】请求一旦大量阻塞,会占用大量资源,可能导致整个系统雪崩
2、构建弹性应用
【服务限流】服务消费者限制自身对某一服务能发起的并发请求数量,超过数量则不调用或等一段时间后再调用
【服务熔断】熔断状态下,服务消费者不会发起对某一服务的调用
【服务降级】请求异常情况下,程序执行指定的降级策略(可类比try-catch)
3、spring cloud提供的hystrix
若服务出现超时或其他错误,可以使用【hystrix】来处理
二、集成Hystrix
在《分布式系统开发技术 | Eureka》中代码的基础上,对 【服务消费者】进行改造
1. maven引入
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2. 代码示例
创建一个类CustomerCommand,继承HystrixCommand,重写fallback方法
import com.netflix.hystrix.*;
import org.springframework.web.client.RestTemplate;
/**
* 继承HystrixCommand,重写fallback方法
*/
public class CustomerCommand extends HystrixCommand<Object> {
private RestTemplate restTemplate;
/**
* 重写构造方法,传入我们需要的参数
* @param restTemplate
*/
public CustomerCommand(RestTemplate restTemplate) {
super(
Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("study-hystrix")) //设置命令分组名
.andCommandKey(HystrixCommandKey.Factory.asKey("CustomerController")) //设置命令名,谁发起请求的设置成谁
.andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("studyThreadPool")) //设置线程池名
//设置熔断的参数
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
.withExecutionTimeoutInMilliseconds(100) //超时时间:100毫秒
.withCircuitBreakerSleepWindowInMilliseconds(5000)) //熔断时长:5秒
//设置线程池参数
.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
.withCoreSize(1) //线程池大小
.withMaxQueueSize(2)) //线程池仓库大小
);
this.restTemplate = restTemplate;
}
/**
* 实现run方法
* @return
* @throws Exception
*/
@Override
protected Object run() throws Exception {
//核心实现,调用我们期望调用的方法
System.out.println("当前线程是: "+Thread.currentThread().getName());
Object result = restTemplate.getForObject("http://helloserver",String.class,"");
return result;
}
/**
* 降级方法
* @return
*/
@Override
protected Object getFallback() {
//核心方法,降级之后会实现这个
System.out.println("降级啦。。。");
return "降级了,返回降级";
}
}
改造CustomerController类中的发送请求方法,通过CustomerCommand类去代理相关请求
@RestController
public class CustomerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
LoadBalancerClient loadBalancerClient;
@GetMapping("index")
public Object getIndex(){
return new CustomerCommand(restTemplate).execute();
}
}
这里可以看到,这种请求方式也可以收到应答
我们来尝试让某个服务提供者模拟宕机情况:
@SpringBootApplication
@EnableEurekaClient
@RestController
public class HelloDemoPeer1Application {
public static void main(String[] args) {
SpringApplication.run(HelloDemoPeer1Application.class, args);
}
@GetMapping("")
public Object index() throws InterruptedException {
Random random = new Random();
int timeOut = random.nextInt(150);
System.out.println("当前线程休眠时间是:"+timeOut);
Thread.sleep(timeOut);
String str = "这是服务端1返回的应答";
return new String(str);
}
}
hystrix设置的超时时间是100毫秒,若休眠时间大于100毫秒,则执行fallback