服務間通信:Spring Cloud Netflix Ribbon和 Spring Cloud OpenFeign
一個大型的系統由多個微服務子產品組成,我們一般可以通過内部接口調用的形式(服務A提供一個接口,服務B通過HTTP請求調用服務A的接口)實作各子產品之間的通信。為了簡化開發,SpringCloud內建了Spring Cloud Netflix Ribbon和Spring Cloud OpenFeign,兩個元件都支援通過HTTP請求不同的服務。
舉個例子,使用者子產品和評論子產品,當查詢評論清單時需要傳回使用者的基本資訊(昵稱、頭像等),直接利用SQL語句關聯查詢是可以實作該需求的,但是耦合性較強,亦不利于擴充。使用者資訊應由使用者子產品提供,這時就需要使用者子產品提供接口,評論子產品調用此接口,進而拿到使用者資料。
本文将簡要介紹Spring Cloud Netflix Ribbon,借此引出 Sping Cloud OpenFeign,并詳細介紹其用法。
Spring Cloud Netflix Ribbon的使用
Spring Cloud Netflix Ribbon(即 Ribbon )是Spring Cloud Netflix的一個子項目,它提供了HTTP用戶端和TCP用戶端,用于支援各服務間的通信并且擁有負載均衡能力。

Ribbon 的一個核心概念是命名的用戶端。每一個負載均衡器都是Ribbon元件的一部分,它們在需要的時候一起工作,并且和遠端伺服器通信。
在 Spring Cloud工程中引用Ribbon非常簡單,隻需要在pom.xml中添加以下依賴:
org.springframework.cloudspring-cloud-starter-netflix-ribbon
隻要添加了上述依賴,該工程就擁有了Ribbon的HTTP遠端調用能力。Ribbon通過RestTemplate類調用遠端伺服器,是以我們還需要注入RestTemplate類,在 webConfig 類中添加以下代碼:
@Bean
@LoadBalanced
public RestTemplate restTemplate(){i
return new RestTemplate();
}
除了讀者已經熟悉的@Bean 注解外,還多了一個@LoadBalanced注解,隻有增加該注解,Ribbon才會啟用負載均衡。接下來示範通過comment服務遠端調用TEST服務。
首先,在comment工程下建立TestServiceRibbon接口和TestServiceImplRibbon類,該類用于遠端調用TEST服務的其中一個接口,編寫代碼如下:
public interface TestServiceRibbon {
String test(;
}
@service
public class TestServicelmplRibbon implements TestServiceRibbon {
@Autowired
private RestTemplate restTemplate;
@Override
public string test() {
return restTemplate.postForEntity("http://TEST/test" ,null,String.class).getBody();
}
}
我們可以看到,代碼注入了webConfig 配置的 RestTemplate類,然後通過RestTemplate 的postForEntity方法調用TEST服務的test接口,并通過getBody方法傳回結果。
然後,建立控制器類,并編寫如下代碼:
@RequestMapping( "ribbon")
@RestController
public class TestcontrollerRibbon i
@Autowired
TestServiceRibbon testserviceRibbon;@RequestMapping( "test")
private String test(){
return testServiceRibbon.test();
}
}
提供上述控制器的目的是更友善地測試Ribbon能否成功調用TEST服務及其負載均衡能力,當然也可以直接用單元測試,但是無法看到負載均衡效果。
我們可以分别啟動register、config、comment、test 工程,其中 test工程分别以9999和 9998端口啟動兩次,浏覽器多次通路位址localhost:8203/ribbon/test,可以看到分别列印出端口9999和 9998,說明Ribbon負載均衡已生效。
正如上面所說,如果不添加@LoadBalancer 注解,則無法使用負載均衡功能,并且 postForEntity傳入的位址無法直接使用服務名TEST,會報如圖11-1所示的錯誤。