怎麼用Ribbon+Eureka實現負載均衡?

  一、Ribbon簡介

        Ribbon是Netflix發佈的負載均衡器,它有助於控制HTTP和TCP客戶端行爲。爲Ribbon配置服務提供者地址列表後,Ribbon就可以基於某種負載均衡算法,自動地幫助服務消費者去提供請求。

        在springcloud中,當Ribbon配合Eureka使用時,Ribbon可自動從Eureka Server獲取服務提供者的地址列表,並基於某種負載均衡算法,請求其中第一個服務提供者實例,常用的算法有隨機規則和輪詢,當沒有指定規則時,默認使用的算法爲輪詢。

     下面來演示實怎麼用Ribbon結合Eureka實現負載均衡:

       現準備一個eureka註冊中心,2個名爲expense的服務,均爲服務的提供者(provider),服務除了端口不一樣,其他都保持一致,1個payment服務,在案例中當消費者(consumer)。

       各服務使用的springcloud版本爲:

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR4</spring-cloud.version>
    </properties>

  springboot版本爲:

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.11.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
 </parent>

    客戶端的依賴和配置文件如下:
    payment服務:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.11.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example.hand</groupId>
    <artifactId>payment</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>payment</name>
    <description>project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR4</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <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-security</artifactId>
        </dependency>

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

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

   applicantion.properites配置文件:

server.port=9098
spring.application.name=payment
eureka.instance.prefer-ip-address=true
eureka.instance.instance-id=192.168.3.25:9098
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
eureka.instance.lease-renewal-interval-in-seconds =100
eureka.instance.lease-expiration-duration-in-seconds =50
spring.security.user.name=user
spring.security.user.password=user123
provider.name1=expense

 另外一個擁有2個實例的expense服務的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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.11.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example.hand</groupId>
    <artifactId>expense</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>expense</name>
    <description>project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR4</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <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-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.example.hand.Expense1Application</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

application.properties文件 :

端口爲9096的:

server.port=9096
spring.application.name=expense
eureka.instance.prefer-ip-address=true
eureka.instance.instance-id=192.168.2.13:9096
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
eureka.instance.lease-renewal-interval-in-seconds =30
eureka.instance.lease-expiration-duration-in-seconds =30

 

端口爲9097的:

server.port=9097
spring.application.name=expense
eureka.instance.prefer-ip-address=true
eureka.instance.instance-id=192.168.2.13:9097
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
eureka.instance.lease-renewal-interval-in-seconds =30
eureka.instance.lease-expiration-duration-in-seconds =30

       所需要的配置添加好以後,如果有遠程調用,需要在消費者端,啓動類添加如下代碼,將遠程調用RestTemplate類交給spring容器管理初始化,到後面我們要用的時候直接使用@Autowire註解就可以了,然後添加@LoadBanlanced註解,Ribbon客戶端請求服務端就有負載均衡的效果:

    @Bean
    @LoadBalanced
    RestTemplate restTemplate(){
        return new RestTemplate();
    }

  補充一點:介紹通過打jar包的形式,使用java命令來發布2個同名的實例。在expense服務下啓動兩個終端,分別使用不同端口號來啓動:

    第一步,在pom文件中添加<packaging>jar</packaging>標籤,使用maven插件打jar包:

<groupId>com.example.hand</groupId>
 <artifactId>expense</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>jar</packaging>
<name>expense</name>

    

然後使用命令: mvn install 

   

執行完成後,會在target目錄下生成一個後綴爲.jar的文件,和.jar.original文件:

 然後分別使用9096端口和9097端口執行命令,如下默認使用的配置文件中的默認端口啓動:

java -jar expense-0.0.1-SNAPSHOT.jar

 修改expense的實例id,在修改配置文件後,重新打jar包,修改實例的id和端口號後再啓動:

java -jar expense-0.0.1-SNAPSHOT.jar --server.port=9097

 切換到指定的目錄下:

 啓動後:

 

啓動各服務,效果如下:

然後在客戶端定義一個接口使用loadBalancerClient去調用主機名爲expense的服務,Ribbon客戶端會根據eureka裏面的服務器的地址列表來輪詢選擇一個實例進行請求!

 

Payment的java代碼如下:

 

  @GetMapping("/get/instance")
    public String getInstance(){
        ServiceInstance instance=this.loadBalancerClient.choose("expense");
        String str="實例的id爲:"+instance.getServiceId()+",實例的域名爲:"+instance.getHost()+",端口爲:"+instance.getPort();
        LOGGER.info(str);
        return str;
    }

然後訪問如下Url:http://localhost:9098/api/wallet/get/instance

刷新頁面後,會發現返回的結果爲在9097和9096之間來回切換:

控制檯打印結果如下:

 

 

由上述結果發現,這樣就實現負載均衡了,默認的負載均衡規則爲輪詢,在2各節點之間來回切換!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章