Java Spring Cloud Ribbon

Spring Cloud -- Ribbon負載均衡(初步配置)

黃翰暉 Jacob Huang 2021/07/08 11:40:26
74

前言

      不知道大家有沒有這樣的經驗......某天忽然很想吃麥當當,就準備去買,不過適逢下班時間用餐時間,人潮爆多,但還是很想吃,就咬著牙進去,進去之後有三個點餐的櫃台,都排滿了人,但為了想要吃到香噴噴的麥當當,看了看哪個隊伍人最少,就默默地走去最少的隊伍等排隊......然後,可以看到雖然店裡人很多,但大家都算是平均的排在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教程

 

 

黃翰暉 Jacob Huang