SpringCloud(五):断路器(Hystrix)

一、简介

http://projects.spring.io/spring-cloud/spring-cloud.html#_circuit_breaker_hystrix_clients

Netflix开源了Hystrix组件,实现了断路器模式,SpringCloud对这一组件进行了整合。 在微服务架构中,一个请求需要调用多个服务是非常常见的。

hystrix主要是用来防止服务雪崩效应的。

服务雪崩效应:是一种因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程。

举例:A为服务提供者, B为A的服务调用者, C和D是B的服务调用者. 当A的不可用,引起B的不可用,并将不可用逐渐放大C和D时, 服务雪崩就形成了。

如图一个API可能同时调用多个微服务。

这里写图片描述

较低级别的服务中的服务故障可能导致服务级联故障。当对特定服务的调用达到一定阈值时(Hystrix中的默认值为5秒内的20次故障),断路器打开。

image

断路打开后,回退可以是另一个Hystrix保护的调用,静态数据或一个正常的空值。

二、Ribbon+Hystrix

这里写图片描述

依赖:

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-ribbon</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-hystrix</artifactId>
		</dependency>

application.properties

spring.application.name=hello-consumer-ribbon-hystrix
server.port=8041

eureka.client.serviceUrl.defaultZone=http://localhost:8001/eureka/

HelloService

package cn.saytime.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class HelloService {

	@Autowired
	private RestTemplate restTemplate;

	@HystrixCommand(fallbackMethod = "fallback")
	public String hello (String name) {
		return restTemplate.getForEntity("http://HELLO-SERVICE/hello?name=" + name, String.class).getBody();
	}

	public String fallback (String name) {
		return "hello, hystrix       === fail name:" + name;
	}

}

application

package cn.saytime;

import cn.saytime.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@RestController
public class HelloConsumerRibbonHystrixApplication {

	public static void main(String[] args) {
		SpringApplication.run(HelloConsumerRibbonHystrixApplication.class, args);
	}

	@Bean
	@LoadBalanced
	public RestTemplate restTemplate () {
		return new RestTemplate();
	}

	@Autowired
	private HelloService helloService;

	@RequestMapping("hello")
	public String hello (String name) {
		return helloService.hello(name);
	}

}

测试:

启动eureka-server:8001, hello-service:8012,8002,hello-consumer-ribbon-hystrix:8041

访问:http://localhost:8041/hello?name=ribbon_hystrix

hello, ribbon_hystrix

访问正常,接下来我们把hello-service服务停了,再次访问:

hello, hystrix === fail name:ribbon_hystrix

成功触发熔断。

然后我们再次启动hello-service服务,然后访问:

hello, ribbon_hystrix

没有触发熔断,正常。

同样我们测试访问超时触发熔断的情况,我们在hello-service接口加上线程等待1s

	@RequestMapping("hello")
	public String hello (String name) throws InterruptedException {
		Thread.sleep(1000);
		System.out.println("hello, " + name);
		return "hello, " + name;
	}

访问,发现同样触发熔断,因为hystrix默认超时1s触发熔断,我们可以通过修改属性来改变超时时间。

这里我们把超时时间修改为2s

	@HystrixCommand(fallbackMethod = "fallback", commandProperties = {
			@HystrixProperty(name= "execution.isolation.thread.timeoutInMilliseconds", value="2000")
	})
	public String hello (String name) {
		return restTemplate.getForEntity("http://HELLO-SERVICE/hello?name=" + name, String.class).getBody();
	}

再次访问,发现没有触发熔断。

三、Feign With Hystrix

Feign默认是自带Hystrix的,所以依赖Jar的时候无需再依赖hystrix

这里写图片描述

pom.xml

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-feign</artifactId>
		</dependency>

application.properties

spring.application.name=hello-consumer-feign-hystrix
server.port=8051

eureka.client.serviceUrl.defaultZone=http://localhost:8001/eureka/

## 开启hystrix
feign.hystrix.enabled=true

## hystrix熔断触发默认超时时间
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=2000

HelloService

package cn.saytime.service;


import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(value = "hello-service", fallback = HelloServiceFallBack.class)
public interface HelloService {

    @RequestMapping("hello")
    String hello(@RequestParam(value = "name") String name) ;
}

熔断触发类HelloServiceFallBack

package cn.saytime.service;

import org.springframework.stereotype.Component;

@Component
public class HelloServiceFallBack implements HelloService{

    @Override
    public String hello(String name) {
        return "hello, hystrix      == fail name : " + name;
    }
}

启动类

package cn.saytime;

import cn.saytime.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@RestController
public class HelloConsumerFeignHystrixApplication {

	public static void main(String[] args) {
		SpringApplication.run(HelloConsumerFeignHystrixApplication.class, args);
	}

	@Autowired
	private HelloService helloService;

	@RequestMapping("hello")
	public String hello(String name){
		return helloService.hello(name);
	}
}

测试:

启动eureka-server:8001, hello-service:8011,hello-consumer-feign-hystrix:8051

访问:http://localhost:8051/hello?name=feign_hystrix

hello, feign_hystrix

访问成功

接下来关闭hello-service服务,再次访问:

hello, hystrix == fail name : feign_hystrix

成功触发熔断

将hello-service服务重新启动,访问正常,没有触发熔断。

将hello-service服务接口加上线程等待3s,重启hello-service服务,再次调用

同样成功触发熔断

修改application.properties里面熔断超时时间为4s,再次调用,没有触发熔断。

四、Hystrix Dashboard (Hystrix 仪表盘)

ribbon-hystrix 与 feign-hystrix 两个项目的pom文件都添加以下依赖

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
		</dependency>

启动类都加上如下注解:

@EnableHystrixDashboard

然后访问

http://localhost:8041/hystrix
http://localhost:8051/hystrix

这里写图片描述

输入链接:http://localhost:8041/hystrix.stream

同理,如果是feign-hystrix项目,输入 http://localhost:8051/hystrix.stream

点击Monitor Stream

然后我们访问一下 http://localhost:8041/hello?name=ribbon_hystrix

会出现如下监控界面:

这里写图片描述

具体监控界面内容情况,就不详细描述了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值