OpenFeign的使用和Hystrix断路器

一.使用Open Feign

1.新建一个消费者模块,feign自带负载均衡配置,所以不用手动配置。
2.导入相关依赖。

<dependencies>
    <!-- Open Feign -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <!-- eureka Client -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
        <groupId>com.krisswen.cloud</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>${project.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

3.编写相关的.yml的配置文件

server:
  port: 80
spring:
  application:
    name: cloud-consumer-feign-service
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

4.编写启动类,启动类名称要见名知意。

@SpringBootApplication
@EnableFeignClients //开启使用feign客户端的功能
public class CustomerFeignMain80 {
    public static void main(String[] args) {
        SpringApplication.run(CustomerFeignMain80.class,args);
    }
}

5.编写feign的客户端,在跟启动类同级的目录下建一个client的目录用于创建客户端。

@FeignClient(value = "cloud-payment-service") //标识当前接口就是一个feign客户端,并且指定调用哪一个微服务
public interface PaymentFeignService {
    @GetMapping("payment/{id}")
    public CommonResult<Payment> findPaymentById(@PathVariable("id") Long id);
}

6.编写Controller层

@RestController
public class CustomerFeignController {

    @Autowired
    PaymentFeignService paymentFeignService;

    @GetMapping("consumer/feign/payment/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
        return paymentFeignService.getPaymentById(id);
    }
}

二.超时控制

手动模拟出现超时时间。
1.在提供方8001的Controller里面定义一个方法

//故意模拟服务超时
@GetMapping("payment/timeout")
    public String testTimeOut(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "这是一个模拟超时的服务......";
    }

2.在feign的客户端里面定义两个没有方法体的方法:

	@GetMapping("payment/{id}")
    public CommonResult<Payment> findPaymentById(@PathVariable("id") Long id);

    @GetMapping("payment/timeout")
    public String testTimeOut();

3.在Controller层里面的类中定义下列方法,

	//@SuppressWarnings("all")该注解在类可以自动注入的压制误报
	@Autowired
    OrderFeignClient orderFeignClient;

    @GetMapping("order/feign/{id}")
    public CommonResult<Payment> findById(@PathVariable("id") Long id){
        CommonResult<Payment> commonResult = this.orderFeignClient.findPaymentById(id);
        return commonResult;
    }

    //调用超时的服务
    @GetMapping("order/feign/timeout")
    public String testTimeOut(){
        return this.orderFeignClient.testTimeOut();
    }

4.测试
4.1首先我们直接访问8001服务中的testTimeOut方法,
4.2然后通过feign客户端类访问
5.为了避免出现调用超时的情况,我们需要在消费者的配置文件里面配置超时时间(注意!有的电脑只用配置ribbon就能使用,大部分电脑都需要二者都要配置,极少数的只用配置ribbon即可。)

feign:
  client:
    config:
      default:
        readTimeout: 5000
        connectTimeout: 5000
ribbon: #设置Feign客户端调用超时时间
  ReadTimeOut: 5000 #指的是建立连接所需要的的时间
  ConnectTimeOut: 5000 #指的是建立连接之后,服务器读取资源需要的时间

Open Feign日志打印

1.在消费方编写一个配置类

@Configuration
public class FeignConfig {
    @Bean
    Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }
}

2.在yml的配置文件中添加

logging:
  level:
    com.baidu.service.PaymentFeignService: debug

注意!“com.baidu.service.PaymentFeignService”该路径以自己包下路径为主
3.启动测试,并查看控制台是否打印。

Hystrix断路器

1.新建一个提供者子模块
2.引入pom文件

<dependencies>
    <!-- hystrix -->
<!--
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
-->
    <!--eureka-client-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</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-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
        <groupId>com.krisswen.cloud</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>${project.version}</version>
    </dependency>
</dependencies>

注意,hystrix依赖先注释,待进行熔断操作时再放开加载
3.编写yml配置文件

server:
  port: 8001
spring:
  application:
    name: cloud-payment-service  #服务名称
eureka:
  client:
    # 注册进 Eureka 的服务中心
    register-with-eureka: true
    # 检索 服务中心 的其它服务
    fetch-registry: true
    service-url:
      # 设置与 Eureka Server 交互的地址
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

4.编写启动类

@SpringBootApplication
//@DiscoveryClient
public class HystrixPaymentApplication {
    public static void main(String[] args) {
        SpringApplication.run(HystrixPaymentApplication.class,args);
    }
}

5.编写service

@Service
public class PaymentService {

    /**
     * 可以正常访问的方法
     * @param id
     * @return
     */
    public String paymentInfo_Ok(Integer id){
        return "线程池:" + Thread.currentThread().getName() + "  ,paymentInfo_OK,id:" + id;
    }

    /**
     超时访问的方法
     */
    public String paymentInfo_Timeout(Integer id){
        int interTime = 3;
        try{
            TimeUnit.SECONDS.sleep(interTime);
        }catch (Exception e){
            e.printStackTrace();
        }
        return "线程池:" + Thread.currentThread().getName() + "  ,paymentInfo_Timeout,id:" + id + "耗时" + interTime + "秒钟";
    }
}

6编写Controller层

@RestController
@Slf4j
public class PaymentController {

    @Autowired
    PaymentService paymentService;

    @Value("${server.port}")
    private String serverPort;

