Spring Cloud Ribbon 是一一基於HTTP 和TCP 的客戶端負載均衡工具,它基於NetflixRibbon實現。通過Spring Cloud 的封裝,可以讓我們輕松地將面向服務的REST 模板請求自動轉換成客戶端負載均衡的服務調用。Spring Cloud Ribbon 雖然只是一個工具類框架,它不像服務注冊中心、配置中心、API 網關那樣需要獨立部署,但是它兒乎存在於每一個SpringCloud 構建的微服務和基礎設施中。因為微服務間的調用,API 網關的請求轉發等內容,實際上都是通過Ribbon 來實現的,包括后續我們將要介紹的Feign,它也是基於Ribbon實現的工具。所以,對Spring Cloud Ribbon 的理解和使用,對於我們使用Spring Cloud 來構建微服務非常重要。
在這里,我們將介紹如何使用Ribbon 來實現客戶端的負載均衡,並且通過源碼分析來了解Ribbon 實現客戶端負載均衡的基本原理。
客戶端負載均衡
負載均衡在系統架構中是一個非常重要,並且是不得不去實施的內容。因為負載均衡是對系統的高可用、網絡壓力的緩解和處理能力擴容的重要手段之一。我們通常所說的負載均衡都指的是服務端負載均衡,其中分為硬件負載均衡和軟件負載均衡。硬件負載均衡主要通過在服務器節點之間安裝專門用於負載均衡的設備,比如F5 等; 而軟件負載均衡則是通過在服務器上安裝一些具有均衡負載功能或模塊的軟件來完成請求分發工作,比如Nginx 等。不論采用硬件負載均衡還是軟件負載均衡,只要是服務端負載均衡都能以架構方式構建起來:
硬件負載均衡的設備或是軟件負載均衡的軟件模塊都會維護一個下掛可用的服務端清單,通過心跳檢測來剔除故障的服務端節點以保證清單中都是可以正常訪問的服務端節點。當客戶端發送請求到負載均衡設備的時候,該設備按某種算法(比如線性輪詢、按權重負載、按流量負載等) 從維護的可用服務端清單中取出一台服務端的地址,然后進行轉發。
而客戶端負載均衡和服務端負我均衡最大的不同點在於上面所提到的服務清單所存儲的位置。在客戶端負載均衡中,所有客戶端節點都維護着自己要訪問的服務端清單,而這些服務端的清單來自於服務注冊中心,比如Eureka 服務端。同服務端負載均衡的架構類似,在客戶端負載均衡中也需要心跳去維護服務端清單的健康性,只是這個步驟需要與服務注冊中心配合完成。在Spring Cloud 實現的服務治理框架中,默認會創建針對各個服務治理框架的Ribbon 自動化整合配置,比如Eureka 中的org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration,Consul中的org.springframework.cloud.consul.discovery.RibbonConsulAuto- Configurationo 在實際使用的時候,我們可以通過查看這兩個類的實現,以找到它們的配置詳情來幫助我們更好地使用它。
通過SpringCloudRibbon 的封裝,我們在微服務架構中使用客戶端負載均衡調用非常簡單,只需要如下兩步:
1.服務提供者只需要啟動多個服務實例並注冊到一個注冊中心或是多個相關聯的服務注冊中心。
2. 服務消費者直接通過調用被@LoadBalanced 注解修飾過的RestTemplate來實現面向服務的接口調用。
這樣,我們就可以將服務提供者的高可用以及服務消費者的負載均衡調用一起實現了。 其中,我們使用了個非常有用的對象RestTemplate.該對象會使用Ribbon 的自動化配置,同時通過配置@LoadBalanced 還能夠開啟客戶端負載均衡。之前我們演示了通過RestTemplate實現了最簡單的服務訪問,下面我們將詳細介紹RestTemplate 針對幾種不同請求類型和參數類型的服務調用實現。
GET 請求
在RestTemplate 中,對GET 請求可以通過如下兩個方法進行調用實現。 第一種: getForEntity 函數。該方法返回的是ResponseEntity,該對象是Spring對HTTP 請求響應的封裝,其中主要存儲了HTTP 的幾個重要元素,比如HTTP 請求狀態馬的枚舉對象HttpStatus (也就是我們常說的404、500 這些錯誤碼)、在它的父類ittpEntity中還存儲着HTTP請求的頭信息對象HttpHeaders 以及泛型類型的請求體時象。比如下面的例子,就是訪問USER-SERVER服務的/user 請求,同時最后一個參數idi 會替換url 中的(1}占位符,而返回的ResponseEntity 對象中的body 內容類型:根據第二個參數轉換為String類型。
RestTemplate restTemplate 二newRestTemplate () ;
ResponseEntityStri xesponseEntity 一restTemplate.getFor ("http: //USER-RVICE/user?name={1}",string.class,"didi") ;
String body= responseEntity.getBody () ;
若我們希望返回的body是一個User對象類型,也可以這樣實現:
Restremplate restTemplate= new Restremplate() ;
ResponseEntity responseEntity -restremplate.get "http: /USER- vICE/user?name={1}",User.class,"didi") ;
user body= responseEntity.getBody () ;
上面的例子是比較常用的方法
POST 請求
在RestTemplate 中,
對POST 請求時可以通過如下三個方法進行調用實現。
第一種: postEorEntity 函數。該方法同GET 請求中的getrorEntity 類似,會
在調用后返回ResponseEntity對象,其中T 為請求響應的body 類型。
比如下面這
個例子,使用postForEntity 提交POST請求到USER-SERVICE 服務的/user 接口,
提交的body 內容為user對象,請求響應返回的body 類型為String。
RestTemplate restTemplate= new RestTemplate () ;
User user = new User ("didi",30) ;
ResponseEntity responseEntity=
restTemplate.postForEntity ("http: //USER-SERVICE/user",user,String.class) ;
String body= responseEntity.getBody () ;
postForEntity 函數也實現了三種不同的重載方法。
PUT 請求
GResTemplate中,對PUT請求可以通過pot 方法進行調用實現,比如,
RestTemplaterestTemplate=new RestTemplate();
Long id = 100011;
User user=new User("didi",40);
restemplate.put(http://USER-SERVICE/user/{1} ”,user,id ;
put 函數也實現了三種不同的重載方法:
1.put (string url,Object request,0bject...urlVariables)
2.put (Stringurl,Object request,Map urlVariables)
3.put (URI url,object request )
put函數為void類型,所以沒有返回內容,也就沒有其他函數定義的responserype參數,除此之外的其他傳入參數定義與用法與postforobject基本一致。
DELETE 請求
在RestTemplate 中,對DELETE 請求可以通過delete 方法進行調用實現,比如:
RestTemplate restTemplate = new RestTemplate () ;
Long id = 10001L;restTemplate.delete ("http: //USER-SERVICE/user/ (1}",id) ;
delete 函數也實現了三種不同的重載方法:
1.delete (String url,0bject...urlVariables)
2.delete (String url,Map urlVariables)
3.delete (URi url)由於我們在進行REST請求時,通常都將DELETE 請求的唯一標識拼接在url 中,所DELETE 請求也不需要equest 的body信息,就如上面的三個函數實現一樣,非常簡單。1指定DELETE 請求的位置,urlVariables 綁定url 中的參數即可。
想學習更多更詳細的知識的,在此我向大家推薦一個交流學習群:744642380 里面會分享一些資深架構師錄制的視頻錄像:有Spring,MyBatis,Netty源碼分析,高並發、高性能、分布式、微服務架構的原理,JVM性能優化這些成為架構師必備的知識體系。還能領取免費的學習資源,目前受益良多
