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