白話SpringCloud | 第四章:服務消費者(RestTemple+Ribbon+Feign)
一點知識
在SpringCloud
體系中,我們知道服務之間的呼叫是通過http
協議進行呼叫的。而註冊中心的主要目的就是維護這些服務的服務列表。我們知道,在Spring
中,提供了RestTemplate
。RestTemplate
是Spring
提供的用於訪問Rest服務的客戶端。而在SpringCloud
中也是使用此服務進行服務呼叫的。
同時在微服務中,一般上服務都不會進行單點部署的,都會至少部署2臺及以上的。現在我們有了註冊中心進行服務列表的維護,就需要一個客戶端負載均衡來進行動態服務的呼叫。
所以開始示例前,我們先來大致瞭解下關於負載均衡
和RestTemplate
的相關知識點。其實後面例項的Ribbon
和Feign
最後的呼叫都是基於RestTemplate
的。使用比較簡單~
何為負載均衡
負載均衡(Load Balance)是分散式系統架構設計中必須考慮的因素之一,它通常是指,將請求/資料【均勻】分攤到多個操作單元上執行,負載均衡的關鍵在於【均勻】。
實現的方式
實現負載均衡的方式有很多種,這裡簡單介紹下幾種方式,並未過多深入。
注意:以下部分內容轉至幾種負載均衡技術的實現。
1.HTTP重定向負載均衡
根據使用者的http請求計算出一個真實的web伺服器地址,並將該web伺服器地址寫入http重定向響應中返回給瀏覽器,由瀏覽器重新進行訪問
優缺點:實現起來很簡單,而缺點也顯而易見了:請求兩次才能完成一次訪問;效能差;重定向伺服器會成為瓶頸
2.DNS域名解析負載均衡
在DNS伺服器上配置多個域名對應IP的記錄。例如一個域名
www.baidu.com
對應一組web伺服器IP地址,域名解析時經過DNS伺服器的演算法將一個域名請求分配到合適的真實伺服器上。
優缺點:加快訪問速度,改善效能。同時由於DNS解析是多級解析,每一級DNS都可能化快取記錄A,當某一伺服器下線後,該伺服器對應的DNS記錄A可能仍然存在,導致分配到該伺服器的使用者訪問失敗,而且DNS負載均衡採用的是簡單的輪詢演算法,不能區分伺服器之間的差異,不能反映伺服器當前執行狀態。
3.反向代理負載均衡
反向代理處於web伺服器這邊,反向代理伺服器提供負載均衡的功能,同時管理一組web伺服器,它根據負載均衡演算法將請求的瀏覽器訪問轉發到不同的web伺服器處理,處理結果經過反向伺服器返回給瀏覽器。
優缺點:實現簡單,可利用反向代理快取資源(這是最常用的了)及改善網站效能。同時因為是所有請求和響應的中轉站,所以反向代理伺服器可能成為瓶頸。
以上僅僅是部分實現方式,還有比如IP負載均衡
、資料鏈路層負載均衡
等等,這些可能涉及到相關網路方面的知識點了,不是很瞭解,大家有興趣可以自行搜尋下吧。
客戶端和服務端的負載均衡
實現負載均衡也又區分客戶端和服務端之分,Ribbon
就是基於客戶端的負載均衡。
客戶端負載均衡:
服務端負載均衡:
服務端實現負載均衡方式有很多,比如:硬體F5
、Nginx
、HA Proxy
等等,這些應該實施相關人員應該比較熟悉了,本人可能也就對Nginx
瞭解下,⊙﹏⊙‖∣
RestTemplate簡單介紹
RestTemplate
是Spring
提供的用於訪問Rest服務
的客戶端,RestTemplate
提供了多種便捷訪問遠端Http服務的方法,能夠大大提高客戶端的編寫效率。
簡單來說,RestTemplate
採用了模版設計
的設計模式,將過程中與特定實現相關的部分委託給介面,而這個介面的不同實現定義了介面的不同行為,所以可以很容易的使用不同的第三方http服務,如okHttp
、httpclient
等。
RestTemplate
定義了很多的與REST資源互動,這裡簡單介紹下一些常用的請求方式的使用。
exchange
在URL上執行特定的HTTP方法,返回包含物件的ResponseEntity
。其他的如GET
、POST
等方法底層都是基於此方法的。
如:
- get請求
RequestEntity requestEntity = RequestEntity.get(new URI(uri)).build();
ResponseEntity<User> responseEntity2 = this.restTemplate.exchange(requestEntity, User.class);
- post請求
RequestEntity<User> requestEntity = RequestEntity.post(new URI(uri)).body(user);
ResponseEntity<User> responseEntity2 = this.restTemplate.exchange(requestEntity, User.class);
GET請求
get請求可以分為兩類:
getForEntity()
和getForObject()
.
// 1-getForObject()
User user1 = this.restTemplate.getForObject(uri, User.class);
// 2-getForEntity()
ResponseEntity<User> responseEntity1 = this.restTemplate.getForEntity(uri, User.class);
HttpStatus statusCode = responseEntity1.getStatusCode();
HttpHeaders header = responseEntity1.getHeaders();
User user2 = responseEntity1.getBody();
其他的方法都大同小異了,可以根據實際的業務需求進行呼叫。
POST請求
簡單示例:
// 1-postForObject()
User user1 = this.restTemplate.postForObject(uri, user, User.class);
// 2-postForEntity()
ResponseEntity<User> responseEntity1 = this.restTemplate.postForEntity(uri, user, User.class);
關於postForLocation()
,用的比較少,作用是返回新建立資源的URI,前面介紹的兩者是返回資源本身,也就是結果集了。
關於其他的請求型別相關用法,這裡就不詳細闡述了,都是類似的。可以檢視下此文章:詳解 RestTemplate 操作,講的蠻詳細了。
特別說明:系列教程為了方便,github上分別建立了一個單體的Eureka
註冊中心和高可用的Eureka
註冊中心,無特殊說明,都是使用單體的Eureka
註冊中心進行服務註冊與發現的,工程名為:spring-cloud-eureka-server
,埠號為:1000。服務提供方工程名為:spring-cloud-eureka-client
,應用名稱為:eureka-client
,埠號為:2000,提供了一個介面:http://127.0.0.1:2000/hello
spring-cloud-eureka-server示例:spring-cloud-eureka-server
spring-cloud-eureka-client示例:spring-cloud-eureka-client
LoadBalancerClient例項
此類是實現客戶端負載均衡的關鍵。本身它是個介面類,位於spring-cloud-commons
包下,此包包含了大量的服務治理相關的抽象介面,比如已經介紹過的DiscoveryClient
、ServiceRegistry
以及LoadBalancerClient例項
等等。
首先,我們使用最原生的方式去獲取呼叫服務介面。
建立個工程:spring-cloud-eureka-consumer
0.引入pom檔案依賴。
<!-- 客戶端依賴 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
1.配置檔案新增相關注冊中心等資訊。
## 服務名稱
spring.application.name=eureka-consumer
## 埠號
server.port=8008
#指定註冊中心地址
eureka.client.service-url.defaultZone=http://127.0.0.1:1000/eureka
# 啟用ip配置 這樣在註冊中心列表中看見的是以ip+埠呈現的
eureka.instance.prefer-ip-address=true
# 例項名稱 最後呈現地址:ip:2000
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}
2.編寫啟動類,加入@EnableDiscoveryClient
,申明為一個客戶端應用,同時申明一個RestTemplate
,最後是使用RestTemplate
來完成rest服務呼叫的。
@SpringBootApplication
@EnableDiscoveryClient
@Slf4j
public class EurekaConsumerApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(EurekaConsumerApplication.class, args);
log.info("spring-cloud-eureka-consumer啟動!");
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
3.編寫一個呼叫類,呼叫spring-cloud-eureka-client
服務提供者提供的服務。
/**
* 訪問客戶端示例
* @author oKong
*
*/
@RestController
@Slf4j
public class DemoController {
@Autowired
LoadBalancerClient loadBalancerClient;
@Autowired
RestTemplate restTemplate;
@GetMapping("/hello")
public String hello(String name) {
ServiceInstance serviceInstance = loadBalancerClient.choose("eureka-client");
String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/hello?name=" + name;
log.info("url地址為:{}", url);
return restTemplate.getForObject(url, String.class);
}
}
4.啟動應用,訪問:http://127.0.0.1:8008/hell0?name=oKong ,可以看見控制檯輸出了利用LoadBalancerClient
的choose
方法,獲取到了對應eureka-client
服務ID的服務地址。
最後通過範圍對應的http地址進行服務請求:
最後瀏覽器上可以看見,進行了正確的訪問了:
此時,切換到服務提供者spring-cloud-eureka-client
控制檯,可以看見日誌輸出:
此時我們已經呼叫成功了,通過LoadBalancerClient
獲取到了服務提供者實際服務地址,最後進行呼叫。
大家可以建立多個的spring-cloud-eureka-client
服務提供者,再去呼叫下,可以看見會呼叫不同的服務地址的。
客戶端負載均衡Ribbon例項
Spring Cloud Ribbon
是一個基於Http和TCP的客服端負載均衡工具,它是基於Netflix Ribbon
實現的。與Eureka
配合使用時,Ribbon
可自動從Eureka Server (註冊中心)
獲取服務提供者地址列表,並基於負載均衡
演算法,通過在客戶端中配置ribbonServerList
來設定服務端列表去輪詢訪問以達到均衡負載的作用。
上小節,簡單的使用LoadBalancerClient
進行了服務例項獲取最後呼叫,也說了其實LoadBalancerClient
是個介面類。而Ribbon
實現了此介面,對應實現類為:RibbonLoadBalancerClient
.
Ribbon例項
現在我們來看下,使用Ribbon
的方式如何進行更加優雅的方式進行服務呼叫。
建立一個工程:spring-cloud-eureka-consumer-ribbon
(其實這個工程和spring-cloud-eureka-consumer
是差不多的,只是有些許不同。)
0.加入pom依賴
<!-- 客戶端依賴 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
1.配置檔案修改,新增註冊中心等相關資訊。
spring.application.name=eureka-consumer-ribbon
server.port=8018
#指定註冊中心地址
eureka.client.service-url.defaultZone=http://127.0.0.1:1000/eureka
# 啟用ip配置 這樣在註冊中心列表中看見的是以ip+埠呈現的
eureka.instance.prefer-ip-address=true
# 例項名稱 最後呈現地址:ip:2000
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}
2.編寫啟動類,加入@EnableDiscoveryClient
,同時申明一個RestTemplate
,這裡和原先不同,就在於加入了@LoadBalanced
註解進行修飾RestTemplate
類,稍後會大致講解下是如何進行實現的。
@SpringBootApplication
@EnableDiscoveryClient
@Slf4j
public class EurekaConsumerRibbonApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(EurekaConsumerRibbonApplication.class, args);
log.info("spring-cloud-eureka-consumer-ribbon啟動!");
}
//新增 @LoadBalanced 使其具備了使用LoadBalancerClient 進行負載均衡的能力
@Bean
@LoadBalanced
public RestTemplate restTemplage() {
return new RestTemplate();
}
}
3.編寫測試類,進行服務呼叫。
/**
* ribbon訪問客戶端示例
* @author oKong
*
*/
@RestController
@Slf4j
public class DemoController {
@Autowired
RestTemplate restTemplate;
@GetMapping("/hello")
public String hello(String name) {
//直接使用服務名進行訪問
log.info("請求引數name:{}", name);
return restTemplate.getForObject("http://eureka-client/hello?name=" + name, String.class);
}
}
可以看見,可以直接注入RestTemplate
,通過服務名直接呼叫.
4.啟動應用,訪問:http://127.0.0.1:8018/hello?name=oKong ,可以看見呼叫成功:
控制檯輸出:
簡單聊聊LoadBalanced註解
可以從以上示例中,可以看出,我們就加了一個
@LoadBalanced
註解修飾RestTemplate
bean類,就實現了服務的呼叫。現在來簡單看看具體是如何實現的。
首先,我們看看此註解的程式碼說明:
從註釋可以看出,該註解用來給RestTemplate做標記,以使用負載均衡的客戶端LoadBalancerClient
。
現在來看一眼相同包下的類的情況,可以看到有個LoadBalancerAutoConfiguration
,字面意思可以知道這是一個自動配置類,此類就是我們要找的關鍵類了。
LoadBalancerAutoConfiguration
,此類不長,一百來行,這裡就不貼了。
簡單說明下:
首先,此類生效的條件是
@ConditionalOnClass(RestTemplate.class)
@ConditionalOnBean(LoadBalancerClient.class)
RestTemplate
類必須存在於當前工程的環境中。- 在Spring的Bean工程中有必須有
LoadBalancerClient
的實現Bean。
該自動化配置類中,主要做了幾件事情:
- 維護了一個被@LoadBalanced註解修飾的RestTemplate物件列表
@LoadBalanced
@Autowired(required = false)
private List<RestTemplate> restTemplates = Collections.emptyList();
同時為其每個物件通過呼叫RestTemplateCustomizer
新增了一個LoadBalancerInterceptor
和RetryLoadBalancerInterceptor
攔截器(有生效條件),其為ClientHttpRequestInterceptor
介面的實現類,ClientHttpRequestInterceptor
是RestTemplate
的請求攔截器
RetryLoadBalancerInterceptor攔截器
LoadBalancerInterceptor攔截器
我們主要看下LoadBalancerInterceptor
:
可以看見,最後是實現了ClientHttpRequestInterceptor
介面的實現類執行execute
方法進行.
從繼承關係裡,此實現類就是RibbonLoadBalancerClient
類了。
RibbonLoadBalancerClient
類:
簡單來說:最後還是通過loadBalancerClient.choose()
獲取到服務例項,最通過拼湊http地址來進行最後的服務呼叫。
總體來說,就是通過為加入@LoadBalanced
註解的RestTemplate
新增一個請求攔截器,在請求前通過攔截器獲取真正的請求地址,最後進行服務呼叫。
裡面的細節就不闡述了,畢竟原始碼分析不是很在行呀,大家可以跟蹤進去一探究竟吧。
友情提醒:若被@LoadBalanced
註解的RestTemplate
訪問正常的服務地址,如http://127.0.0.1:8080/hello
時,是會提示無法找到此服務的。
具體原因:serverid
必須是我們訪問的服務名稱
,當我們直接輸入ip
的時候獲取的server
是null
,就會丟擲異常。
此時,若是需要呼叫非註冊中心的服務,可以建立一個不被@LoadBalanced
註解的RestTemplate
,同時指定bean的名稱,使用時,使用@Qualifier
指定name注入此RestTemplate
。
@Bean("normalRestTemplage")
public RestTemplate normalRestTemplage() {
return new RestTemplate();
}
//使用
@Autowired
@Qualifier("normalRestTemplage")
RestTemplate normalRestTemplate;
@GetMapping("/ip")
public String ip(String name) {
//直接使用服務名進行訪問
log.info("使用ip請求,請求引數name:{}", name);
return normalRestTemplate.getForObject("http://127.0.0.1:2000/hello?name=" + name, String.class);
}
負載均衡器
目前還未進行過自定義負載均衡,這裡就簡單的舉例下,上次整理ppt時有講過一些,但未深入瞭解過⊙﹏⊙‖∣,
可以從繼承關係看出,是通過繼承IRule
來實現的。
可繼承ClientConfigEnabledRoundRobinRule,來實現自己負載均衡策略。
宣告式服務Feign例項
從上一章節,我們知道,當我們要呼叫一個服務時,需要知道服務名和api地址,這樣才能進行服務呼叫,服務少時,這樣寫覺得沒有什麼問題,但當服務一多,介面引數很多時,上面的寫法就顯得不夠優雅了。所以,接下來,來說說一種更好更優雅的呼叫服務的方式:Feign。
Feign
是Netflix
開發的宣告式、模組化的HTTP客戶端。Feign
可幫助我們更好更快的便捷、優雅地呼叫HTTP API
。
在Spring Cloud
中,使用Feign
非常簡單——建立一個介面,並在介面上新增一些註解。Feign
支援多種註釋,例如Feign自帶的註解或者JAX-RS註解等
Spring Cloud對Feign進行了增強,使Feign支援了Spring MVC註解,並整合了Ribbon和 Eureka,從而讓Feign 的使用更加方便。只需要通過建立介面並用註解來配置它既可完成對Web服務介面的繫結。
Feign例項
建立個spring-cloud-eureka-consumer-ribbon
工程專案。
0.加入feigin
依賴
<!-- feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- eureka客戶端依賴 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- rest api -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
1.配置檔案
spring.application.name=eureka-consumer-feign
server.port=8028
#指定註冊中心地址
eureka.client.service-url.defaultZone=http://127.0.0.1:1000/eureka
# 啟用ip配置 這樣在註冊中心列表中看見的是以ip+埠呈現的
eureka.instance.prefer-ip-address=true
# 例項名稱 最後呈現地址:ip:2000
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}
2.建立啟動類,加入註解@EnableFeignClients
,開啟feign
支援。
@SpringBootApplication
@EnableFeignClients
@Slf4j
public class EurekaConsumerFeignApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(EurekaConsumerFeignApplication.class, args);
log.info("spring-cloud-eureka-consumer-feign啟動");
}
}
3.建立一個介面類IHelloClient
,加入註解@FeignClient
來指定這個介面所要呼叫的服務名稱。
@FeignClient(name="eureka-client")
public interface IHelloClient {
/**
* 定義介面
* @param name
* @return
*/
@RequestMapping(value="/hello", method=RequestMethod.GET)
public String hello(@RequestParam("name") String name);
}
4.建立一個demo控制層,引入此介面類。
/**
* feign 示例
* @author OKong
*
*/
@RestController
@Slf4j
public class DemoController {
@Autowired
IHelloClient helloClient;
@GetMapping("/hello")
public String hello(String name) {
log.info("使用feign呼叫服務,引數name:{}", name);
return helloClient.hello(name);
}
}
5.啟動應用,訪問:http://127.0.0.1:8028/hello?name=oKong-feign
是不是很簡單,和呼叫本地服務是一樣的了!
Feign繼承特性
Feign
支援繼承,但不支援多繼承。使用繼承,可將一些公共操作分組到一些父類介面中,從而簡化Feign的開發。
所以在實際開發中,呼叫服務介面時,可直接按介面類和實現類進行編寫,呼叫方引入介面依賴,繼承一個本地介面,這樣介面方法預設都是定義好的,也少了很多編碼量。用起來就更爽了,就是有點依賴性,對方服務修改後需要同步更新下,但這個團隊內部約定下問題不大的
這裡簡單例項下,建立一個spring-cloud-eureka-client-api
工程。
0.加入依賴,注意此依賴的作用範圍:
<!--api介面依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided</scope>
</dependency>
1.編寫一個介面類IHellpApi
:
public interface IHelloApi {
//定義提供者服務名
public static final String SERVICE_NAME = "eureka-client";
/**
* 定義介面
* @param name
* @return
*/
@RequestMapping(value="/hello", method=RequestMethod.GET)
public String hello(@RequestParam("name") String name);
}
修改spring-cloud-eureka-client
工程
0.引入api依賴
<!-- 匯入介面依賴 -->
<dependency>
<groupId>cn.lqdev.learning</groupId>
<artifactId>spring-cloud-eureka-client-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
1.建立一個HelloApiImpl
類,實現IHelloApi
:
/**
* 使用介面方式進行介面編寫
* @author oKong
*
*/
@RestController
@Slf4j
public class HelloApiImpl implements IHelloApi {
@Override
public String helloApi(@RequestParam("name") String name) {
log.info("[spring-cloud-eureka-client]服務[helloApi]被呼叫,引數name值為:{}", name);
return name + ",helloApi呼叫!";
}
}
此時,HelloApiImpl
是個控制層也是個介面實現類了。
修改spring-cloud-eureka-consumer-feign
工程。
0.引入api依賴
<!-- 匯入介面依賴 -->
<dependency>
<groupId>cn.lqdev.learning</groupId>
<artifactId>spring-cloud-eureka-client-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
1.同樣建立一個介面,使其繼承IHelloApi
:
/**
* 直接繼承介面
* @author Okong
*
*/
@FeignClient(name = IHelloApi.SERVICE_NAME)
public interface HelloApi extends IHelloApi{
}
小技巧:可以在IHelloApi
定義一個服務名變數,如:SERVICE_NAME,這樣讓提供者進行變數的賦值,可以避免一些不必要的交流成本的,若有變化,服務呼叫方也無需關心的。一切都是約定程式設計!
2.修改下DemoController
類,注入HelloApi
:
@Autowired
HelloApi helloApi;
@GetMapping("hello2")
public String hello2(String name) {
log.info("使用feign繼承方式呼叫服務,引數name:{}", name);
return helloApi.helloApi(name);
}
3.分別啟動各服務,訪問:http://127.0.0.1:8028/hello2?name=oKong-api
使用起來沒啥差別的,一樣的呼叫,但對於呼叫方而言,可以無需去理會具體細節了,照著介面方法去傳參就好了。
這種方式,和原來的dubbo
呼叫的方式是類似的,簡單方便。大家可以把介面和實體放入一個包中,呼叫者和提供者都進行依賴即可。
注意事項
在使用Feign
時,會碰見一些問題,為了避免不必要的錯誤,以下這些需要額外注意下。
- GET請求多個引數時,需要使用@RequestParam
- GET請求引數為實體時,會自動轉換成POST請求
- POST請求使用@RequestBody註解引數
- 不建議直接將@RequestMapping註解在類上,直接寫在方法上
參考資料
總結
本章節主要講解了下服務消費者如何利用原生、ribbon、fegin三種方式進行服務呼叫的,其實每種呼叫方式都是使用
ribbon
來進行呼叫的,只是有些進行了增強,是的使用起來更簡單高效而已。對於其原理的實現,本文未進行詳細闡述,大家可以谷歌想相關知識,跟蹤下原始碼瞭解下,本人也尚未深入研究過,還是停留在使用階段,之後有時間了看一看,有啥心得再來分享吧。此時若服務上線下線,呼叫者呼叫可能會出現短暫的呼叫異常,最常見的就是找不到服務,此時服務容錯保護就排上用場了,所以下一章節,就來說說關於服務容錯保護
相關知識點~
最後
目前網際網路上大佬都有分享
SpringCloud
系列教程,內容可能會類似,望多多包涵了。原創不易,碼字不易,還希望大家多多支援。若文中有錯誤之處,還望提出,謝謝。
相關文章
- SpringCloud服務消費者-openFeign元件SpringGCCloud元件
- 《springcloud 一》搭建註冊中心,服務提供者,服務消費者SpringGCCloud
- SpringCloud學習之路(四) - 服務消費者(Feign)SpringGCCloud
- springcloud微服務實戰 學習筆記三 服務消費者SpringGCCloud微服務筆記
- SpringCloud 教程 | 第二篇: 服務消費者(rest+ribbon)SpringGCCloudREST
- springcloud之自定義簡易消費服務元件SpringGCCloud元件
- springcloud簡介及註冊中心和單體專案拆分服務者消費者SpringGCCloud
- 企業分散式微服務雲SpringCloud SpringBoot mybatis - 服務消費者(Feign)分散式微服務GCCloudSpring BootMyBatis
- Spring Cloud(四)服務提供者 Eureka + 服務消費者 FeignSpringCloud
- SpringCloud-eureka服務註冊發現以及消費流程SpringGCCloud
- Spring Cloud(三) 服務提供者 Eureka + 服務消費者(rest + Ribbon)SpringCloudREST
- SpringCloud學習系列之二 ----- 服務消費者(Feign)和負載均衡(Ribbon)SpringGCCloud負載
- 業餘草 SpringCloud教程 | 第三篇: 服務消費者(Feign)(Finchley版本)SpringGCCloud
- SpringCloud分散式微服務雲架構 第三篇: 服務消費者(Feign)(Finchley版本)SpringGCCloud分散式微服務架構
- 業餘草 SpringCloud教程 | 第二篇: 服務消費者(rest+ribbon)(Finchley版本)SpringGCCloudREST
- SpringCloud分散式微服務雲架構第二篇: 服務消費者(rest+ribbon)(Finchley版本)SpringGCCloud分散式微服務架構REST
- YouGov:只有35%的消費者信任無人機送餐服務Go無人機
- Springcloud電子商城系統 java B2B2C-服務消費者(rest+ribbon)SpringGCCloudJavaREST
- 讓消費者享受更優質的通訊服務BIQ
- spring cloud微服務分散式雲架構-服務消費者FeignSpringCloud微服務分散式架構
- hyperf從零開始構建微服務(二)——構建服務消費者微服務
- SpringCloud微服務系列(4): 服務發現與消費及客戶端負載均衡RibbonSpringGCCloud微服務客戶端負載
- SpringBoot整合Kafka(生產者和消費者都是SpringBoot服務)Spring BootKafka
- spring cloud微服務分散式雲架構(三)-服務消費者(Feign)SpringCloud微服務分散式架構
- 消費者雲CSE微服務實踐微服務
- 轉載:史上最簡單的SpringCloud教程 | 第二篇: 服務消費者(rest+ribbon)(Finchley版本)SpringGCCloudREST
- 圖解Dubbo,Dubbo服務消費詳解圖解
- Kafka 消費組消費者分配策略Kafka
- Java springboot B2B2C o2o多使用者商城 springcloud架構 (三) 服務消費者(Feign)JavaSpring BootGCCloud架構
- 使用多種客戶端消費WCF RestFul服務(一)——服務端客戶端REST服務端
- spring cloud微服務分散式雲架構(二)-服務消費者(rest+ribbon)SpringCloud微服務分散式架構REST
- (七)spring cloud微服務分散式雲架構-服務消費者(rest+ribbon)SpringCloud微服務分散式架構REST
- 如何使用 ABAP 程式消費 SAP ABAP OData 服務
- kafka消費者消費訊息的流程Kafka
- [菜鳥SpringCloud入門]第四章:遠端呼叫服務實戰SpringGCCloud
- Spring Boot 整合 RabbitMQ 訊息事務(消費者)Spring BootMQ
- 破解消費者密碼:線上消費者最重視什麼密碼
- RocketMQ之消費者啟動與消費流程MQ