Spring Cloud負載均衡神器——Ribbon簡介與基本使用

老劉星星宇宇 發表於 2020-10-17
Spring


Ribbon簡介與基本使用



一、Ribbon 簡介

負載均衡在系統架構中是一個非常重要,並且是不得不去實施的內容。因為負載均衡是對系統的高可用、網路壓力的緩解和處理能力擴容的重要手段之一。我們通常所說的負載均衡都指的是服務端負載均衡,其中分為硬體負載均衡和軟體負載均衡。

  • 硬體負載均衡主要通過在伺服器節點之間按照專門用於負載均衡的裝置,比如F5等;
  • 軟體負載均衡則是通過在伺服器上安裝一些用於負載均衡功能或模組等軟體來完成請求分發工作,比如Nginx等。
    Spring Cloud Ribbon是一個基於HTTP和TCP的客戶端負載均衡工具,它基於Netflix Ribbon實現。

Ribbon 通過Spring Cloud的封裝,可以讓我們輕鬆地將面向服務的REST模版請求自動轉換成客戶端負載均衡的服務呼叫。Spring Cloud Ribbon雖然只是一個工具類框架,它不像服務註冊中心、配置中心、API閘道器那樣需要獨立部署,但是它幾乎存在於每一個Spring Cloud構建的微服務和基礎設施中。因為微服務間的呼叫,API閘道器的請求轉發等內容,實際上都是通過Ribbon來實現的,包括後續我們將要介紹的Feign,它也是基於Ribbon實現的工具。所以,對Spring Cloud Ribbon的理解和使用,對於我們使用Spring Cloud來構建微服務非常重要。
在這裡插入圖片描述


二、Ribbon 可以做什麼

Ribbon 的核心功能就是——LB,即負載均衡(Load Balance),在微服務或分散式叢集中經常用的一種應用

常見的負載均衡軟體:Nginx、Lvs等等

dubbo、SpringCloud中都給我們提供了負載均衡,其中,SpringCloud的負載均衡演算法可以自定義。

負載均衡簡單分類:

  • 集中式LB:在服務的消費方和提供方之間使用獨立的LB設施,如Nginx,由該設施負責把訪問請求通過某種策略轉發至服務的提供方。

    • 例如:Nginx
  • 程式式LB:將LB邏輯整合到消費方,消費方從服務註冊中心獲知有哪些地址可用,然後從這些地址中找到一個合適的伺服器。

    • 例如:Ribbon

Ribbon內部已有的一些負載均衡演算法:隨機、輪詢(預設)、權重等等


三、Ribbon 簡單使用

1、搭建環境:多個服務提供者、與之對應的多個資料庫、Eureka Server叢集。(之前的部落格有)

接下來是在客戶端,即服務消費方操作:

2、匯入pom依賴:

<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>

3、在application.yaml中進行相關配置:

eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com/eureka/,http://eureka7002.com/eureka/,http://eureka7003.com/eureka/
    register-with-eureka: false

4、在 RestTemplate 配置檔案中新增註解@LoadBalanced

package com.xingyu.springcloud.config;

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 {

    @Bean
    @LoadBalanced //Ribbon負載均衡
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

5、修改 Controller

之前的Controller如下:

package com.xingyu.springcloud.controller;

import com.xingyu.springcloud.pojo.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@RestController
public class DeptConsumerController {

    @Autowired
    private RestTemplate restTemplate; //提供多種便捷訪問遠端http服務的方法,簡單的restful服務模板

    private static final String REST_URL_PREFIX = "http://localhost:8001";

    @RequestMapping(value = "/consumer/dept/add", method = RequestMethod.POST)
    public Boolean add(Dept dept) {
        return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add",dept, Boolean.class);
    }

    @RequestMapping(value = "/consumer/dept/get/{id}", method = RequestMethod.GET)
    public Dept getOne(@PathVariable Long id) {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class);
    }

    @RequestMapping(value = "/consumer/dept/list", method = RequestMethod.GET)
    public List<Dept> getAll() {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
    }
}

其中:private static final String REST_URL_PREFIX = "http://localhost:8001";

這個語句設定了一個常量REST_URL_PREFIX用於指定服務的RESTurl地址,這樣會固定只能訪問8001,所以需要更改。將其中的localhost:8001修改為Eureka Server頁面(http://localhost:7001/)中服務例項的Application名:

所以將其修改成:private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";

修改後的Controller:

package com.xingyu.springcloud.controller;

import com.xingyu.springcloud.pojo.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@RestController
public class DeptConsumerController {

    @Autowired
    private RestTemplate restTemplate; //=提供多種便捷訪問遠端http服務的方法,簡單的restful服務模板

    private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";

    @RequestMapping(value = "/consumer/dept/add", method = RequestMethod.POST)
    public Boolean add(Dept dept) {
        return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add",dept, Boolean.class);
    }

    @RequestMapping(value = "/consumer/dept/get/{id}", method = RequestMethod.GET)
    public Dept getOne(@PathVariable Long id) {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class);
    }

    @RequestMapping(value = "/consumer/dept/list", method = RequestMethod.GET)
    public List<Dept> getAll() {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
    }
}

結論:Ribbon和Eureka整合後,客戶端可以直接呼叫服務,不需要關心IP地址和埠號。