Spring Cloud Getting Started Tutorial - Ribbon Implements Client Load Balancing

Introduction

structure

We continue to build on the code from the previous blog and add Ribbon components to provide client-side load balancing. Load balancing is an important part of realizing high-concurrency, high-performance, and scalable services. It can distribute requests to different servers in a cluster to reduce the burden on each server. Client load balancing runs in client programs, such as our web project, and then randomly selects a server to send requests by obtaining a list of cluster IP addresses. Compared with server-side load balancing, it does not need to consume server resources.

basic environment

  • JDK 1.8
  • Maven 3.3.9
  • IntelliJ 2018.1
  • Git

Project source code

Gitee Code Cloud

Update configuration

This time we need to start two production service programs locally to verify load balancing, so we need to provide a different port for the second program. The configuration of the Spring Cloud configuration service center will override the local system environment variables by default, and we need to set the port of the product service through the system environment variable, so we need to modify the configuration file of the product service in the configuration center git repositoryproduct-service.yml

server:
  port: 8081
spring:
  cloud:
    config:
      allow-override: true
      override-system-properties: false

allow-overrideThe default value of is true. It is written to illustrate that it means to allow the configuration items of the remote configuration center to override the local configuration, not to allow the local configuration to override the remote configuration. Of course we can set it to false, but in order to provide more precise override rules, the default value is left here. We added override-system-properties=falsethat although the configuration file of the remote configuration center can overwrite the local configuration, it should not overwrite the local system variables. After the modification is completed, submit it to the git repository.

In addition, add some logs to the productServiceproject ProductControllerto verify whether the load balancing is in effect:

package cn.zxuqian.controllers;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class ProductController {

    private static Logger log = LoggerFactory.getLogger(ProductController.class);

    @RequestMapping("/products")
    public String productList() {
        log.info("Access to /products endpoint");
        return "外套,夹克,毛衣,T恤";
    }
}

Configure Ribbon for the web

First pom.xmladd Ribbon's dependencies in:

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

Then modify the Applicationclass and add the following code:

@EnableCircuitBreaker
@EnableDiscoveryClient
@RibbonClient(name = "product-service")
@SpringBootApplication
public class Application {

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

    @Bean
    @LoadBalanced
    public RestTemplate rest(RestTemplateBuilder builder) {
        return builder.build();
    }
}

The annotations are used here @RibbonClient(name = "product-service")to mark this project as a Ribbon load balancing client. It needs to select one of the product service clusters to access the required services. The nameattributes here correspond to the attributes configured in the productService project spring.application.name. @LoadBalancedThe annotation indicates the uri that RestTemplatewill be configured to automatically use Ribbon LoadBalancerClientto select the service and send the request.

ProductServiceAdd the following code to our class:

@Service
public class ProductService {

    private final RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    public ProductService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @HystrixCommand(fallbackMethod = "backupProductList")
    public String productList() {
        List<ServiceInstance> instances = this.discoveryClient.getInstances("product-service");
        if(instances != null && instances.size() > 0) {
            return this.restTemplate.getForObject(instances.get(0).getUri() + "/products", String.class);
        }

        return "";
    }

    public String backupProductList() {
        return "夹克,毛衣";
    }


    public String productListLoadBalanced() {
        return this.restTemplate.getForObject("http://product-service/products", String.class);
    }
}

A new method is added here , which accesses the same service as the productListLoadBalancedprevious productListmethod, but uses Ribbon Client for load balancing. The host of the uri here becomes the product-servicename of the service to be accessed, and the properties @RibbonClientconfigured in namebe consistent. Finally ProductControlleradd the following code to our:

@RestController
public class ProductController {

    @Autowired
    private ProductService productService;

    @RequestMapping("/products")
    public String productList() {
        return productService.productList();
    }

    @RequestMapping("/productslb")
    public String productListLoadBalanced() {
        return productService.productListLoadBalanced();
    }
}

To create a method dedicated to handling /productslbrequests, call the method that productServieprovides load balancing.

At this point, our code is complete. The code seems simple, but in fact, all configurations use the default values. Ribbon provides two ways to configure Ribbon Client, programmatic and configuration. Now let's briefly introduce it, and then we will see how to modify its configuration when we go deeper into Ribbon. Ribbon provides the following configuration (interface on the left, default implementation on the right):

  • IClientConfigribbonClientConfig: DefaultClientConfigImpl
  • IRule ribbonRule: ZoneAvoidanceRule
  • IPing ribbonPing: DummyPing
  • ServerList<Server>ribbonServerList: ConfigurationBasedServerList
  • ServerListFilter<Server>ribbonServerListFilter: ZonePreferenceServerListFilter
  • ILoadBalancerribbonLoadBalancer: ZoneAwareLoadBalancer
  • ServerListUpdaterribbonServerListUpdater: PollingServerListUpdater

Because our project uses Eureka, some configuration items are different from the default implementation. For example, Eureka uses DiscoveryEnabledNIWSServerListsubstitution ribbonServerListto get a list of services registered on Eureka. Below is a simple Congiguration class from Spring's official website:

public class SayHelloConfiguration {

  @Autowired
  IClientConfig ribbonClientConfig;

  @Bean
  public IPing ribbonPing(IClientConfig config) {
    return new PingUrl();
  }

  @Bean
  public IRule ribbonRule(IClientConfig config) {
    return new AvailabilityFilteringRule();
  }

}

Ribbon will not send Ping to check the health status of the server by default, the default is normal, and then IRune is implemented by default as ZoneAvoidanceRulea zone to avoid AWS EC2 problems, which is not used in the local test environment, and then replaced with AvailabilityFilteringRule, This can open the circuit breaker function that comes with Ribbon to filter servers that are not working properly.

test

First start our configserverconfiguration center service, then start the registryEureka registration and discovery service, and then start two productService, the first one we can use the spring-boot:runplug-in to start normally, the second we need to provide it with a new port, which can be started with the following command :

$ SERVER_PORT=8082 mvn spring-boot:run

Finally, start our webclient project, access http://localhost:8080/productslbit, and refresh it a few times. You will see that productServiceour logs will appear randomly in the two running command line windows:

 Access to /products endpoint

Welcome to my blog, Zhang Xuqian's blog

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325377715&siteId=291194637