Using the Ribbon

Simple to use

Write a production terminal and a consumer terminal. Start the two production terminals. Then the consumer terminal accesses the production terminal through the load balancing function of the Ribbon.

The production end

  1. Introduction of depend on
  2. Writing configuration files
  3. Start the class
  4. The controller class

The project structure

The overall project structure is shown below

Introduction of depend on

To introduce dependencies in the parent project, refer to the previous Nacos usage tips, and the subproject POM.xml file is

<? The 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" > < the parent > < artifactId > Learn < / artifactId > < groupId > zyz. SpringCloudAlibaba < / groupId > < version > 1.0 - the SNAPSHOT < / version > < / parent > The < modelVersion > 4.0.0 < / modelVersion > < artifactId > ribbon - produce < / artifactId > < dependencies > < the dependency > <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-nacos-discovery</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</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>Copy the code

Writing configuration files

Write the configuration file application.yml

spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
  application:
    name: ribbon-provider
server:
  port: 8081
Copy the code

Creating a Startup Class

Create the RibbonProvider startup class

package com.zyz; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class RibbonProvider { public static void main(String[] args) { SpringApplication.run(RibbonProvider.class, args); }}Copy the code

A new Controller class

package com.zyz.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @Slf4j @RestController public class ProviderController { @GetMapping(value = "/ribbon/provider/{string}") public String echo(@PathVariable String string){ log.info("Receive this request"); return "Hello Ribbon provider Discovery " + string; }}Copy the code

Introduce the logging annotation @slf4j

reference

The consumer end

  1. Introduction of depend on
  2. Writing configuration files
  3. Start the class
  4. The configuration class
  5. The controller class

Overall project structure

The overall project structure is shown below

Introduction of depend on

<? The 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" > < the parent > < artifactId > Learn < / artifactId > < groupId > zyz. SpringCloudAlibaba < / groupId > < version > 1.0 - the SNAPSHOT < / version > < / parent > The < modelVersion > 4.0.0 < / modelVersion > < artifactId > ribbon - consumer < / artifactId > < dependencies > < the dependency > <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId> </dependency> <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</artifactId> </dependency> </dependencies> </project>Copy the code

Writing configuration files

spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
  application:
    name: ribbon-consumer
server:
  port: 8083
Copy the code

Start the class

package com.zyz; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class RibbonConsumer { public static void main(String[] args) { SpringApplication.run(RibbonConsumer.class,args); }}Copy the code

The configuration class

package com.zyz.config; 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; @Configuration public class WebConfig { @LoadBalanced @Bean public RestTemplate restTemplate(){ return new RestTemplate(); }}Copy the code

The controller class

package com.zyz.contorller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController public class ConsumerController { @Autowired private RestTemplate restTemplate; @GetMapping(value = "/ribbon/consumer/{str}") public String rest(@PathVariable String str){ return restTemplate.getForObject("http://ribbon-provider/ribbon/provider/" + str, String.class); }}Copy the code

Start the project

Start the two production ends and use the consumer side for access to verify the results

Start the skills

The production port is 8081. After starting a service with 8081, we can change the port to 8082 and modify the following figure. Then we can start two instances of the same project

Mac: Select Allow Parallel Run

Authentication is successful

The Ribbon’s built-in load balancing algorithm

RandomRule

Select a Server at random

RetryRule

The retry mechanism is added to the load balancing policy. If the Server selection fails during the configuration period, the system tries to use subRule to select an available Server

RoundRobinRule

Poll Select, poll index, and select the Server corresponding to index

AvailabilityFilteringRule

Filter out back-end servers tagged with circuit tripped that repeatedly failed to connect and filter out those with high concurrency or use an AvailabilityPredicate that includes the logic to filter servers, Check the running status of each Server recorded in status

BestAvailableRule

Pick a Server with minimal concurrent requests, inspect servers one by one, and skip them if they tripped.

WeightedResponseTimeRule

Based on response time weighting, the longer the response time, the smaller the weight and the lower the probability of being selected

ZoneAvoidanceRule (default is this)

Compound judge the performance of the Zone where the Server resides and the availability of the Server select the Server. In the case of no Zone, the class is polling.

Ribbon custom load balancing policies

The Ribbon also supports custom configuration load balancing policies, such as random order centers and polling inventory centers.

Three services are set up, the first an order center, the second an inventory center, and the third a caller.

The order center

  1. Introduction of depend on
  2. Writing configuration files
  3. Start the class
  4. The controller class

The overall structure

Introduction of depend on

<? The 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" > < the parent > < artifactId > Learn < / artifactId > < groupId > zyz. SpringCloudAlibaba < / groupId > < version > 1.0 - the SNAPSHOT < / version > < / parent > The < modelVersion > 4.0.0 < / modelVersion > < artifactId > ribbon - product < / artifactId > < dependencies > < the dependency > <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-nacos-discovery</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</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>Copy the code

Writing configuration files

spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
  application:
    name: ribbon-product
server:
  port: 8081
Copy the code

Start the class

package com.zyz; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class RibbonProduct { public static void main(String[] args) { SpringApplication.run(RibbonProduct.class, args); }}Copy the code

Controlelr class

package com.zyz.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController @Slf4j public class ProductController { @GetMapping(value = "/ribbon/product/{string}") public String echo(@PathVariable String string){ log.info("Receive this request"); return "Hello Ribbon product Discovery " + string; }}Copy the code

Inventory center

  1. Introduction of depend on
  2. Writing configuration files
  3. Start the class
  4. The controller class

Introduction of depend on

<dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-discovery</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</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

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

Writing configuration files

spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
  application:
    name: ribbon-order
server:
  port: 8083
Copy the code

Start the class

package com.zyz; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class RibbonOrder { public static void main(String[] args) { SpringApplication.run(RibbonOrder.class, args); }}Copy the code

The controller class

package com.zyz.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController @Slf4j public class OrderController { @GetMapping(value = "/ribbon/order/{str}") public String order(@PathVariable String string){ log.info("Receive this request"); return "Hello Ribbon order Discovery " + string; }}Copy the code

The client

  1. Introduction of depend on
  2. Write configuration files (including load balancing configuration policies)
  3. Start the class
  4. The controller class
  5. The configuration class

The overall structure

Introduction of depend on

<? The 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" > < the parent > < artifactId > Learn < / artifactId > < groupId > zyz. SpringCloudAlibaba < / groupId > < version > 1.0 - the SNAPSHOT < / version > < / parent > The < modelVersion > 4.0.0 < / modelVersion > < artifactId > ribbon - app < / artifactId > < dependencies > < the dependency > <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-nacos-discovery</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</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>Copy the code

Writing configuration files

spring: cloud: nacos: discovery: server-addr: localhost:8848 application: name: ribbon-app server: port: 8088 ribbon-order: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule ribbon-product: ribbon: NFLoadBalancerRuleClassName: com.net flix. Loadbalancer. RoundRobinRule # open ribbon hunger load, solve the service call for the first time under the condition of slow ribbon: eager - load: Clients: ribbon-order,ribbon-productCopy the code

Start the class

package com.zyz; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class RibbonApp { public static void main(String[] args) { SpringApplication.run(RibbonApp.class, args); }}Copy the code

The controller class

package com.zyz.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @Slf4j @RestController public class RibbonController { @Autowired private RestTemplate restTemplate; @GetMapping(value = "/ribbon/app/product/{str}") public String product(@PathVariable String str){ return restTemplate.getForObject("http://ribbon-product/ribbon/product/" + str, String.class); } @GetMapping(value = "/ribbon/app/order/{str}") public String order(@PathVariable String str){ return restTemplate.getForObject("http://ribbon-order/ribbon/order/" + str, String.class); }}Copy the code

The configuration class

package com.zyz.config; 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; @Configuration public class WebConfig { @LoadBalanced @Bean public RestTemplate restTemplate(){ return new RestTemplate(); }}Copy the code

Ribbon common parameter description

Commonly used parameters

The Ribbon customizes load balancing policies

Nacos supports weight configuration, which is a useful feature, such as:

  1. Set low weights for poor machines and high weights for good machines, so that requests are sent to high machines first
  2. When an instance is abnormal, set the weight low, troubleshoot the problem, and then restore the weight after troubleshooting
  3. When you want to take an instance offline, set the weight of the instance to 0 so that traffic does not flow to it — then take it offline gracefully

Let’s extend the Ribbon to support Nacos weight configuration

Custom weight rule class

package com.zyz.rule; import com.alibaba.cloud.nacos.NacosDiscoveryProperties; import com.alibaba.cloud.nacos.ribbon.NacosServer; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.naming.NamingService; import com.alibaba.nacos.api.naming.pojo.Instance; import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.AbstractLoadBalancerRule; import com.netflix.loadbalancer.BaseLoadBalancer; import com.netflix.loadbalancer.Server; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @Slf4j public class WeightRule extends AbstractLoadBalancerRule { @Autowired private NacosDiscoveryProperties discoveryProperties; } @override public void initWithNiwsConfig(IClientConfig IClientConfig)  Server choose(Object key) { try { log.info("key:{}",key); BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer) this.getLoadBalancer(); log.info("baseLoadBalancer--->:{}",baseLoadBalancer); String serviceName = baseloadbalancer.getName (); / / for Nacos service discovery related component API NamingService NamingService = discoveryProperties. NamingServiceInstance (); / / get a nacos based client achieve weight load balancing algorithm Instance Instance. = namingService selectOneHealthyInstance (serviceName); Return new NacosServer(instance); }catch (NacosException e){log.error(" error "); } return null; }}Copy the code

Add the configuration

ribbon-product:
  ribbon:
    NFLoadBalancerRuleClassName: com.zyz.rule.WeightRule
Copy the code