1. 程式人生 > 其它 >Spring Cloud | OpenFeign 讓遠端呼叫變得簡單

Spring Cloud | OpenFeign 讓遠端呼叫變得簡單

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介面。
在這裡插入圖片描述

/**
 * @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後,就能像本地呼叫一樣,實現遠端呼叫微服務。