微服务服务降级与熔断

目录

1:服务降级

1.1 feign实现服务降级

1.2 Hystrix实现服务降级

2:服务熔断

2.1 熔断机制

2.2 Consumer侧引入pom

2.3 在Consumer侧启动类开启熔断

2.4 在Consumer侧编写熔断方法及配置

2.5 Provider服务概述


1:服务降级

1.1 feign实现服务降级

Spring Cloud 中,Feign默认整合了Hystrix,所以只需要在配置中启用Hystrix即可,如下是在application.yml中的配置:

feign:
  hystrix:
      enabled: true 

feign实现回退方法有两种方式:fallback,FallbackFactory,其不能同时使用,只能用其中的一种。(1.1章节中的代码,延用了上一文章《声明式服务调用的实现(Feign)及其优化(Ribbon)》中的consumer,Controller api ) 

1.1.1 fallback方法回退

编写一个Feign Client的实现类,且在@FeignClient的fallback属性指定对应的类:


@Component
public class ErrorFallback implements BookConsumerControllerInterface {

	@Override
	public List<Book> getBookList() {
		List<Book> booklist = new ArrayList<Book>();
		Book book = new Book();
		book.setId(404);
		book.setAuthor("error");
		book.setBookName("Error Fallback");
		booklist.add(book);
		return booklist;
	}
	@Override
	public Book getBook(Integer id) {
		Book book = new Book();
		book.setId(id);
		book.setAuthor("error");
		book.setBookName("error name");
		return book;
	}
	@Override
	public Book getBook(Book book) {
		return book;
	}
	@Override
	public Book getBook(Integer id, String bookName, String author) {
		Book book = new Book();
		book.setId(id);
		book.setAuthor(bookName);
		book.setBookName(author);
		return book;
	}
	@Override
	public Book addBook(Book book) {
		return book;
	}

}

在@FeignClient的fallback属性指定对应的类 

@FeignClient(name="bookshop-service-provider" ,fallback=ErrorFallback.class)
public interface BookConsumerControllerInterface extends BookController {

}

1.1.2 FallbackFactory方法回退

如下图,是Feign client及FallbackFactory接口的继承与实现关系,需要额外提出的是,本次代码中没有额外的实现BookConsumerControllerInterface接口类,而是以类中类在ErrorFallbackFactory类中实现。

 实现FallbackFactory<BookConsumerControllerInterface>类:

@Component()
public class ErrorFallbackFactory implements FallbackFactory<BookConsumerControllerInterface> {
	@Override
	public BookConsumerControllerInterface create(Throwable arg0) {
		
		return new BookConsumerControllerInterface() {
			@Override
			public List<Book> getBookList() {
				List<Book> booklist = new ArrayList<Book>();
				Book book = new Book();
				book.setId(404);
				book.setAuthor("error");
				book.setBookName("error name");
				booklist.add(book);
				return booklist;
			}
			@Override
			public Book getBook(Integer id) {
				Book book = new Book();
				book.setId(id);
				book.setAuthor("error");
				book.setBookName("error name");
				return book;
			}
			@Override
			public Book getBook(Book book) {
				return book;
			}
			@Override
			public Book getBook(Integer id, String bookName, String author) {
				Book book = new Book();
				book.setId(id);
				book.setAuthor(bookName);
				book.setBookName(author);
				return book;
			}
			@Override
			public Book addBook(Book book) {				
				return book;
			}			
		};
	}	
}

在@FeignClient的fallbackFactory中指定对应的类。


@FeignClient(name="bookshop-service-provider" ,fallbackFactory=ErrorFallbackFactory.class)
public interface BookConsumerControllerInterface extends BookController {

}

1.2 Hystrix实现服务降级

hystrix提供了降级操作,可以实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值. fallback方法的返回值一般是设置的默认值或者来自缓存。下述代码主要利用注解的方式来实现服务降级,Hystrix还可以实现HystrixCommand接口来实现降级。

 1.2.1 引入Hystrix依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

 1.2.2 启动类开启熔断

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableCircuitBreaker   //开启熔断

public class BookshopConsumerHystrixApplication {

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

}

 1.2.3 编写fallbackMethod方法

        /**
	 * 以下四种情况会触发fallback调用
	 * 1:方法抛出非HystrixBadRequestException异常
	 * 2:方法调用超时
	 * 3:熔断器开启拦截调用
	 * 4:线程池/队列/信号量是否饱满
	 * 
	 * 降级参数:
	 * fallback.enabled   --- fallback是否可用----默认true---当执行失败或者请求被拒绝,是否尝试调用hystrixCommand.getFallback()
	 * fallback.isolation.semaphore.maxConcurrentRequests   ---fallback最大并发度,默认10,如果并发数达到设置值,请求会被拒绝和抛出异常并且fallback不会被调用
	 * */
	@HystrixCommand(fallbackMethod="getBookListFallback")
	@RequestMapping(value="getbooklist",method=RequestMethod.GET)
	public List<Book> getBookList(){
		
		return bookCon.getBookList();
	}
	
	public List<Book> getBookListFallback() {
		List<Book> bookList = new ArrayList<Book>();
		Book book = new Book();
		book.setAuthor("hystrix error");
		book.setBookName("hystrix fallback");
		book.setId(0);
		bookList.add(book);
		return bookList;
	}

注意:fallbackMethod方法,需要和@HystrixCommand注解处于同一个类中,同时,服务降级函数在执行过程中也有可能发生异常,所以也可以给服务降级函数添加降级方法。