    @GetMapping("/payment/hystrix/{id}")
    public String paymentInfo_OK(@PathVariable("id")Integer id){
        log.info("paymentInfo_OKKKKOKKK");
        return paymentService.paymentInfo_Ok(id);
    }

    @GetMapping("/payment/hystrix/timeout/{id}")
    public String paymentInfo_Timeout(@PathVariable("id")Integer id){
        log.info("paymentInfo_timeout");
        return paymentService.paymentInfo_Timeout(id);
    }
}
// localhost:8001/payment/hystrix/1   localhost:8001/payment/hystrix/timeout/1

7.启动测试,查看两个方法都是否能被正常访问

localhost:8001/payment/hystrix/1
localhost:8001/payment/hystrix/timeout/1

模拟高并发

1.要有一个JMeter压力测试其。
2.有压缩包,直接解压,双击/bin/jmeter.bat即可启动。
3.进入内部,左上方操作"测试计划–>添加–>线程(用户)–>线程组"。
4.编写线程组名称,下方输入线程数,时间(秒),循环次数
5.设置http请求,ctrl+s保存当前线程。
6.分别访问service服务里面的两个方法。
7.定义hystrix消费方的模块。
8.引入依赖

<dependencies>
    <!-- hystrix -->
   <!-- <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>-->
    <!-- OpenFeign -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <!--eureka-client-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</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-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
        <groupId>com.krisswen.cloud</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>${project.version}</version>
    </dependency>
</dependencies>

9.编写yml配置文件

server:
  port: 80
spring:
  application:
    name: cloud-customer-feign-hystrix-service
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

10.编写启动类

@SpringBootApplication
//@DiscoveryClient
@EnableFeignClients //开启Feign客户端
public class HystrixOrderApplication80 {
    public static void main(String[] args) {
        SpringApplication.run(HystrixOrderApplication80.class,args);
    }
}

11.编写feign客户端

@Component
@FeignClient(value = "cloud-payment-service")
public interface OrderService {

    @GetMapping("/payment/hystrix/{id}")
    public String paymentInfo_OK(@PathVariable("id")Integer id);

    @GetMapping("/payment/hystrix/timeout/{id}")
    public String paymentInfo_Timeout(@PathVariable("id")Integer id);
}

12.编写Controller

@RestController
@Slf4j
public class OrderController {

    @Autowired
    OrderService orderService;

    @GetMapping("/consumer/payment/hystrix/{id}")
    public String paymentInfo_OK(@PathVariable("id")Integer id){
        log.info("paymentInfo_OKKKKOKKK");
        return orderService.paymentInfo_OK(id);
    }

    @GetMapping("/consumer/payment/hystrix/timeout/{id}")
    public String paymentInfo_Timeout(@PathVariable("id")Integer id){
        log.info("paymentInfo_timeout");
        return orderService.paymentInfo_Timeout(id);
    }
}

13.启动测试,使用jmeter压测攻击模拟高并发。

局部服务降级(提供方)

1.再8001服务的提供方,放开Hysetix依赖

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

2.对8001的service进行重新配置

@Service
public class PaymentService {

    /**
     * 可以正常访问的方法
     * @param id
     * @return
     */
    public String paymentInfo_Ok(Integer id){
        return "线程池:" + Thread.currentThread().getName() + "  ,paymentInfo_OK,id:" + id;
    }

    /**
     超时访问的方法
     */
    @HystrixCommand(fallbackMethod = "timeoutHandler",commandProperties = {
            //设置峰值,超过 3 秒,就会调用兜底方法,这个时间也可以由feign控制
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
    })
    public String paymentInfo_Timeout(Integer id){
        int interTime = 5;
        //int i = 10/0;
        try{
            TimeUnit.SECONDS.sleep(interTime);
        }catch (Exception e){
            e.printStackTrace();
        }
        return "线程池:" + Thread.currentThread().getName() + "  ,paymentInfo_Timeout,id:" + id + "耗时" + interTime + "秒钟";
    }
   // 定义服务出现异常之后,兜底的方法
    public String timeoutHandler(Integer id){
        return "服务异常,请重试......";
    }
}

3.在启动类上开启服务熔断的注解

@EnableCircuitBreaker //开启服务熔断

4.启动8001服务测试。
5.改动服务方里面的代码进行测试。

局部服务降级(消费方)

1.将服务提供方关于所有服务降级的设置全部去掉
2.在消费放引入hystrix依赖(放开注释即可)

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

3.在启动类上开启服务熔断

@EnableCircuitBreaker//开启熔断器

4.在Controller编写降级逻辑

@RestController
@Slf4j
@SuppressWarnings("all")
public class OrderController {
    @Autowired
    OrderService orderService;
    @GetMapping("/consumer/payment/hystrix/{id}")
    public String paymentInfo_OK(@PathVariable("id")Integer id){
        log.info("paymentInfo_OKKKKOKKK");
        return orderService.paymentInfo_OK(id);
    }
    @HystrixCommand(fallbackMethod = "handeException", commandProperties = {
            //设置峰值,超过 1.5 秒,就会调用兜底方法
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value = "1500")
    })
    @GetMapping("/consumer/payment/hystrix/timeout/{id}")
    public String paymentInfo_Timeout(@PathVariable("id")Integer id){
        log.info("paymentInfo_timeout");
        return orderService.paymentInfo_Timeout(id);
    }

    public String handeException(Integer id){
        return "服务调用异常,请稍后再试.....";
    }
}

5.启动测试。
6.修改,然后再启动测试看是成功。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值