SpringCloud之微服务(七)之服务容错和Hystrix、zuul超时配置,feign-hystrix,hystrix-dashboard

0、代码参考

springcloudmysell
order项目

1、触发降级

1、引入依赖

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

2、启动类添加@SpringCloudApplication或者(@EnableCircuitBreaker)

package cn.linst.springcloudsell.order;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;


// 要调用的product服务client所在的包。并且product的jar包引入到依赖中了。
// 先在product项目,执行命令mvn -Dmaven.test.skip=true -U clean install
// 后面改成product的jar发布到服务器上
@EnableFeignClients(basePackages = "cn.linst.springcloudsell.product.client")

 @SpringCloudApplication含下面3个
//@SpringBootApplication
//@EnableDiscoveryClient
//@EnableCircuitBreaker

@SpringCloudApplication
public class OrderApplication {

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

}

3、添加@HystrixCommand注解

HystrixController 测试demo。

package cn.linst.springcloudsell.order.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;


@RestController
public class HystrixController {

	@HystrixCommand(fallbackMethod = "fallback")
	@GetMapping("/getProductInfoList")
	public String getProductInfoList() {
 
		// 1、模拟 调用目标服务 降级。假设该目标服务出问题了
		RestTemplate restTemplate = new RestTemplate();
		return restTemplate.postForObject("http://127.0.0.1:7001/product/listForOrder",
				Arrays.asList("157875196366160022"),
				String.class);
		// 2、模拟自己内部服务降级
//		throw new RuntimeException("发送异常了");
	}

	private String fallback() {
		return "太拥挤了, 请稍后再试~~";
	}
}

在这里插入图片描述

4、默认注解@DefaultProperties(defaultFallback = “defaultFallback”)

package cn.linst.springcloudsell.order.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;


@RestController
@DefaultProperties(defaultFallback = "defaultFallback")
public class HystrixController {

	@GetMapping("/getProductInfoList")
	public String getProductInfoList() {

		RestTemplate restTemplate = new RestTemplate();
		return restTemplate.postForObject("http://127.0.0.1:7001/product/listForOrder222",
				Arrays.asList("157875196366160022"),
				String.class);

//		throw new RuntimeException("发送异常了");
	}

	private String fallback() {
		return "太拥挤了, 请稍后再试~~";
	}

	private String defaultFallback() {
		return "默认提示:太拥挤了, 请稍后再试~~";
	}
}

5、全局服务降级@DefaultProperties(defaultFallback = “defaultFallback”)

方法上要加上@HystrixCommand。

package cn.linst.springcloudsell.order.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;


@RestController
@DefaultProperties(defaultFallback = "fallback")
public class HystrixController {

    @HystrixCommand
	@GetMapping("/getProductInfoList")
	public String getProductInfoList() {

// 模拟调用外部
		RestTemplate restTemplate = new RestTemplate();
		return restTemplate.postForObject("http://127.0.0.1:7001/product/listForOrder",
				Arrays.asList("157875196366160022"),
				String.class);

//		throw new RuntimeException("发送异常了");
	}

	private String fallback() {
		return "太拥挤了, 请稍后再试~~";
	}

	private String defaultFallback() {
		return "默认提示:太拥挤了, 请稍后再试~~";
	}
}

在这里插入图片描述

2、超时设置

package com.imooc.order.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;


@RestController
@DefaultProperties(defaultFallback = "defaultFallback")
public class HystrixController {

	//超时配置
	@HystrixCommand(commandProperties = {
			@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
	})
	@GetMapping("/getProductInfoList")
	public String getProductInfoList() {
	
		RestTemplate restTemplate = new RestTemplate();
		return restTemplate.postForObject("http://127.0.0.1:7001/product/listForOrder",
				Arrays.asList("157875196366160022"),
				String.class);

//		throw new RuntimeException("发送异常了");
	}

	private String fallback() {
		return "太拥挤了, 请稍后再试~~";
	}

