一、負載均衡的簡介:
負載均衡是高可用架構的一個關鍵組件,主要用來提高性能和可用性,通過負載均衡將流量分發到多個服務器,多服務器能夠消除單個服務器的故障,減輕單個服務器的訪問壓力。
1、服務端負載均衡:客戶端請求到負載均衡服務器,負載均衡服務器根據自身的算法將該請求轉給某台真正提供業務的服務器,該服務器將響應數據給負載均衡服務器,負載均衡服務器最后將數據返回給客服端,服務端負載均衡完全由服務器處理,客戶端不需要做任何事情。常見例子,例如:nginx
2、客服端負載均衡:基於客戶端的負載均衡,簡單的說就是在客戶端程序里面,維護一組服務器引用,自己設定一個調度算法,在向服務器發起請求的時候,先執行調度算法計算出向哪台服務器發起請求,然后再發起請求給服務器,常見例子,例如:Ribbon
二、Ribbon的簡介:
上一篇文章,講了服務的注冊和發現。在微服務架構中,業務都會被拆分成一個獨立的服務,服務與服務的通訊是基於http restful的。Spring cloud提供兩種服務調度方式,一種方式是ribbon+restTemplate,另一種方式是feign。這章先講解下基於ribbon+restful的服務請求方式。
ribbon是一個負載均衡客戶端,提供了很多在HTTP和TCP客戶端之上的控制。Feign內部也已經使用了Ribbon, 所以只要使用了@FeignClient注解,也能實現本章功能。
三、准備集群服務:
通過標題我們也知道ribbon有負載均衡的功能,所以首先需要准備一個服務器集群,這一篇文章基於上一篇文章的工程,繼續進行完善的。
1. 啟動eureka-server 工程,eureka注冊中心就啟動了。
2. 啟動springcloud-eureka-client工程,上篇文章我們知道springcloud-eureka-client工程的端口為9300。
3. 將springcloud-eureka-client工程的端口改成9400(修改application.properties文件),然后再啟動springcloud-eureka-client。
通過上面三個步驟,我們就相當於在eureka服務上啟動了兩個springcloud-eureka-client服務,但是端口號不同,輸入 http://localhost:8761/ 查看頁面效果

四、新建Ribbon客戶端模塊:
重新新建一個spring-boot工程,取名為:springcloud-ribbon-client
<parent>標簽就是引入我們第一章節新建的父工程的pom.xml文件,具體可參考:一起來學Spring Cloud | 第一章 :如何搭建一個多模塊的springcloud項目
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.haly</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.haly</groupId>
<artifactId>springcloud-ribbon-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud-ribbon-client</name>
<description>新建一個springcloud項目</description>
<dependencies>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
新增springcloud-ribbon-client的配置文件application.properties
server.port=9500 spring.application.name=springcloud-ribbon-client eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
新增啟動類SpringcloudRibbonClientApplication
@EnableDiscoveryClient向服務中心注冊,並且注冊了一個叫restTemplate的bean。
@ LoadBalanced注解表明,這個restRemplate是需要做負載均衡的。
package com.haly;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
public class SpringcloudRibbonClientApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudRibbonClientApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
新建一個service類,用來調用第二章在springcloud-eureka-client模塊中的hello方法,springcloud-eureka-client模塊的搭建,詳情參考:一起來學Spring Cloud | 第二章:服務注冊和發現組件 (Eureka)
package com.haly.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class RibbonService {
@Autowired
RestTemplate restTemplate;
public String getHello(String name) {
return restTemplate.getForObject("http://springcloud-eureka-client/hello?name="+name,String.class);
}
}
ps: 我們請求時用springcloud-eureka-client服務名代替了ip地址,在ribbon中它會根據服務名來選擇具體的服務實例,根據服務實例在請求的時候會用具體的url替換掉服務名。
新建一個controller名為:RibbonController,來接收瀏覽器訪問,RibbonController的getHello方法調用RibbonService的getHello方法
package com.haly.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.haly.service.RibbonService;
@RestController
public class RibbonController {
@Autowired
RibbonService ribbonService;
@GetMapping(value = "/getHello")
public String getHello(@RequestParam String name) {
return ribbonService.getHello(name);
}
}
打開瀏覽器輸入http://localhost:9500/getHello?name=young碼農 多次訪問頁面會交替出現如下結果


從上圖可以驗證,當我們通過調用restTemplate.getForObject("http://springcloud-eureka-client/hello?name="+name,String.class)方法時,已經做了負載均衡,訪問了不同的端口的服務實例。
五、實驗總結:
本章結束后,項目結構:

1. 一個服務注冊中心,eureka server,端口為8761
2. springcloud-eureka-client工程跑了兩個實例,端口分別為9300,9400,分別向服務注冊中心注冊
3. springcloud-ribbon-client端口為9500,向服務注冊中心注冊
4. 當springcloud-ribbon-client通過restTemplate調用springcloud-eureka-client的hello接口時,因為用ribbon進行了負載均衡,會輪流的9300和9400 兩個服務端口的hello接口
