ribbon的使用

簡(jiǎn)介

spring cloud ribbon 是一個(gè)基于http和TCP客戶度負(fù)載均衡工具,它基于Netflix Ribbon實(shí)現(xiàn)。通過(guò)Spring Cloud的封裝,可以讓我們輕松地將面向服務(wù)的REST模版請(qǐng)求自動(dòng)轉(zhuǎn)換成客戶端負(fù)載均衡的服務(wù)調(diào)用。

負(fù)載均衡

負(fù)載均衡有兩種,一般是服務(wù)器負(fù)載均衡,分為硬件負(fù)載均衡和軟件負(fù)載均衡.
硬件負(fù)載均衡是用于服務(wù)器節(jié)點(diǎn)之間的負(fù)載均衡設(shè)備
軟件負(fù)載均衡是通過(guò)在服務(wù)器上安裝一些負(fù)載均衡的軟件,來(lái)完成一些請(qǐng)求分發(fā)的工作,例如我們現(xiàn)在用的Nginx


負(fù)載均衡架構(gòu)圖.png

搭建ribbon工程

創(chuàng)建一個(gè)spring boot的工程,然后勾選上


ribbon創(chuàng)建.png

添加配置文件

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8080/eureka
server:
  port: 8764
spring:
  application:
    name: service-ribbon

在啟動(dòng)類上添加

@EnableEurekaClient
@EnableDiscoveryClient

我們需要使用對(duì)象RestTemplate。該對(duì)象會(huì)使用Ribbon的自動(dòng)化配置,同時(shí)通過(guò)配置@LoadBalanced開(kāi)啟客戶端負(fù)載均衡。

    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

測(cè)試

編寫(xiě)一個(gè)測(cè)試類,注入template

@RestController
public class RibbonController {
    @Autowired
    RestTemplate restTemplate;

    @RequestMapping("/helloRibbon")
    public String helloRibbon(){
        //訪問(wèn)hello-service服務(wù)的hello接口
        ResponseEntity<String> forEntity = restTemplate.getForEntity("http://service-user/test", String.class);
        System.out.println(forEntity);
        return forEntity.getBody();
    }
}

啟動(dòng)兩個(gè)producer
可以在注冊(cè)中心看到

注冊(cè)中心.png

多次訪問(wèn)http://localhost:8764/helloRibbon
查看控制臺(tái)就可以看到兩個(gè)user分別被訪問(wèn)了

請(qǐng)求方式

GET 請(qǐng)求

    在RestTemplate中,對(duì)GET請(qǐng)求可以通過(guò)如下兩個(gè)方法進(jìn)行調(diào)用實(shí)現(xiàn)。

    第一種:getForEntity函數(shù)。該方法返回的是ResponseEntity,該對(duì)象是Spring對(duì)HTTP請(qǐng)求響應(yīng)的封裝,其中主要存儲(chǔ)了HTTP的幾個(gè)重要元素,比如HTTP請(qǐng)求狀態(tài)碼的枚舉對(duì)象HttpStatus(也就是我們常說(shuō)的404、500這些錯(cuò)誤碼)、在它的父類HttpEntity中還存儲(chǔ)著HTTP請(qǐng)求的頭信息對(duì)象HttpHeaders以及泛型類型的請(qǐng)求體對(duì)象。比如下面的例子,就是訪問(wèn)USER-SERVER服務(wù)端/user請(qǐng)求,同時(shí)最后一個(gè)參數(shù)didi會(huì)替換url中的{1}占位符,而返回的ResponseEntity對(duì)象的body內(nèi)容類型會(huì)根據(jù)第二個(gè)參數(shù)轉(zhuǎn)換為String類型。
image
    若我們希望返回body是一個(gè)User對(duì)象類型,也可以這樣實(shí)現(xiàn):
image
    上面的例子是比較常用的方法,getForEntity函數(shù)實(shí)際上提供了以下三種不同的重載實(shí)現(xiàn)。

??getForEntity(String url, Class responseType,Object... urlVariables);

    該方法提供了三個(gè)參數(shù),其中url為請(qǐng)求的地址,responseType為請(qǐng)求響應(yīng)體body的包裝類型,urlVariables為url中的參數(shù)綁定。GET請(qǐng)求的參數(shù)綁定通過(guò)使用url中拼接的方式,比如http://USER-SERVICE/user?name=didi,我們可以像這樣自己將參數(shù)拼接到 url中,但更好的方法是在url中使用占位符并配合urlVariables參數(shù)實(shí)現(xiàn)GET請(qǐng)求的參數(shù)綁定,比如url定義為:getForEntity("http://USER-SERVICE/user?name={1}", String.class, "didi"),其中第三個(gè)參數(shù)didi會(huì)替換掉url中的{1}站位符。這里需要注意的是,由于urlVariables參數(shù)是一個(gè)數(shù)組,所以它的順序會(huì)對(duì)應(yīng)url中占位符定義的數(shù)字順序。

??getForEntity(String url, Class responseType, Map urlVariables);

    該方法提供的參數(shù)重,只有urlVariables的參數(shù)類型與上面的方法不同。這里使用了Map類型,所以使用該方法進(jìn)行參數(shù)綁定時(shí)需要再占位符中指定Map中的參數(shù)的key值,比如url定義為http://USER-SERVICE/user?name={name},在Map類型的urlVariables中,我們就需要put一個(gè)key為name的參數(shù)來(lái)綁定url中{name}占位符的值,比如:
image

