OpenFeign是什么

在说OpenFeign之前,Feign是一个声明式的Web Service客户端。它的出现使开发Web Service客户端变得很简单。使用Feign只需要创建一个接口加上对应的注解。就能够使调用远程微服务像调用本地服务一样简单。

那OpenFeign是什么呢?

OpenFeign是Spring Cloud 在Feign的基础上支持了Spring MVC的注解,如@RequesMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。

在开发微服务时,不同服务之间调用是必须的。Spring Boot集成了RestTemplate来实现远程调用,Dubbo则本身就是一个RPC远程调用框架,而Open Feign则是Spring Cloud这一套的成员。

本文介绍的OpenFeign,可以看作是Feign的加强版,浅显来讲,主要是一个可以用来远程调用服务的框架,当然它也支持很多其他的细节功能。

  • 1.可插拔的注解支持,包括Feign注解和JAX-RS注解。
  • 2.支持可插拔的HTTP编码器和解码器(Gson,Jackson,Sax,JAXB,JAX-RS,- SOAP)。
  • 3.支持Hystrix和它的Fallback。
  • 4.支持Ribbon的负载均衡。
  • 5.支持HTTP请求和响应的压缩。
  • 6.灵活的配置:基于 name 粒度进行配置
  • 7.支持多种客户端:JDK URLConnection、apache httpclient、okhttp,ribbon)
  • 8.支持日志
  • 9.支持错误重试
  • 10.url支持占位符
  • 11.可以不依赖注册中心独立运行

OpenFeign怎么用

既然是为远程调用而生,那么我们当然要以微服务调用来测试,并学习使用。

这里以下单、扣钱、减库存三个微服务作为样例。

引入POM依赖

<!-- open-feign    -->
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-openfeign</artifactId>
      <version>2.2.3.RELEASE</version>
  </dependency>

在Application启动类加上@EnableFeignClients注解开启Feign,本服务是订单服务。

/**
 * @author 阳光大男孩!!!
 */
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class,args);
    }
}

现在我们有三个微服务,分别是扣钱、创建订单、减库存,订单微服务中需要调用扣钱和减库存两个服务。

所以在订单服务中除了本地需要的订单服务,还需要创建远程微服务的两个接口,并指定FeignClient注解。

也就是说,你若想要调用别的微服务的Service,需要创建Service接口。

Java feign远程调用 read time out_spring

/**
 * @author 阳光大男孩!!!
 */
@FeignClient(value = "seata-account-service",url = "http://localhost:9001")
public interface AccountService {

    @RequestMapping("/account/decreaseMoney")
    void decreaseMoney(@RequestParam("userId") String userId, @RequestParam("money") Integer money);
}
@FeignClient(value = "seata-storage-service",url = "http://localhost:9003")
public interface StorageService {

    @RequestMapping("/storage/deduct")
    void deduct(@RequestParam("commodityCode") String commodityCode, @RequestParam("count") int count);
}

需要注意的是,我们这里在@FeignClient中指定了Value。

这个value的值就是对应被调用微服务的名称,并且指定微服务的url地址,与普通接口不同的是,@RequestMapping("/storage/deduct")要加在接口内方法,事实上如果只用Feign这么干是不行的,需要使用@RequestLine注解,而本片博文使用的是OpenFeign,支持SpringMvc注解,这也是OpenFeign的方便之处,

当然,如果你有使用Nacos,我们就可以更方便,而无需指定url,因为Nacos作为注册中心,可以帮助我们管理微服务。

阅读本篇博文的你,大概率也是在用Nacos Euraka之类的注册中心吧!这里以Nacos为例。

/**
 * @author 阳光大男孩!!!
 */
@FeignClient(value = "seata-account-service")
public interface AccountService {

    @RequestMapping("/account/decreaseMoney")
    void decreaseMoney(@RequestParam("userId") String userId, @RequestParam("money") Integer money);
}
@FeignClient(value = "seata-storage-service")
public interface StorageService {

    @RequestMapping("/storage/deduct")
    void deduct(@RequestParam("commodityCode") String commodityCode, @RequestParam("count") int count);
}

而本地订单服务调用则不用配置OpenFeign,因为实现类就在本服务。

/**
 * @author 阳光大男孩!!!
 */
public interface OrderService {

    /**
     * 创建订单
     * @param orderTbl
     */
    void create(OrderTbl orderTbl);
}

好了,加上了注解,指定了URI,这就是我们需要做的全部事情了,接下来就是在Service实现类中去调用实现逻辑了。

/**
 * @author 阳光大男孩!!!
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class OrderServiceImpl implements OrderService {

    private final OrderTblDao orderTblDao;
    // 远程库存微服务
    private final StorageService storageService;
    // 远程扣减余额微服务
    private final AccountService accountService;

    @Override
    public void create(OrderTbl orderTbl) {

        log.info("----->开始新建订单");
        //1 新建订单
        orderTblDao.insertSelective(orderTbl);

        //2 扣减库存
        log.info("----->订单微服务开始调用库存,做扣减Count");
        storageService.deduct(orderTbl.getCommodityCode(),orderTbl.getCount());
        log.info("----->订单微服务开始调用库存,做扣减end");

        //3 扣减账户
        log.info("----->订单微服务开始调用账户,做扣减Money");
        accountService.decreaseMoney(orderTbl.getUserId(),orderTbl.getMoney());
        log.info("----->订单微服务开始调用账户,做扣减end");

        log.info("----->下单全流程结束.........");
    }
}

有没有发现,我们注入远程Service后,就能像本地调用一样,实现远程调用微服务。