Spring Cloud -- Ribbon負載均衡(初步配置)
前言
不知道大家有沒有這樣的經驗......某天忽然很想吃麥當當,就準備去買,不過適逢下班時間用餐時間,人潮爆多,但還是很想吃,就咬著牙進去,進去之後有三個點餐的櫃台,都排滿了人,但為了想要吃到香噴噴的麥當當,看了看哪個隊伍人最少,就默默地走去最少的隊伍等排隊......然後,可以看到雖然店裡人很多,但大家都算是平均的排在3個櫃台前,店員也能按部就班地為客人點餐並出餐。
一個系統也是一樣,都需要服務成千上萬個消費端,面對那麼多的消費端,不可能只有一個Service端來工作,流量大時肯定爆炸,停擺,最後下線......因此多個Service端是必然的結果,但,電腦沒那麼聰明,會像人一樣自己找最少人的地方排隊,我們需要有一個機制來完成這項任務,達到負載均衡的目標。
負載均衡是什麼?
負載均衡 LB (Load Balance),是微服務或是分散式叢集中經常使用的一種應用,簡單的說,就是將所有用戶的請求,平分到多個Service端上,使系統負擔不會在某一端過大導致崩潰。LB區分兩種形式:
1. 集中式LB:在服務方和消費方之間使用的獨立負載均衡設施,由該設施把訪問請求通過某種策略轉發至服務方,Ex:F5、nginx。
2. 程式式LB:將LB的邏輯整合至消費方,消費方再從服務註冊中心獲知有哪些地址可用,再從這些地址選出最適合的伺服器,Ex:Ribbon。
Spring Cloud Ribbon 是基於Netflix Ribbon實現的一套針對客戶端的負載均衡工具,簡單來說,就是在配置文件中列出LB後面的所有機器,Ribbon會自動幫助你基於某種規則(如輪詢、隨機連接等)去連接這些機器,Ribbon也可以實現自訂義的負載均衡算法。
負載均衡初步配置
那我們就開始來了解一下如何做負載均衡的初步配置,程式部分延續上一篇 "Spring Cloud -- Eureka集群配置" 來繼續做下去,因為Ribbon是需要和Eureka整合的,如果還沒有看過再請先去看一下囉~
1. 首先,將 microservicecloud-consumer-dept-80 的pom.xml新增Ribbon相關配置,程式如下:
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.jacob.springcloud</groupId>
<artifactId>microservicecloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>microservicecloud-consumer-dept-80</artifactId>
<description>部門微服務消費者</description>
<dependencies>
<dependency><!-- 自己定義的api -->
<groupId>com.jacob.springcloud</groupId>
<artifactId>microservicecloud-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 修改後立即生效,熱部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- Ribbon相關 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!-- Ribbon相關 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</dependency>
</dependencies>
</project>
2. 需將Ribbon註冊至Eureka,在 microservicecloud-consumer-dept-80 的 application.yml中加入Eureka的集群配置,程式如下:
server:
port: 80
eureka:
client:
register-with-eureka: true #註冊到Eureka註冊中心
service-url:
# defaultZone: http://localhost:7001/eureka/ #單機版Eureka註冊中心
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
3. 為了達到讓客戶端獲得負載均衡的功能,在 microservicecloud-consumer-dept-80 的 ConfigBean.java中的Rest服務中加入@LoadBalanced配置註解,程式如下:
package com.jacob.springcloud.cfgbeans;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ConfigBean {//@Configuration + ConfigBean 等於applicationContext.xml文件
@Bean
@LoadBalanced //Spring Cloud Ribbon是基於Netflix Ribbon實現的一套客戶端 負載均衡的工具
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
4. 在 microservicecloud-consumer-dept-80 的主啟動class -> DeptConsumer80_App.java中加入@EnableEurekaClient,程式如下:
package com.jacob.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class DeptConsumer80_App {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer80_App.class, args);
}
}
5. 修改客戶端訪問類 DeptController_Consumer.java,將REST_URL_PREFIX改成我們的微服務名,至此,才算我們正式的微服務訪問,程式如下:
package com.jacob.springcloud.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import com.jacob.springcloud.entities.Dept;
@RestController
public class DeptController_Consumer {
// private static final String REST_URL_PREFIX = "http://localhost:8001";
private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT";
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/consumer/dept/add")
public boolean add(Dept dept) {
return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
}
@RequestMapping(value = "/consumer/dept/get/{id}")
public Dept get(@PathVariable("id") Long id) {
return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class);
}
@SuppressWarnings("unchecked")
@RequestMapping(value = "/consumer/dept/list")
public List<Dept> list() {
return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
}
// 測試@EnableDiscoveryClient,消費端可以調用服務發現
@RequestMapping(value = "/consumer/dept/discovery")
public Object discovery() {
return restTemplate.getForObject(REST_URL_PREFIX + "/dept/discovery", Object.class);
}
}
6. 接著,我們依序啟動Eureka的7001、7002、7003、Server端的8001及客戶端的80(目前已啟動5個微服務了,可能已經耗掉快7G的記憶體,如果記憶體不足的話可能會跑不動喔),打開網頁輸入http://localhost/consumer/dept/get/1,可以看到我們一樣成功訪問到微服務
7. 連接http://eureka7003.com:7003/,可以看到我們的微服務名已被改為正式的名稱MICROSERVICECLOUD-DEPT
從這裡可以得出一個結論:Ribbon和Eureka整合後,可以直接調用微服務,而不必再關心該微服務的地址和阜號是多少,也就是我們之後再做的每一個微服務,直接調用MICROSERVICECLOUD-DEPT即可。
至此,我們已完成了Ribbon的初步配置,下一篇文章將繼續來分享Ribbon的負載均衡實作功能,謝謝大家~
參考文獻
Spring Cloud負載均衡神器——Ribbon簡介與基本使用
尚硅谷Spring Cloud教程