Spring Cloud Ribbon 是一個(gè)基于Http和TCP的客戶端負(fù)載均衡工具,基于Netflix Ribbon實(shí)現(xiàn)的。它不像服務(wù)注冊(cè)中心、配置中心、API網(wǎng)關(guān)那樣獨(dú)立部署,但是它幾乎存在于每個(gè)微服務(wù)的基礎(chǔ)設(shè)施中。
Ribbon架構(gòu)圖

Ribbon負(fù)載均衡策略

Ribbon默認(rèn)的策略是輪詢,我們可以自定義負(fù)載策略來(lái)覆蓋默認(rèn)的,當(dāng)然也可以通過(guò)配置指定使用哪些策略。
負(fù)載均衡概念
負(fù)載均衡技術(shù)在現(xiàn)有網(wǎng)絡(luò)結(jié)構(gòu)之上提供了一種廉價(jià)、有效、透明的方法,來(lái)擴(kuò)展網(wǎng)絡(luò)設(shè)備和服務(wù)器的帶寬、增加吞吐量、加強(qiáng)網(wǎng)絡(luò)數(shù)據(jù)處理能力、提高網(wǎng)絡(luò)的靈活性和可用性。它有兩方面的含義:首先,大量的并發(fā)訪問(wèn)或數(shù)據(jù)流量分擔(dān)到多臺(tái)節(jié)點(diǎn)設(shè)備上分別處理,減少用戶等待響應(yīng)的時(shí)間;其次,單個(gè)重負(fù)載的運(yùn)算分擔(dān)到多臺(tái)節(jié)點(diǎn)設(shè)備上做并行處理,每個(gè)節(jié)點(diǎn)設(shè)備處理結(jié)束后,將結(jié)果匯總,返回給用戶,系統(tǒng)處理能力得到大幅度提高。
負(fù)載均衡是對(duì)系統(tǒng)的高可用,網(wǎng)絡(luò)壓力的緩解和處理能力擴(kuò)容的重要手段之一。
硬件負(fù)載均衡:
主要通過(guò)在服務(wù)節(jié)點(diǎn)之間安裝專門(mén)的負(fù)載均衡設(shè)備,比如F5
詳細(xì)參照百度百科:https://baike.baidu.com/item/F5%E6%96%B9%E6%A1%88/1121377?fr=aladdin
軟件負(fù)載均衡
實(shí)現(xiàn)方式有兩種,分別是服務(wù)端的負(fù)載均衡和客戶端的負(fù)載均衡
服務(wù)端負(fù)載均衡:在服務(wù)端安裝一些具有均衡負(fù)載功能或者模塊的軟件來(lái)完成請(qǐng)求的分發(fā)工作,比如Nginx。
當(dāng)瀏覽器向后臺(tái)發(fā)出請(qǐng)求的時(shí)候,會(huì)首先向反向代理服務(wù)器發(fā)送請(qǐng)求,反向代理服務(wù)器會(huì)根據(jù)客戶端部署的ip:port映射表以及負(fù)載均衡策略,來(lái)決定向哪臺(tái)服務(wù)器發(fā)送請(qǐng)求,一般會(huì)使用到nginx反向代理技術(shù)。

客戶端負(fù)載均衡:當(dāng)瀏覽器向后臺(tái)發(fā)出請(qǐng)求的時(shí)候,客戶端會(huì)向服務(wù)注冊(cè)器(例如Eureka Server),拉取注冊(cè)到服務(wù)器的可用服務(wù)信息,然后根據(jù)負(fù)載均衡策略,直接命中哪臺(tái)服務(wù)器發(fā)送請(qǐng)求。這整個(gè)過(guò)程都是在客戶端完成的,并不需要反向代理服務(wù)器的參與。
在微服務(wù)中最基本的兩個(gè)角色是服務(wù)提供者與服務(wù)消費(fèi)者。
服務(wù)提供者:服務(wù)的被調(diào)用方(為其他服務(wù)提供服務(wù)的服務(wù))
服務(wù)消費(fèi)者:服務(wù)的調(diào)用方(依賴其他服務(wù)的服務(wù))
之前我們已經(jīng)嘗試了好幾種服務(wù)注冊(cè)方式,注冊(cè)了服務(wù),肯定需要被調(diào)用的,也就是消費(fèi)。
服務(wù)調(diào)用方式實(shí)現(xiàn)方式RestTemplate+Ribbon
使用RestTemplate消費(fèi)SpringBoot的Restful服務(wù)
前提
需要一個(gè)服務(wù)注冊(cè)中心,兩個(gè)服務(wù)提供者和一個(gè)消費(fèi)者
因?yàn)橹挥袃蓚€(gè)以上的服務(wù)提供者提供相同的服務(wù)才可以體現(xiàn)出負(fù)載均衡
服務(wù)注冊(cè)中心和服務(wù)提供者都使用Spring Cloud Eureka
實(shí)現(xiàn)服務(wù)提供者的Restful接口
之前已經(jīng)實(shí)現(xiàn)過(guò)服務(wù)注冊(cè)中心和服務(wù)提供者
不過(guò)之前的服務(wù)提供者并沒(méi)有提供接口給消費(fèi)者使用
@RestController
public class DiscoveryController {
@Autowired
private DiscoveryClient discoveryClient;
@Value("${server.port}")
private String ip;
@GetMapping("/client")
public String client() {
String services = "調(diào)用的服務(wù)是: " + discoveryClient.getServices()+" 對(duì)應(yīng)的端口號(hào) :"+ip;
System.out.println("調(diào)用的服務(wù)是: " + discoveryClient.getServices()+" 對(duì)應(yīng)的端口號(hào) :"+ip);
return services;
}
}
實(shí)現(xiàn)服務(wù)消費(fèi)者Ribbon
一開(kāi)始肯定打算是引入Spring Cloud Ribbon依賴,不過(guò)Spring Cloud Eureka依賴中已經(jīng)有
Ribbon的依賴了。單獨(dú)引入Ribbon依賴可能注冊(cè)不了服務(wù)

