SpringCloud微服務之Ribbon負載均衡(一)

来源:https://www.cnblogs.com/lzhdonald/archive/2020/03/17/11798912.html
-Advertisement-
Play Games

什麼是微服務?什麼是SpringCloud? 微服務是一種架構的模式,它提倡將一個應用程式劃分成很多個微小的服務,服務與服務之間相互協調、相互配合。每個服務運行都是一個獨立的進程,服務與服務之間採用輕量級的通訊機制相互溝通。簡單的來說就是將一個龐大的複雜的單體應用進行劃分成n多個微小的服務(一個服務 ...


什麼是微服務?什麼是SpringCloud?

 微服務是一種架構的模式,它提倡將一個應用程式劃分成很多個微小的服務,服務與服務之間相互協調、相互配合。每個服務運行都是一個獨立的進程,服務與服務之間採用輕量級的通訊機制相互溝通。簡單的來說就是將一個龐大的複雜的單體應用進行劃分成n多個微小的服務(一個服務負責一個業務),各個微服務都被獨立的部署。

 微服務與集群的區別是,微服務的每一個部署的服務都是不相同的,而集群部署的每一個服務都是相同的。

 Spring Cloud是一個微服務框架,相比Dubbo等RPC框架,Spring Cloud提供的全套的分散式系統解決方案。它是在SpringBoot的基礎上構建的。SpringCloud的五大神獸分別是Eureka、Ribbon、Feign、Hystrix、Zuul。

環境搭建

版本說明

springboot:2.0.3

springcloud:Finchley

創建一個父工程(maven項目)

 

 選擇maven,點擊next

 

 然後點擊完成

 修改父工程pom.xml

<?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>

    <groupId>com.lzh</groupId>
    <artifactId>my-springcloud-01</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>


    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <junit.version>4.12</junit.version>
        <log4j.version>1.2.17</log4j.version>
        <lombok.version>1.16.18</lombok.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.RELEASE</version>
                <!--<version>Dalston.SR1</version>-->
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.0.3.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.0.4</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.0.31</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.0</version>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
                <version>1.2.3</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <finalName>microservicecloud</finalName>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <delimiters>
                        <delimit>$</delimit>
                    </delimiters>
                </configuration>
            </plugin>
        </plugins>
    </build>


</project>

 創建子工程(maven項目)

工程名稱:microservice-consumer-80

pom.xml文件

<?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">
    <parent>
        <artifactId>my-springcloud-01</artifactId>
        <groupId>com.lzh</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>microservice-consumer-80</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.lzh</groupId>
            <artifactId>microservice-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <!-- 整合ribbon -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>

</project>

 

編碼實現

在主啟動類上加上@EnableDiscoveryClient註解

創建一個配置文件ConfigBean.java,new一個RestTemplate遠程調用模板,加入@LoadBalanced註解,開啟負載均衡

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;

/**
 * @author lzh
 * create 2019-11-05-9:58
 */
@Configuration
public class ConfigBean {

    @Bean
    //加入負載均衡
    //Spring Cloud Ribbon是基於Netflix Ribbon實現的一套客戶端    負載均衡的工具
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }

}

在服務層DeptServiceImpl.java類中用RestTemplate模板工具調用,這裡使用服務名稱調用,如果服務名稱相同,則會進行順序輪詢調用 

import com.lzh.cloud.model.Dept;
import com.lzh.cloud.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
 * @author lzh
 * create 2019-11-05-10:27
 */
@Service
public class DeptServiceImpl implements DeptService {


    /**
     * 使用restTemplate訪問restful介面非常的簡單粗暴無腦。
     * (url, requestMap, ResponseBean.class)這三個參數分別代表
     * REST請求地址、請求參數、HTTP響應轉換被轉換成的對象類型。
     */
    @Autowired
    private RestTemplate restTemplate;

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

    @Override
    public boolean add(Dept dept) {
        return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
    }

    @Override
    public Dept get(Long id) {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class);
    }

    @Override
    public List<Dept> list() {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list/", List.class);
    }

    @Override
    public Object discovery() {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/discovery", Object.class);
    }
}

自定義輪詢規則

在主啟動類的前一個包創建一個配置MySelRule類,註意不要跟主啟動類同包或者在主啟動類的子包中創建

import com.netflix.loadbalancer.IRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author lzh
 * create 2019-05-19-17:10
 */

@Configuration
public class MySelfRule {

    @Bean
    public IRule myRule(){
        //return new RandomRule(); //Ribbon預設是輪詢,我自定義為隨機
        //return new RoundRobinRule(); //Ribbon預設是輪詢,我自定義為隨機

        return new RandomRule_LZH(); // 我自定義為每台機器5次
    }

}

 參照源碼,自定義輪詢演算法RandomRule_LZH.java 

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;

import java.util.List;

public class RandomRule_LZH extends AbstractLoadBalancerRule {

    // total = 0 // 當total==5以後,我們指針才能往下走,
    // index = 0 // 當前對外提供服務的伺服器地址,
    // total需要重新置為零,但是已經達到過一個5次,我們的index = 1
    // 分析:我們5次,但是微服務只有8001 8002 8003 三台,OK?
    //


