Ribbon of SpringCloud: Load Balancing

Spring Cloud integrates Ribbon, combined with Eureka, to achieve client load balancing.

An example is implemented below, and the structure is shown in the figure below.

One, server side

1. Create a project

Development tool:
Create a new SpringBoot project in IntelliJ IDEA 2019.2.3 IDEA with the name "cloud-server", select the SpringBoot version 2.1.10, and select Spring Cloud Discovery ->
Eureka Server in the Dependencies interface , The created pom.xml configuration file automatically adds the latest stable version of SpringCloud as a dependency, currently Greenwich.SR3.
The complete content of pom.xml is as follows:

<?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.10.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>cloud-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>cloud-server</name>
    <description>Demo project for Spring Boot</description>

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

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</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>

2. Modify the configuration application.yml

server:
  port: 8761
eureka:
  client:
    register-with-eureka: false
    fetch-registry: false

3. Modify the startup class code CloudServerApplication.java

Add annotation @EnableEurekaServer

package com.example.cloudserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class CloudServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(CloudServerApplication.class, args);
    }

}

2. Service provider

1. Create a project

Create a new SpringBoot project in IDEA, except that the name is "cloud-provider", the other steps are the same as the server-side creation above.

2. Modify the configuration application.yml

spring:
  application:
    name: cloud-provider
eureka:
  instance:
    hostname: localhost
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

3. Modify the startup class code CloudProviderApplication.java

Add the annotation @EnableEurekaClient;
let the class read the console input at startup and decide which port to use to start the server;
add a test controller method.package com.example.cloudprovider;

//import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.Scanner;

@SpringBootApplication
@EnableEurekaClient
@RestController
public class CloudProviderApplication {

public static void main(String[] args) {
//SpringApplication.run(CloudProviderApplication.class, args);
Scanner scan = new Scanner(System.in);
String port = scan.nextLine();
new SpringApplicationBuilder(CloudProviderApplication.class).properties("server.port=" + port).run(args);
}

@RequestMapping("/")
public String index(HttpServletRequest request) {
return request.getRequestURL().toString();
}
}

Three, the service caller

1.
Create a new SpringBoot project in IDEA, except that the name is "cloud-invoker", the other steps are the same as the server-side creation above.

2. Modify the configuration application.yml

server:
  port: 9000
spring:
  application:
    name: cloud-invoker
eureka:
  instance:
    hostname: localhost
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

3. Modify the startup class code CloudInvokerApplication.java

Add the annotation @EnableDiscoveryClient.

package com.example.cloudinvoker;

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

@SpringBootApplication
@EnableDiscoveryClient
public class CloudInvokerApplication {

    public static void main(String[] args) {
        SpringApplication.run(CloudInvokerApplication.class, args);
    }

}

4. There are two ways to configure Ribbon: use code and use configuration files

Method 1: Use code
(1) to create a new custom load rule class MyRule.java
Ribbon. The load balancer interface defines the operation of the server, which is mainly used for server selection.
Calling the getAllServers method of ILoadBalancer can return all servers, here only the first server is returned.

package com.example.cloudinvoker;

import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.Server;

import java.util.List;

public class MyRule implements IRule {

    private ILoadBalancer iLoadBalancer;

    @Override
    public Server choose(Object o) {
        List<Server> servers = iLoadBalancer.getAllServers();
        System.out.println("自定义服务器规则类,输出服务器信息:");
        for(Server s: servers){
            System.out.println(" " + s.getHostPort());
        }
        return servers.get(0);
    }

    @Override
    public void setLoadBalancer(ILoadBalancer iLoadBalancer) {
        this.iLoadBalancer = iLoadBalancer;
    }

    @Override
    public ILoadBalancer getLoadBalancer() {
        return this.iLoadBalancer;
    }
}

(2) Create a new Ping class MyPing.java

The Ping mechanism is provided in the load balancer to ping the server at regular intervals to determine whether the server is alive.
This work is in charge of the implementation class of the IPing interface.

package com.example.cloudinvoker;

import com.netflix.loadbalancer.IPing;
import com.netflix.loadbalancer.Server;

public class MyPing implements IPing {

    @Override
    public boolean isAlive(Server server) {
        System.out.println("自定义Ping类,服务器信息:" + server.getHostPort() + ",状态:" + server.isAlive());
        return true;
    }
}

(3) Create a new configuration class MyConfig.java

package com.example.cloudinvoker.config;

import com.example.cloudinvoker.MyPing;
import com.example.cloudinvoker.MyRule;
import com.netflix.loadbalancer.IPing;
import com.netflix.loadbalancer.IRule;
import org.springframework.context.annotation.Bean;

public class MyConfig {
    @Bean
    public IRule getRule(){
        return new MyRule();
    }
    @Bean
    public IPing getPing(){
        return new MyPing();
    }
}

(4) Create a new configuration class CloudProviderConfig.java

package com.example.cloudinvoker.config;

import org.springframework.cloud.netflix.ribbon.RibbonClient;

@RibbonClient(name = "cloud-provider", configuration = MyConfig.class)
public class CloudProviderConfig {
}

Method 2: Use the configuration file

Comment out the two configuration classes of Method 1, and add the following configuration at the end of application.yml

cloud-provider:
  ribbon:
    NFLoadBalancerRuleClassName: com.example.cloudinvoker.MyRule
    NFLoadBalancerPingClassName: com.example.cloudinvoker.MyPing
    listOfServers: http://localhost:8080/,http://localhost:8081/

5. Add the controller InvokerController.java

package com.example.cloudinvoker;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@Configuration
public class InvokerController {

    @LoadBalanced
    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }

    @RequestMapping(value="/router", method = RequestMethod.GET,produces = MediaType.APPLICATION_JSON_VALUE)
    public String router(){
        RestTemplate restTemplate = getRestTemplate();
        //根据名称调用服务
        String json = restTemplate.getForObject("http://cloud-provider/", String.class);
        return json;
    }
}

Four, test

1. Start the server.
2. Start the two service providers and enter 8080 and 8081 in the console to start.
3. Start the service caller.
4. The browser visits http://localhost:9000/router and refreshes the page many times. The results are all:

http://localhost:8081/

Timed output of the IDEA console of the service caller project:

自定义服务器规则类,输出服务器信息:
 localhost:8081
 localhost:8080
自定义Ping类,服务器信息:localhost:8081,状态:true
自定义Ping类,服务器信息:localhost:8080,状态:true

 

Guess you like

Origin blog.csdn.net/gdjlc/article/details/115007400