Sprint Cloud学习笔记——服务容错保护机制Hystrix

一、前言

以之前的负载均衡的例子为例(具体搭建步骤请参考: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,如图所示:

代码如下:

扫描二维码关注公众号,回复: 6017102 查看本文章
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的响应时间,无法精准的控制这个服务处理数据的具体时间。

猜你喜欢

转载自blog.csdn.net/notMoonHeart/article/details/84956115