关闭provider服务,浏览器调用consumer,结果如下:

 1.2.4 异常处理

如果有一个异常抛出后我不希望进入到服务降级方法中去处理,而是直接将异常抛给用户,那么我们可以在@HystrixCommand注解中添加忽略异常(ignoreExceptions)。

	@HystrixCommand(fallbackMethod="getBookListFallback",ignoreExceptions = ArithmeticException.class)
	@RequestMapping(value="getbooklist",method=RequestMethod.GET)
	public List<Book> getBookList(){
		int i = 1/0;
		return bookCon.getBookList();
	}
	
	public List<Book> getBookListFallback() {
		List<Book> bookList = new ArrayList<Book>();
		Book book = new Book();
		book.setAuthor("hystrix error");
		book.setBookName("hystrix fallback");
		book.setId(0);
		bookList.add(book);
		return bookList;
	}

执行调用结果:

 1.2.5 参数详解

降级参数
参数作用默认值备注
fallback.enabledfallback是否可用TRUE当执行失败或者请求被拒绝,是否会尝试调用hystrixCommand.getFallback()
fallback.isolation.semaphore.maxConcurrentRequestsfallback最大并发数10如果并发数达到该设置值,请求会被拒绝和抛出异常并且fallback不会被调用.
以下四种情况将触发getFallback调用
1:方法抛出非HystrixBadRequestException异常
2:方法调用超时
3:熔断器开启拦截调用
4:线程池/队列/信号量是否饱满

2:服务熔断

2.1 熔断机制

如下图,是熔断开启/关闭的一般流程:

2.2 Consumer侧引入pom

在Consumer侧的pom中引入hystrix的依赖。

                <dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
		</dependency>

2.3 在Consumer侧启动类开启熔断

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker   //开启Hystrix熔断

public class BookshopConsumerHystrixBreakerApplication {
	
	@Bean
	public RestTemplate createRt() {
		return new RestTemplate();
	}

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

2.4 在Consumer侧编写熔断方法及配置

在Consumer中建立service类,其实现getBookList方法调用服务Provider中的/getbooklist接口,并对getBookList实现熔断处理:

@Service
public class BookService {
	
	@Autowired
	private RestTemplate restTemplate;
	
	@Autowired
	private LoadBalancerClient loadBalancerClient;//ribbon 负载均衡客户端
	
	@HystrixCommand(fallbackMethod="getBookListFallback",
			commandProperties={
			
			//10s内请求数大于20(默认)个时就启动熔断器,当请求符合熔断器条件时触发getFallBack()
			@HystrixProperty(name=HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD,value="10"),
			//请求错误率大于50%时就熔断,然后for循环发起请求,当请求符合熔断条件时触发getFallBack()
			@HystrixProperty(name=HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE,value="50"),
			//熔断器开启5s后去尝试请求,默认5秒,以毫秒为单位
			@HystrixProperty(name=HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS,value="5000"),
			//超时设置
			@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "8000"),
			
	})
	public List<Book> getBookList(Integer id) {
		System.out.println("====================get BookList===== " + id);
		if (id ==1) {
			throw new RuntimeException();
		}
		
		ServiceInstance si=loadBalancerClient.choose("bookshop-service-provider");
		StringBuffer sb=new StringBuffer("");
		sb.append("http://");
		sb.append(si.getHost());
		sb.append(":");
		sb.append(si.getPort());
		sb.append("/getbooklist");
		System.out.println(sb.toString());
		
		//String data = restTemplate.getForObject(sb.toString(), String.class);
		/**
		 *封装返回对象为List<Book> 
		 **/
		ParameterizedTypeReference<List<Book>> responseType = new ParameterizedTypeReference<List<Book>>(){};
		ResponseEntity<List<Book>> result = restTemplate.exchange(sb.toString(),HttpMethod.GET, null,responseType);
		System.out.println("code : " + result.getStatusCode());
		return result.getBody();		
	
	}
	
	/**
	 * 实现List<Book> getBookList()的熔断方法
	 * */
	@HystrixCommand
	public List<Book> getBookListFallback(Integer id) {
		System.out.println("=========get book list fallback== " +id);
		List<Book> bookList = new ArrayList<Book>();
		Book book = new Book();
		book.setAuthor("breaker");
		book.setBookName("breaker");
		bookList.add(book);
		return bookList;
	}

}

参数详解:

 

熔断参数
参数作用默认值备注
circuitBreaker.enabled是否开启熔断TRUE 
circuitBreaker.requestVolumeThreshold一个统计窗口内熔断触发的最小个数/10s2010s内请求数大于20个时就启动熔断器,当请求符合熔断条件时将触发getFallback().
circuitBreaker.sleepWindowInMilliseconds熔断多少秒后去尝试请求5000ms 
circuitBreaker.errorThresholdPercentage失败率达到多少百分比后开启熔断默认配置下采样周期为10s,失败率为50%请求错误率大于50%时就熔断,然后for循环发起请求,当请求符合熔断条件时将触发getFallback()
circuitBreaker.forceOpen是否强制开启熔断FALSE置为true时,所有请求都将被拒绝,直接到fallback
circuitBreaker.forceClose是否强制关闭熔断FALSE置为true时,将忽略错误.

2.5 Provider服务概述

本章的Provider服务利用了《声明式服务调用的实现(Feign)及其优化(Ribbon) 》中的provider服务,此处不做具体的介绍,

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值