SpringCloud教程 | 五.断路器(hystrix)【基于ribbon和feign】

本文介绍微服务架构中常见的“雪崩”效应,并通过实战演示如何利用Spring Cloud中的Hystrix断路器来解决这一问题。分别展示了基于Ribbon和Feign两种方式的配置与实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以相互调用(RPC),在Spring Cloud可以用RestTemplate+Ribbon和Feign来调用。为了保证其高可用,单个服务通常会集群部署。由于网络原因或者自身的原因,服务并不能保证100%可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。

为了解决这个问题,业界提出了断路器模型。



较底层的服务如果出现故障,会导致连锁故障。当对特定的服务的调用的不可用达到一个阀值(Hystric 是5秒20次) 断路器将会被打开。



分类

1.基于ribbon

2.基于feign


实战一

首先我们来看下基于ribbon的实战

一.环境准备

1.启动服务注册中心:spring-cloud-eureka
2.启动服务提供方:spring-cloud-eureka-client【端口为2002】

3.基于SpringCloud教程 | 三.服务消费者(Ribbon)



二.调整项目

1.调整项目spring-cloud-eureka-ribbon,在对应的pom中加入spring-cloud-starter-hystrix的起步依赖

【注意】除了加上上面说的hystrix依赖外还需要添加如下依赖【务必注意依赖版本,最开始我用的是1.8.3(默认就是),结果报错】:

<dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.7.1</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.7.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
        </dependency>

pom.xml:

<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.9.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<spring-cloud.version>Edgware.SR1</spring-cloud.version>
	</properties>

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

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>
		<dependency>
	       <groupId>org.springframework.cloud</groupId>
	       <artifactId>spring-cloud-starter-eureka</artifactId>
	   </dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
		    <groupId>org.springframework.cloud</groupId>
		    <artifactId>spring-cloud-starter-hystrix</artifactId>
		</dependency>
		<dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.7.1</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.7.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
        </dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

2.application.properties

server.port=8764
spring.application.name=eureka-ribbon
eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/

3.启动类上使用@EnableCircuitBreaker注解开启断路器功能:

package com.aikucun;

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;

@EnableDiscoveryClient
@SpringBootApplication
@EnableCircuitBreaker
public class SpringCloudEurekaRibbonApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringCloudEurekaRibbonApplication.class, args);
	}
	
	@Bean
	@LoadBalanced
	RestTemplate restTemplate() {
		return new RestTemplate();
	}
}

4.修改service,在使用ribbon消费服务的函数上增加@HystrixCommand注解来指定回调方法

当服务提供者挂了之后会自动返回sorry,error

package com.aikucun.service;

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;

/** 
* @FileName TestService.java
* @Description:TODO
* @author JackHisen(gu.weidong)
* @version V1.0
* @createtime 2018年1月18日 上午10:25:51 
* 修改历史:
* 时间           作者          版本        描述
*====================================================  
*/
@Service
public class TestService {
	@Autowired
    RestTemplate restTemplate;
	
	@HystrixCommand(fallbackMethod="hiError")
    public String hiService() {	
        return restTemplate.getForObject("http://EUREKA-CLIENT/dc",String.class);
    }
	
	public String hiError() {
		return "sorry,error";
	}
}

5.controller不变

package com.aikucun.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.aikucun.service.TestService;

/** 
* @FileName TestController.java
* @Description:TODO
* @author JackHisen(gu.weidong)
* @version V1.0
* @createtime 2018年1月21日 下午1:08:26 
* 修改历史:
* 时间           作者          版本        描述
*====================================================  
*
*/
@RestController
public class TestController {
	@Autowired
	TestService testService;
	
	@RequestMapping("/hi")
	public String testController() {
		return testService.hiService();
	}
}


6.服务提供者没挂的时候正常显示,挂了之后就熔断并且显示默认值


挂掉后:



-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


基于Feign使用Hystrix

注意这里说的是“使用”,没有错,我们不需要在Feigh工程中引入Hystix,Feign中已经依赖了Hystrix。

一.环境准备

1.启动服务注册中心:spring-cloud-eureka
2.启动服务提供方:spring-cloud-eureka-client【端口为2002】

3.基于 SpringCloud教程 | 四.服务消费者(Feign)


二.调整项目

1.调整项目spring-cloud-eureka-feign,对应的pom.xml如下

<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.9.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<spring-cloud.version>Edgware.RELEASE</spring-cloud.version>
	</properties>

	<dependencies>
		<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>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


2.application.properties

【注意】:如下图所示,feign.hystrix.enabled在不设置的情况下默认是false,所以这边需要设置一下,否则熔断器无效


eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka
server.port=8000
feign.hystrix.enabled=true
spring.application.name=eureka-feign

3.启动类

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;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class SpringCloudEurekaFeignApplication {
	public static void main(String[] args) {
		SpringApplication.run(SpringCloudEurekaFeignApplication.class, args);
	}
}

4.service层

接口:

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import com.aikucun.service.ComputeClientHystrix;

/** 
* @FileName TestService.java
* @Description:TODO
* @author JackHisen(gu.weidong)
* @version V1.0
* @createtime 2018年1月22日 上午10:29:54 
* 修改历史:
* 时间           作者          版本        描述
*====================================================  
*
*/
@FeignClient(value = "eureka-client", fallback = ComputeClientHystrix.class)
public interface TestService {
	@RequestMapping("/dc")
	public String testFeign();
}

实现类:
【注意】:此处一定要加上@Component注解
import org.springframework.stereotype.Component;
import com.aikucun.feign.TestService;
/** 
* @FileName ComputeClientHystrix.java
* @Description:TODO
* @author JackHisen(gu.weidong)
* @version V1.0
* @createtime 2018年1月22日 下午5:32:29 
* 修改历史:
* 时间           作者          版本        描述
*====================================================  
*
*/
@Component
public class ComputeClientHystrix implements TestService {
	@Override
	public String testFeign() {
		return "------------------------------------------Feign-Error";
	}
}

5.controller
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.aikucun.feign.TestService;
/** 
* @FileName TestFeignController.java
* @Description:TODO
* @author JackHisen(gu.weidong)
* @version V1.0
* @createtime 2018年1月22日 上午10:32:52 
* 修改历史:
* 时间           作者          版本        描述
*====================================================  
*
*/
@RestController
public class TestFeignController {
	@Autowired
	private TestService testService;
	@RequestMapping("/feign")
	public String testFeignController() {
		return testService.testFeign();
	}
}


6.测试结果
依次开启注册中心,服务提供者,服务消费者
在地址栏输入:http://localhost:8000/feign

关闭服务提供者,出现下图提示,熔断器生效



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东天里的冬天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值