	private String defaultFallback() {
		return "默认提示:太拥挤了, 请稍后再试~~";
	}
}

在这里插入图片描述

3、在order项目的配置文件bootstrap.yml,或者配置git仓库order-dev.yml配置超时项。从zuul网关调用接口,可以在api-gateway.yml中配置。

下面测试以直接在order项目调用product接口。所以配置order-dev.yml。
正常应该都从zuul网关调用。
同样可以。


hystrix:
  command.default.execution.isolation.thread.timeoutInMilliseconds: 5000

# 下面这个不生效。不知道是否因为版本原因
# hystrix:
#  command:
#    default:
#      execution:
#        isolation:
#          thread:
#            timeout-in-milliseconds: 8000

4、自定义commandKey,单独为一个方法设置超时时间

getProductInfoList是方法名。
order-dev.yml:


hystrix:
  command.default.execution.isolation.thread.timeoutInMilliseconds: 5000
  
  getProductInfoList.execution.isolation.thread.timeout-in-milliseconds: 3000

5、断路器模式

package cn.linst.springcloudsell.order.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;


@RestController
@DefaultProperties(defaultFallback = "defaultFallback")
public class HystrixController {

//	//超时配置
//	@HystrixCommand(commandProperties = {
//			@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000")
//	})

	@HystrixCommand(commandProperties = {
			@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),  				//设置熔断
			@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),	//请求数达到后才计算
			@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), //休眠时间窗
			@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60"),	//错误率
	})
//	@HystrixCommand
	@GetMapping("/getProductInfoList")
	public String getProductInfoList(@RequestParam("number") Integer number) {
		if (number % 2 == 0) {
			return "success";
		}

// 模拟调用外部服务
		RestTemplate restTemplate = new RestTemplate();
		return restTemplate.postForObject("http://127.0.0.1:7001/product/listForOrder",
				Arrays.asList("157875196366160022"),
				String.class);

//		throw new RuntimeException("发送异常了");
	}

	private String fallback() {
		return "太拥挤了, 请稍后再试~~";
	}

	private String defaultFallback() {
		return "默认提示:太拥挤了, 请稍后再试~~";
	}
}

首先访问:

http://127.0.0.1:8081/getProductInfoList?number=2

在这里插入图片描述

多次访问刷新,根据前面配置错误率60%以上。

http://127.0.0.1:8081/getProductInfoList?number=1

在这里插入图片描述

再次访问:

http://127.0.0.1:8081/getProductInfoList?number=2

在这里插入图片描述

过一会,再访问:

http://127.0.0.1:8081/getProductInfoList?number=2

在这里插入图片描述

6 、zuul超时配置

配置中心api-gateway-dev.yml:

hystrix:
  command.default.execution.isolation.thread.timeoutInMilliseconds: 5000

7、feign-hystrix的使用

调用方order,和被调用方服务product

1、在被调用方服务product项目中,写一个ProductClient熔断方案,ProductClientFallback

package cn.linst.springcloudsell.product.client;

import cn.linst.springcloudsell.product.common.DecreaseStockInput;
import cn.linst.springcloudsell.product.common.ProductInfoOutput;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 *
 *  ProductClient熔断方案
 *
 */
@Component
public class ProductClientFallback implements ProductClient {

    @Override
    public List<ProductInfoOutput> listForOrder(List<String> productIdList) {
        return null;
    }

    @Override
    public void decreaseStock(List<DecreaseStockInput> decreaseStockInputList) {

    }

    @Override
    public String productMsg() {
        return null;
    }
}

2、在被调用方服务product项目中,给ProductClient增加熔断方案ProductClientFallback

package cn.linst.springcloudsell.product.client;



import cn.linst.springcloudsell.product.common.DecreaseStockInput;
import cn.linst.springcloudsell.product.common.ProductInfoOutput;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.List;


// 调用product应用的。调用远程服务product,并增加熔断方案ProductClientFallback
@FeignClient(name = "product", fallback = ProductClientFallback.class)
public interface ProductClient {

