2020-01-15

SpringCloud分布式微服务云架构-feign中的使用Hystrix
在@FeignClient中有两个属性我们值得关注一下,它们分别是fallBack和fallBackFactory,了解springcloud架构可以加求求:三五三六二四七二五九,当然我们系统里要添加Hystrix支持并且在属性文件里设置:

feign.hystrix.enabled=true

同样我们要在启动类里加上@EnableCircuitBreaker注解打开Hystrix保护

fallBack属性很简单,用来设置降级方法,当feign请求服务失败时所调用的方法, 这里我给出接口的例子:

首先定义一个接口:IOrderService

package com.bdqn.lyrk.service.api;

import com.bdqn.lyrk.service.dto.OrderDTO;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;


public interface IOrderService {

    @GetMapping("/orderId/{orderId}")
    OrderDTO getOrderById(@PathVariable("orderId") Integer orderId);

    @GetMapping("/errorOrder")
    OrderDTO getErrorOrder();
}

其次定义Feign的接口OrderServiceClient继承IOrderService

package com.bdqn.lyrk.order.service.consumer.feign;

import com.bdqn.lyrk.service.api.IOrderService;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.annotation.Primary;

@Primary
@FeignClient(value = "ORDER-SERVER", fallBack="FailedOrderServiceClientImpl.class")
public interface OrderServiceClient extends IOrderService {

}

由于IOrderService不在同一个项目里,而且SpringCloud不推荐服务端和客户端使用同一个接口,所以我采用继承的方式,注意加上@Primary注解以免使用@Autowired时注入失败

在定义实现类:

package com.bdqn.lyrk.order.service.consumer.feign;

import com.bdqn.lyrk.service.dto.OrderDTO;
import org.springframework.stereotype.Component;

@Component
public class FailedOrderServiceClientImpl implements OrderServiceClient {
    @Override
    public OrderDTO getOrderById(Integer orderId) {
        OrderDTO orderDTO = new OrderDTO();
        orderDTO.setId(orderId);
        orderDTO.setOrderName("服务中失败的订单,id为:" + orderId);
        return null;
    }

    @Override
    public OrderDTO getErrorOrder() {
        OrderDTO orderDTO = new OrderDTO();
        orderDTO.setOrderName("服务中失败的订单");
        orderDTO.setId(-1);
        return orderDTO;
    }
}

最后@FeignClient中设置属性fallBack="FailedOrderServiceClientImpl.class" 就可以了

当我们需要封装服务端的异常信息时,可以指定fallbackFactory属性,请看下面的例子:

package com.bdqn.lyrk.order.service.consumer.feign;

import com.bdqn.lyrk.service.dto.OrderDTO;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;

@Component
public class OrderServiceFallbackFactoryImpl implements FallbackFactory {
    @Override
    public OrderServiceClient create(Throwable cause) {
       return new OrderServiceClient() {
           @Override
           public OrderDTO getOrderById(Integer orderId) {
               OrderDTO orderDTO = new OrderDTO();
               orderDTO.setOrderName(cause.getMessage());
               return orderDTO;
           }

           @Override
           public OrderDTO getErrorOrder() {
               OrderDTO orderDTO = new OrderDTO();
               orderDTO.setOrderName(cause.getMessage());
               return orderDTO;
           }
       };
    }
}

注意:FallbackFactory的泛型参数一定要指定为@FeignClient修饰的接口,同时不建议fallback与fallbackFactory同时使用
 最后 服务端的实现代码:

package com.bdqn.lyrk.springcloud.order.service;

import com.bdqn.lyrk.service.api.IOrderService;
import com.bdqn.lyrk.service.dto.OrderDTO;
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.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;


@RestController
public class OrderServiceImpl implements IOrderService {

    @HystrixCommand(fallbackMethod = "errorDTO",
            commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")}

    )
    @GetMapping("/orderId/{orderId}")
    @Override
    public OrderDTO getOrderById(@PathVariable("orderId") Integer orderId) {
        OrderDTO orderDTO = new OrderDTO();
        orderDTO.setId(orderId);
        orderDTO.setOrderName("订单ID为" + orderId + "的订单");
        try {
            TimeUnit.SECONDS.sleep(orderId);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        return orderDTO;
    }

    @Override
    public OrderDTO getErrorOrder() {
        System.out.println(1 / 0);
        return null;
    }

    public OrderDTO errorDTO(Integer orderId) {
        OrderDTO orderDTO = new OrderDTO();
        orderDTO.setId(-1);
        orderDTO.setOrderName("错误的订单,请重试");
        return orderDTO;
    }
}

你可能感兴趣的:(2020-01-15)