一、前言
以之前的负载均衡的例子为例(具体搭建步骤请参考:https://blog.csdn.net/notMoonHeart/article/details/84954217),在服务注册中心注册了两个服务,假如此时把server1关闭(粗暴的把server1干掉),再次访问,则会导致无法返回请求信息。在实际生产上,有可能是高并发,网络慢等等原因导致自身服务响应慢,从而影响整个系统的正常运行。为了解决这种问题,Spring Cloud利用一种叫做短路器的东西来解决这种问题。
那么什么叫断路器呢,举个例子,假如在家庭电路中,某电器发生了短路问题,而引起空气开关跳闸。那么这个空气开关的作用就是断路器的作用。
个人理解:其实就是在客户端发送请求时,服务端长时间不响应,客户端见此状况自主触发的一种保护机制。下面通过简单的例子来说明。
二、断路器保护机制的demo
1.我们再之前负载均衡的例子上加以改造,依然是一个服务注册中心,两个服务端,和一个客户端(具体步骤参考前言中出现的链接)
2.在客户端(作者这里的客户端工程名为hello-client)pom.xml文件中增加jar包的依赖,详细配置如下:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
这里加入到dependencies标签中即可,版本最好与cloud版本保持一致(作者并不知道其他版本会不会有问题,有兴趣的小伙伴可以尝试研究一下)
3.在客户端中增加一个java类,命名HelloService.java,如图所示:
代码如下:
package com.example.client.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
//这里的fallbackMethod的值要和方法名保持一致
@HystrixCommand(fallbackMethod="helloFallback")
public String helloService() {
return restTemplate.getForEntity("http://hello-service/hello", String.class).getBody();
}
public String helloFallback() {
return "error";
}
}
3.修改ClientController.java中的代码,修改后的代码如下:
package com.example.client.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class ClientController {
@Autowired
RestTemplate restTemplate;
@Autowired
HelloService helloService;
@RequestMapping(value="/ribbon-client",method=RequestMethod.GET)
public String helloTemplate() {
return helloService.helloService();
}
}
4.在启动类中加入断路器注解,代码如下:
package com.example.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
//断路器功能
@EnableCircuitBreaker
@SpringBootApplication
@EnableDiscoveryClient
public class HelloClientApplication {
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(HelloClientApplication.class, args);
}
}
5.按顺序分别启动服务注册中心,两个服务端,客户端,然后访问http://localhost:9100/ribbon-client
这时候会发现可以正常访问,并返回服务端返回的结果。
然后我们粗暴的干掉其中的一个server,再访问http://localhost:9100/ribbon-client,会发现当访问到我们干掉的那个服务时,不会报错了,而会出现我们定义的错误结果,如图:
6.接下来模拟请求响应超级慢的场景
①首先在服务端地方加入线程等待,模拟网络超时,修改server端中Contronller类(作者这里是HelloController.java),代码如下:
package com.example.demo.controller;
import java.util.Random;
import java.util.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
private final Logger logger = Logger.getLogger("HelloController");
@Autowired
private Registration registration;// 服务注册
@RequestMapping(value="/hello")
public String index() throws InterruptedException {
//等待,模拟访问时间过长,进程挂起的情况,hystrix的默认响应时间是1000毫秒
int sleepTime = new Random().nextInt(3000);
logger.info("sleepTime:"+sleepTime);
Thread.sleep(sleepTime);
return "hello server1";
}
}
②然后再重新启动服务端,接着访问http://localhost:9100/ribbon-client,通过观察日志得知,当时间小于1000毫秒的时候,是可以正常返回信息的,当大于1000毫秒的时候会返回error(作者这里亲测是1000毫秒,但是有的版本说是2000毫秒,作者不知)
遗留问题:作者这里有个问题,如果是这样引发的断路器机制那么,实际上服务端是在处理数据的,当服务端在处理数据时客户端以及返回了一个错误信息,那么服务端处理的数据还有意义吗?怎么样才能控制这种情况,让客户端多等待一会,等待数据的生成。如果设置hystrix的响应时间,无法精准的控制这个服务处理数据的具体时间。