    // 调用它的接口。在product的接口
    @GetMapping("/msg")
    // 方法名字任意定义
    String productMsg();

//    // 使用@RequestBody注解,必须用post
    @PostMapping("/product/listForOrder")
     List<ProductInfoOutput> listForOrder(@RequestBody List<String> productIdList);

    @PostMapping("/product/decreaseStock")
    void decreaseStock(@RequestBody List<DecreaseStockInput> decreaseStockInputList);


}


3、被调用方product重新打成jar包。

mvn -Dmaven.test.skip=true -U clean install

4、调用方order,重新引入依赖product的jar

刷新pom.xml,重新maven导入。

5、在调用方order,设置feign超时时间

order-dev.yml:

feign:
  client:
    config:
      default:
        connect-timeout: 5000
        read-timeout: 5000

6、在调用方order,开启hystrix熔断

order-dev.yml:

feign:
  client:
    config:
      default:
        connect-timeout: 5000
        read-timeout: 5000
  # 熔断
  hystrix:
    enabled: true

7、在调用方,引导类上加上@ComponentScan(basePackages=“包”),不然找不到引入的client的jar包

@ComponentScan(basePackages = "cn.linst.springcloudsell")
package cn.linst.springcloudsell.order;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;


// 要调用的product服务client所在的包。并且product的jar包引入到依赖中了。
// 先在product项目,执行命令mvn -Dmaven.test.skip=true -U clean install
// 后面改成product的jar发布到服务器上
@EnableFeignClients(basePackages = "cn.linst.springcloudsell.product.client")

 @SpringCloudApplication含下面3个
//@SpringBootApplication
//@EnableDiscoveryClient
//@EnableCircuitBreaker

@SpringCloudApplication
@EnableHystrixDashboard
//在调用方,引导类上加上@ComponentScan(basePackages="包"),不然找不到引入的client的jar包
@ComponentScan(basePackages = "cn.linst.springcloudsell")
public class OrderApplication {

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

    @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }
}

8、hystrix-dashboard

在order 项目

1、引入依赖

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



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

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

2、引导类加上@EnableHystrixDashboard

并添加getServlet 方法。

package cn.linst.springcloudsell.order;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;


// 要调用的product服务client所在的包。并且product的jar包引入到依赖中了。
// 先在product项目,执行命令mvn -Dmaven.test.skip=true -U clean install
// 后面改成product的jar发布到服务器上
@EnableFeignClients(basePackages = "cn.linst.springcloudsell.product.client")

 @SpringCloudApplication含下面3个
//@SpringBootApplication
//@EnableDiscoveryClient
//@EnableCircuitBreaker

@SpringCloudApplication
@EnableHystrixDashboard
public class OrderApplication {

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

    @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }
}

浏览器访问。

http://127.0.0.1:8081/hystrix

在这里插入图片描述

填写:应用名字,时间1秒
在这里插入图片描述

进入连接不上:

在这里插入图片描述

3、修改order的yml配置:

management:
  endpoints:
    web:
      exposure:
        include: env,health,metrics,info,hystrix.stream,*

4、开启@HystrixCommand熔断配置

开启@HystrixCommand熔断配置

@HystrixCommand(commandProperties = {
		@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),  				//设置熔断
		@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),	//请求数达到后才计算
		@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), //休眠时间窗
		@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60"),	//错误率
})

5、访问接口测试

http://127.0.0.1:8081/getProductInfoList?number=1

使用浏览器或者postman工具:
在这里插入图片描述

在这里插入图片描述

使用postman工具测试:

在这里插入图片描述

在这里插入图片描述
点击运行:开始调用接口
在这里插入图片描述
可以看到:
在这里插入图片描述

访问一个正常接口,

http://127.0.0.1:8081/getProductInfoList?number=2

在这里插入图片描述

过段时间,再次访问一个正常接口,

http://127.0.0.1:8081/getProductInfoList?number=2

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值