    private int total = 0;            // 總共被調用的次數,目前要求每台被調用5次
    private int currentIndex = 0;    // 當前提供服務的機器號

    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        }
        Server server = null;

        while (server == null) {
            if (Thread.interrupted()) {
                return null;
            }
            List<Server> upList = lb.getReachableServers();
            List<Server> allList = lb.getAllServers();

            int serverCount = allList.size();
            if (serverCount == 0) {
                /*
                 * No servers. End regardless of pass, because subsequent passes only get more
                 * restrictive.
                 */
                return null;
            }

//            int index = rand.nextInt(serverCount);// java.util.Random().nextInt(3);
//            server = upList.get(index);


//            private int total = 0;             // 總共被調用的次數,目前要求每台被調用5次
//            private int currentIndex = 0;    // 當前提供服務的機器號
            if (total < 5) {
                server = upList.get(currentIndex);
                total++;
            } else {
                total = 0;
                currentIndex++;
                if (currentIndex >= upList.size()) {
                    currentIndex = 0;
                }
            }


            if (server == null) {
                /*
                 * The only time this should happen is if the server list were somehow trimmed.
                 * This is a transient condition. Retry after yielding.
                 */
                Thread.yield();
                continue;
            }

            if (server.isAlive()) {
                return (server);
            }

            // Shouldn't actually happen.. but must be transient or a bug.
            server = null;
            Thread.yield();
        }

        return server;

    }

    @Override
    public Server choose(Object key) {
        return choose(getLoadBalancer(), key);
    }

    @Override
    public void initWithNiwsConfig(IClientConfig clientConfig) {
        // TODO Auto-generated method stub

    }

}

最後不要忘了在主啟動類加上註解,使用自定義輪詢演算法configuration = MySelfRule.class

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;


/**
 * @author lzh
 * create 2019-11-04-22:26
 */
@SpringBootApplication
@EnableEurekaClient
//自定義負載均衡規則
//在啟動該為服務的時候就能去載入我們的自定義Ribbon配置類,從而使配置生效
//configuration = MySelfRule.class  把MySelfRule配置類載入進容器
@RibbonClient(name = "MICROSERVICECLOUD-DEPT",configuration = MySelfRule.class)
@EnableDiscoveryClient
public class MyConsumerApplication_80 {
    public static void main(String[] args) {
        SpringApplication.run(MyConsumerApplication_80.class);
    }
}

代碼

 github:https://github.com/LZHDonald/my-springcloud-01/tree/master/microservice-consumer-80


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 定義三個方法 1.定義一個獲取數據的getData()方法2.定義一個導出excel表的方法exportSqlServer()3.定義一個獲取類型typeof()的方法,用作查詢出來的數據被識別 下麵直接展示代碼 from datetime import datetime import os imp ...
  • 關於模型: 1:一個模型類對應一個表,模型類中的屬性對應表中的一個欄位 2:欄位類型(資料庫支持的類型) 字元串 1:CharField(Maxlength=長度) models.CharField 2:TextFiled 大文本 3:IntegerField 整數 4:DecimalField(m ...
  • 本文存在[視頻版本][1],請知悉 項目簡介 項目來源於: "https://gitee.com/thuihuang/shine_bookshop" 一個基於 JSP+Servlet+Jdbc 的shine網上書城。涉及技術少,易於理解,適合 JavaWeb初學者 學習使用。 技術棧 編輯器 Ecl ...
  • 有一個這樣的問題:現要用 setuptools 把一個項目打包成 whl 文件,然後 pip install 在 Windows/Linux 兩種操作系統上,但是該項目中有一些依賴庫只有 Windows 上才有(例如 pywinauto、pywingui、pywinrm),那麼問題是,如何實現打包文 ...
  • 基於S2SH開發線上學堂系統(課程學習網站 前臺+後臺) 開發環境: Windows操作系統開發工具:Eclipse+Jdk+Tomcat+MYSQL資料庫運行效果圖 源碼及原文鏈接:https://javadao.xyz/forum.php?mod=viewthread&tid=97 ...
  • Maven項目打包時,如果遇到需要添加本地jar包依賴的時候,可以選擇兩種方法: 1. 安裝到本地倉庫 第一種方法比較常規,適用於需要添加的jar包也是由maven項目導出,含有pom文件的時候。只需要將jar包安裝到本地maven倉庫下,然後添加依賴即可。 (1)安裝到本地倉庫,執行以下命令(其中 ...
  • Spring Boot為廣大開發人員提供了便利。 本文將介紹如何編寫Starter,以便開發人員復用自己或項目組的代碼。 代碼下載地址:https://gitee.com/jxd134/Spring Boot Greeter Starter.git 1 新建項目 項目基於Maven構建,包含以下三個 ...
  • 題目: 代碼及思路: #include <stdio.h> #include <string.h> int main() { //以字元串的形式接受用戶輸入的數字 char str[1000]; //定義一個統計數組 int nums1[10] = {0}; scanf("%s", str); // ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...