??getForEntity(URI url, Class responseType)

    該方法使用uri對(duì)象來(lái)代替之前url和urlVariables參數(shù)來(lái)指定訪問(wèn)地址和參數(shù)綁定。URI是JDK java.net包下單一個(gè)類,它表示一個(gè)統(tǒng)一資源標(biāo)識(shí)符(Uniform Resource Identifier)引用,比如下面的例子:
image
    更多關(guān)于如何定義一個(gè)URI的方法可以參見(jiàn)JDK文檔,這里不做詳細(xì)說(shuō)明。

    第二種:getForObject函數(shù)。該方法可以理解為對(duì)getForEntity的進(jìn)一步封裝,它通過(guò)HttpMessageConverterExtractor對(duì)HTTP的請(qǐng)求響應(yīng)體body內(nèi)容進(jìn)行對(duì)象轉(zhuǎn)換,實(shí)現(xiàn)請(qǐng)求直接返回包裝好的對(duì)象內(nèi)容。比如:

RestTemplate restTemplate = new RestTemplate();

String result = restTemplate.getForObject(uri, String.class);

    當(dāng)body是一個(gè)User對(duì)象時(shí),可以直接這樣實(shí)現(xiàn):

RestTemplate restTemplate = new RestTemplate();

User result = restTemplate.getForObject(uri, User.class);

    當(dāng)不需要關(guān)注請(qǐng)求響應(yīng)除body外的其他內(nèi)容時(shí),該函數(shù)就非常好用,可以少一個(gè)從Response中獲取body的步驟。它與getForEntity函數(shù)類似,也提供了三種不同的重載實(shí)現(xiàn)。

??getForObject(String url, Class responseType, Object ... urlVariables)

??getForObject(String url, Class responseType, Map urlVariables)

??getForObject(URI url, Class responseType)

POST 請(qǐng)求

    在RestTemplate中,對(duì)POST請(qǐng)求時(shí)可以通過(guò)如下三個(gè)方法調(diào)用實(shí)現(xiàn)。

??第一種:postForEntity函數(shù)。

    該方法同GET請(qǐng)求中的getForEntity類似,會(huì)在調(diào)用后返回ResponseEntity對(duì)象,其中T為請(qǐng)求響應(yīng)的body類型。比如下面這個(gè)例子,使用postForEntity提交POST請(qǐng)求到USER-SERVICE服務(wù)的/user接口,提交的body內(nèi)容為user對(duì)象,請(qǐng)求響應(yīng)返回的body類型為String。
image

postForEntity函數(shù)也實(shí)現(xiàn)了三種不同的重載方法。

image

??postForEntity(String url, Object request, Class responseType, Object... uriVariables)

??postForEntity(String url, Object request, Class responseType, Map uriVariables)

??postForEntity(URI url, Object request, Class responseType)

    這些函數(shù)中的參數(shù)用法大部分與getForEntity一致,比如,第一個(gè)重載函數(shù)和第二個(gè)重載函數(shù)中的uriVariables參數(shù)都用來(lái)對(duì)url中的參數(shù)進(jìn)行綁定使用;responseType參數(shù)是對(duì)請(qǐng)求響應(yīng)的body內(nèi)容的類型定義。這里需要注意的是新增加的request參數(shù),該參數(shù)可以是一個(gè)普通對(duì)象,也可以是一個(gè)HttpEntity對(duì)象。如果是普通對(duì)象,而非HttpEntity對(duì)象的時(shí)候,RestTemplate會(huì)將請(qǐng)求對(duì)象轉(zhuǎn)換為一個(gè)HttpEntity對(duì)象來(lái)處理;其中Object就是request的類型,request內(nèi)容會(huì)唄視作完整的body來(lái)處理;而如果request是一個(gè)HttpEntity對(duì)象,那么就會(huì)被當(dāng)作一個(gè)完成的HTTP請(qǐng)求對(duì)象來(lái)處理,這個(gè)request中不僅包含了body的內(nèi)容,也包含了header的內(nèi)容。

??第二種:postForObject函數(shù)。

    該方法也跟getForObject的類型類似,它的作用就是簡(jiǎn)化postForEntity的后續(xù)處理。通過(guò)直接將請(qǐng)求響應(yīng)的body內(nèi)容包裝成對(duì)象來(lái)返回使用,比如下面的例子:
image

postForObject函數(shù)也實(shí)現(xiàn)了三種不同的重載方法:

image

??postForObject(String url, Object request, Class responseType, Object... uriVariables)

??postForObject(String url, Object request, Class responseType, Map uriVariables)

??postForObject(URI url, Object request, Class responseType)

    這三個(gè)函數(shù)除了返回的對(duì)象類型不同,函數(shù)的傳入?yún)?shù)均與postForEntity一致,因此可參考之前postForEntity的說(shuō)明。

??第三種:postForLocation函數(shù)。

    該方法實(shí)現(xiàn)了以POST請(qǐng)求提交資源,并返回新的資源的URI,比如下面的例子:
image
    postForLocation函數(shù)也實(shí)現(xiàn)了三種不同的重載方法:
image

??postForLocation(String url, Object request, Object... uriVariables)

??postForLocation(String url, Object request, Map uriVariables)

??postForLocation(URI url, Object request)

由于postForLocation函數(shù)會(huì)返回新資源的URI,該URI就相當(dāng)于指定了返回類型,所以此方法實(shí)現(xiàn)的POST請(qǐng)求不需要像postForEntity和postForObject那樣指定responseType。其他的參數(shù)用法相同。

參考文章:http://www.itdecent.cn/p/1bd66db5dc46

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容