codestory

Load Balancing in Spring Cloud mit Ribbon und Beispiel verstehen

  1. Was ist Load Balancer ?
  2. Netflix Ribbon
  3. Das Ziel von der Unterricht
  4. Das Projekt Spring Boot erstellen
  5. Ribbon konfigurieren
  6. Controller
  7. Die Applikation laufen

1. Was ist Load Balancer ?

Stellen Sie sich vor, Sie ein verteiltes System haben, einschließlich die Dienstleistungen (die Applikation) laufen auf die unterschiedlichen Computer. Aber wenn der Anzahl von Benutzer groß ist, wird eine Dienstleistung in vielen Kopien (replica) oft erstellt. Jede Kopie läuft auf einen verschiedenen Computer. Jetzt entsteht "Load Balancer" . Er hilft bei der gleichermaßenen Verteilung des ankommenden Verkehr (incoming traffic) zwischen die Servers
Server side Load Balancer
Nach der Tradition sind die Load Balancer die Komponenten, die in Server Seite (Server Side) liegt. Wenn die Anforderungen aus Clientkommen, werden sie zum Load Balancer gehen und der Load Balancer wird einen Server für diese Anforderung bestimmen. Das meist einface Algorithmus, das der Load Balancer benutzt, ist die Random-Bezeichnung. Die meisten Load Balancers in diesen Fall sind Hardware mit der integrierte Software um das Load Balancing zu kontrollieren
Client-Side Load Balancer
Wenn der Load Balancer bei der Seite Client (Client side) liegt, wird er sich activ entscheiden dafür, nach welchenmServer er die Anforderungen nach der Kriterien schicken wird
Tatsächlich haben die Server den Unterschied. Sie unterscheiden sich von einander in die folgenden Kriterien:
  1. Die Verfügbarkeit (Availability): Keine Server funktioniert immer.
  2. Die Leistung (Performance): Die Geschwindigkeit vom Server ist unterschiedlich.
  3. Die Geographie: Die Servers werden in die unterschiedlichen Stelle gestellt. Zum Beispiel: Sie liegen in die verschiedenen Länder. Er kann in der Nahe von einem Client aber entfern von anderem Client sein
Die Client-Side Load Balancer schicken normalerweiser die Anforderungen nach den Servers in der gleichen Zone oder mit der schnellen Response

2. Netflix Ribbon

Ribbon ist eine Teil von der Familie Netflix Open Source Software (Netflix OSS). Es ist eine Bibliothek, die den Client-Side Load Balancer bietet. Denn es ist ein Mitglieder von der Familie Netflix , so kann es mit Netflix Service Discovery (Eureka) interaktivieren.
Spring Cloud hat API erstellt um Ihnen bei der leichten Verwendung der Bibliothek Ribbon zu helfen.
OK, Wir werden die Begriffe über Ribbon diskussieren:
  1. Die Liste der Server.
  2. Die gefilterte Liste der Server.
  3. Load Balancer
  4. Ping
-
  • Die Liste von Server (List Of Servers):
Eine Liste der Server, die eine bestimmte Dienstleistung für 1 Client reagiert. Zum Beispiel 1 Client braucht die Information über das Wetter. Es gibt eine Liste der Server zur Informationsversorgung. Die Liste fasst die Servers, die in der Applikation Client direkt konfiguriert werden, und die Server, die Client entdeckt, um
  • Die gefilterte Liste von Server (Filtered List of Servers):
Wir machen das oben Beispiel weiter. 1 Client braucht die Information von Wetter und eine Liste der Server kann diese Information bieten. Allerding funktionieren alle Server nicht, oder der Server ist zu weit von Client . So reagiert er sehr langsam. Client wird diese Servers aus der Liste beseitigen und zum letzten hat es eine Liste der mehr entsprechenden Server ( eine gefilterte Liste).
  • Load Balancer (Ribbon):
Ribbon ist ein Load Balancer. Er ist ein Client-Side Komponent. Er entscheidet sich dafür, welcher Server geruft werden wird (in die gefilterte Liste der Server).
Es gibt einige Strategien (Strategy) um die Entscheidung zu treffen. Aber sie basieren oft auf "Rule Component" (Regel Komponent) um eine Unterscheiden zu treffen. Nach dem Default benutzt Spring Cloud Ribbon die Strategie ZoneAwareLoadBalancer (die Server in den gleichen Zone mit Client).
Rule Component ist eine kluge Module. Es macht eine Entscheidung "Rufen oder nicht rufen". Nach dem Default benutzt Spring Cloud das Regel ZoneAvoidanceRule.
  • Ping:
Ping ist die Methode, die Client benutzt um zu prüfen, ob der Server in dieser Zeit funktioniert oder nicht? Das Default-Verhalten vom Spring Cloud ist darin, Eureka die automatische Prüfung der Information zu übertragen. Aber Spring Cloud erlaubt Sie, die Prüfung nach Ihrem Weg anzupassen

3. Das Ziel von der Unterricht

Achtung: diese Unterricht bezieht sich direkt auf die 2 letzten Unterrichten
  • Bài học (1): Wir haben eine "Service Registration" (Eureka Server) erstellt.
  • Bài học (2): Wir haben eine Applikation "ABC Service" erstellt. Das ist ein Discovery Client (Eureka Client).