在項(xiàng)目的外部
Jar包目錄中可以發(fā)現(xiàn)Spring Cloud Eureka依賴中已經(jīng)有Ribbon的依賴了所以,主要引入的依賴和Eureka客戶端的一樣
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
在項(xiàng)目啟動(dòng)類上添加@EnableEurekaClient注解,消費(fèi)者和服務(wù)提供者一樣,都需要到注冊(cè)中心中注冊(cè)
并且使用@bean像Spring容器中注入一個(gè)restTemplate對(duì)象,@LoadBalanced注解表明這個(gè)
restRemplate開(kāi)啟負(fù)載均衡的功能。
@SpringBootApplication
@EnableEurekaClient
public class SpringcloudConsumerRibbonApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(SpringcloudConsumerRibbonApplication.class, args);
}
}
下面來(lái)寫(xiě)一個(gè)簡(jiǎn)單的服務(wù)消費(fèi)類
@RestController
public class RibbonController {
@Autowired
RestTemplate restTemplate;
@GetMapping("/consumer")
public String getMsg() {
return restTemplate.getForObject("http://springcloud-eureka-client/client", String.class);
}
}
restTemplate可以發(fā)送Get,Post,Put,Delete等請(qǐng)求
Get調(diào)用getForEntity()方法
Post調(diào)用postForObject()方法
Put調(diào)用put()方法
Delete調(diào)用delete()方法
getForEntity的第一個(gè)參數(shù)為我要調(diào)用的服務(wù)的地址,這里我調(diào)用了服務(wù)提供者提供的
/client接口(Eureka客戶端中已寫(xiě)好),getForEntity第二個(gè)參數(shù)String.class表示我希望返回的body類型是String
注意這里是通過(guò)服務(wù)名調(diào)用而不是服務(wù)地址,如果寫(xiě)成服務(wù)地址就沒(méi)法實(shí)現(xiàn)客戶端負(fù)載均衡了。
調(diào)用spring boot服務(wù)的時(shí)候,需要將服務(wù)的URL寫(xiě)死或者是寫(xiě)在配置文件中,一旦ip地址發(fā)生了變化,都需要改動(dòng)程序,并重新部署服務(wù),使用Ribbon的時(shí)候,可以有效的避免這個(gè)問(wèn)題。
restTemplate的所有用法可以參考
官方說(shuō)明文檔:https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html
在配置文件中加入相關(guān)配置
spring:
application:
name: eureka-consumer-ribbon
server:
port: 9999
eureka:
client:
service-url:
defaultZone: http://localhost:9090/eureka
整體項(xiàng)目結(jié)構(gòu)
Eureka服務(wù)端 端口號(hào)是9090
兩個(gè)Eureka客戶端 端口號(hào)分別是8081和8082 相同的服務(wù)名springcloud-eureka-client
Ribbon消費(fèi)者客戶端 端口號(hào)是9999
啟動(dòng)服務(wù)進(jìn)行測(cè)試
先啟動(dòng)服務(wù)端再啟動(dòng)客戶端,客戶端啟動(dòng)順序沒(méi)要求
訪問(wèn)http://localhost:9090服務(wù)注冊(cè)中心

在服務(wù)注冊(cè)中心可以看到,服務(wù)提供者和消費(fèi)者都注冊(cè)好了
對(duì)服務(wù)提供者的Restful服務(wù)進(jìn)行消費(fèi)
訪問(wèn)http://localhost:9999/consumer可以看到消費(fèi)的服務(wù)名和端口

刷新下頁(yè)面

繼續(xù)刷新就調(diào)用另一個(gè)端口的服務(wù)了
我試著刷新了11次頁(yè)面,在控制臺(tái)可以看到調(diào)用情況


說(shuō)明已經(jīng)消費(fèi)了Eureka客戶端提供的服務(wù),而且Ribbon已經(jīng)默認(rèn)實(shí)現(xiàn)了負(fù)載均衡
在整個(gè)程序中,最關(guān)鍵的就是在RestTemplate上標(biāo)記的@LoadBalanced注解,Spring Cloud Ribbon通過(guò)注解@LoadBalanced 來(lái)實(shí)現(xiàn)負(fù)載均衡
深入了解@LoadBalanced注解可以參考:
https://blog.csdn.net/qq_26562641/article/details/53332269