In dieser Unterricht werde ich eine Applikation "XYZ Service" erstellen. Sie ist eine Discovery Client (Eureka Client) und sie wird nach "ABC Service" aufrufen. Auf die Applikation "XYZ Service" werden wir einen Load Balancer benutzen
Um diese Applikation zu prüfen, sollen wir alle 3 Applikation laufen. Davon wird die Applikation "ABC Service" in die 5 Kopien (replica) erstellt (simulieren, dass sie in 5 unterschiedlichen Computer läuft). Wenn Client (XYZ Service) nach "ABC Service" ruft, wird der Load Balancer sich entscheiden, auf welcher Kopie vom "ABC Service" aufgeruft wird
OK!, Das ist eine interessante und auch leichte Aufgabe

4. Das Projekt Spring Boot erstellen

Auf Eclipse erstellen Sie ein Projekt Spring Boot.
Geben Sie ein
  • Name: SpringCloudLoadBalancerRibbon
  • Group: org.o7planning
  • Artifact: SpringCloudLoadBalancerRibbon
  • Description: Spring Cloud Load Balancer (Ribbon)
  • Package: org.o7planning.ribbon
  • Die Applikation, die durch uns erstellt wird, wird auf "ABC Service" aufgeruft. Es braucht ein Load Balancer , so werden wir die Bibliothek Ribbon zu verwenden deklarieren.
  • Die Applikation soll die anderen in dem verteilten System laufenden Dienstleistungen (die Applikation) entdecken. Deshalb soll sie die Bibliothek Discovery benutzen. Wir werden Eureka Discovery (Eureka Client) benutzen.
OK, Das Projekt wurde erstellt
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>org.o7planning</groupId>
    <artifactId>SpringCloudLoadBalancerRibbon</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>SpringCloudLoadBalancerRibbon</name>
    <description>Spring Cloud Load Balancer (Ribbon)</description>

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

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Edgware.RELEASE</spring-cloud.version>
    </properties>

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

5. Ribbon konfigurieren

application.yml
spring:
  application:
    name: XYZ-SERVICE
 
server:
  port: 5555

# -- Configure for Ribbon:
 
ping-server:
  ribbon:
    eureka:
      enabled: false # Disable Default Ping
    listOfServers: localhost:8000,localhost:8001,localhost:8002,,localhost:8003
    ServerListRefreshInterval: 15000
    
# -- Configure Discovery Client (Eureka Client).    
# Configure this application to known "Service Registration".

eureka:
  instance:
    appname: XYZ-SERVICE  # ==> This is an instance of XYZ-SERVICE
  client:    
    fetchRegistry: true
    serviceUrl:
#      defaultZone: http://my-eureka-server.com:9000/eureka
      defaultZone: http://my-eureka-server-us.com:9001/eureka
#      defaultZone: http://my-eureka-server-fr.com:9002/eureka
#      defaultZone: http://my-eureka-server-vn.com:9003/eureka
SpringCloudLoadBalancerRibbonApplication.java
package org.o7planning.ribbon;

import org.o7planning.ribbon.config.RibbonConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;

@RibbonClient(name = "ping-a-server", configuration = RibbonConfiguration.class)
@EnableEurekaClient
@SpringBootApplication
public class SpringCloudLoadBalancerRibbonApplication {

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

}
RibbonConfiguration.java
package org.o7planning.ribbon.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.IPing;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.PingUrl;
import com.netflix.loadbalancer.WeightedResponseTimeRule;

 
public class RibbonConfiguration {
    
    @Autowired
    private IClientConfig ribbonClientConfig;
 
    @Bean
    public IPing ribbonPing(IClientConfig config) {
        return new PingUrl();
    }
 
    @Bean
    public IRule ribbonRule(IClientConfig config) {
        return new WeightedResponseTimeRule();
    }
    
}

6. Controller

Example1Controller.java
package org.o7planning.ribbon.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class Example1Controller {

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private LoadBalancerClient loadBalancer;

    @ResponseBody
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home() {

        return "<a href='testCallAbcService'>/testCallAbcService</a>";
    }

    @ResponseBody
    @RequestMapping(value = "/testCallAbcService", method = RequestMethod.GET)
    public String showFirstService() {

        String serviceId = "ABC-SERVICE".toLowerCase();

        // (Need!!) eureka.client.fetchRegistry=true
        List<ServiceInstance> instances = this.discoveryClient.getInstances(serviceId);

        if (instances == null || instances.isEmpty()) {
            return "No instances for service: " + serviceId;
        }
        String html = "<h2>Instances for Service Id: " + serviceId + "</h2>";

        for (ServiceInstance serviceInstance : instances) {
            html += "<h3>Instance :" + serviceInstance.getUri() + "</h3>";
        }

        // Create a RestTemplate.
        RestTemplate restTemplate = new RestTemplate();

        html += "<br><h4>Call /hello of service: " + serviceId + "</h4>";

        try {
            // May be throw IllegalStateException (No instances available)
            ServiceInstance serviceInstance = this.loadBalancer.choose(serviceId);

            html += "<br>===> Load Balancer choose: " + serviceInstance.getUri();

            String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/hello";

            html += "<br>Make a Call: " + url;
            html += "<br>";

            String result = restTemplate.getForObject(url, String.class);

            html += "<br>Result: " + result;
        } catch (IllegalStateException e) {
            html += "<br>loadBalancer.choose ERROR: " + e.getMessage();
            e.printStackTrace();
        } catch (Exception e) {
            html += "<br>Other ERROR: " + e.getMessage();
            e.printStackTrace();
        }
        return html;
    }

}

7. Die Applikation laufen

Um diese Applikation voll zu prüfen, sollen Sie 2 Applikation von der 2 letzten Unterrichten laufen ("Service Registration" und "ABC Service")
Danach können Sie auf Eclipse diese Applikation direkt laufen und in den folgenden Pfaf zugreifen um Eureka Monitor zu sehen
Test Load Balancer: