preface

Spring Cloud Ribbon is an HTTP and TCP client load balancing tool based on the Netflix Ribbon.

First, the core concept of Ribbon

Raibbon is a set of client-side load balancing tools based on the Netflix Ribbon. The Raibbon client provides a series of configurations, such as timeout, retry, load balancing, etc. Understanding and using the Spring Cloud Ribbon is very important for us to use Spring Cloud to build microservices, such as calls between microservices, API gateway forwarding requests, etc. It’s actually done through the Ribbon.

Colloquially: Ribbon = Load Balancing + RestTemplate

The term “client side load balancing” is mentioned here, so you might think of our Nginx, so is Nginx client side load balancing? No, Nginx is actually a centralized load balancer (server side load balancer), not a client side load balancer. So what’s the difference between the two?

Server load balancing and Riboon client load balancing

1. Server-side load balancing:

Server load balancing is divided into two types, one is hardware load balancing, and the other is software load balancing.

For example, Nginx is a software load balancer. Nginx is used to perform load balancing. Requests are sent first, and then a load balancing algorithm is used to select one server among multiple servers for access. In other words, the load balancing algorithm is allocated on the server side. Let’s look at a picture of the load balancing strategy done by Nginx.

2, Riboon client load balancing:

For example, the ribbon in Spring Cloud provides a client with a list of server addresses. Before sending a request, the client selects a server using the load balancing algorithm and then accesses it. This is the client load balancing. That is, the load balancing algorithm is allocated on the client. Go straight to the figure above. The following figure shows the Ribbon load balancing strategy that we will implement in this article.

3. Ribbon strategy

When we add the @LoadBalanced annotation to the RestTemplate, we can use the service name to call interfaces, and load balancing when there are multiple services. The Ribbon provides a wide range of configuration options, such as connection timeouts, retries, and the ability to customize load balancing policies using the Ribbon.

Common load balancing policies are as follows:

  • The default policy is rotation
  • random
  • Retry (if the service fails, retry within the specified time to obtain the available service)
  • Filter out the failed services and select a service with the minimum amount of concurrency

The realization of load balancing rotation training algorithm is shown as follows:

4. Use the Ribbon configuration

Here we use Nacos as the registry to simulate the call between the order service and the inventory service. The Ribbon is used as the client load balancing implementation. The configuration method is very simple.

The service name The port number
dt-stock-service 8083
dt-stock-service 8082
dt-order-service 8081

Here we have two inventory services and one order service. The inventory service is invoked by the order service to realize the load balancing of the Ribbon. The first is the order service startup class, and we register the RestTemplate. With the RestTemplate annotation @loadBalanced, the RestTemplate interface can be called using the service name. This function implements the load balancing policy in the Ribbon.

@SpringBootApplication
@EnableDiscoveryClient
public class OrderApplication {

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

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        returnbuilder.build(); }}Copy the code

The order service controller invocation interface is as follows:

@RestController
@RequestMapping(value = "order")
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("test")
    public String getOrder(a) {
        String msg = restTemplate.getForObject("http://dt-stock-service/stock/test", String.class);
        return "Invoke order Service ->>>"+msg; }}Copy the code

We call the inventory service interface method with the service name (dT-stock-service), and then we write the inventory service controller interface method:

@RestController
@RequestMapping(value = "/stock")
public class StockController {

    @Value("${server.port}")
    private String port;

    @GetMapping("/test")
    public String getStock(a) {
        return "Call inventory service:"+port; }}Copy the code

Here we print the ports that the current inventory service is invoked to see the load balancing policy pattern in the Ribbon. The service architecture is as follows.

We start the order service 8081, then start the inventory service 8082 and 8083 successively. After the service is started, observe the change of our registry service instance. At this time, the order service has one instance, and the inventory service has two instances.

Send a request:http://localhost:8081/order/test

First port 8083:

Second port 8082:

The default policy mode the Ribbon uses is polling. As we said at the beginning of this article, the Riboon policy is not just polling. Polling is an internal default implementation. Let’s look at some other common ways to play.

Configure a user-defined load balancing algorithm

1. Implement load balancing based on weight

The Ribbon itself has no concept of weights. How can you achieve load balancing using weights instead? In NACOS, the server cluster has a concept of weight. When the weight is set for the server, the traffic can be allocated to the server according to the proportion of weight.

1.1 configuration Ribbon

spring:
  application:
    name: dt-order-service
  cloud:
    nacos:
      server-addr: 47.108191.196.: 9091
      discovery:
        username: nacos
        password: nacos
        namespace: public
ribbon:
  NFLoadBalancerRuleClassName: com.dt.springcloud.ribbon.config.GlobalRibbonConfig # Specify a global load balancing algorithm
  eager-load:
    enabled: true             # Enable hunger mode
    clients: dt-stock-service Use commas to separate multiple service names
Copy the code

Com. Dt. Springcloud. Ribbon. Config. GlobalRibbonConfig # specify global load balancing algorithm of the name of the class

The Ribbon clients do not load when a service is started, so the first call may be slow, or even time out.

1.2 Global load balancing algorithm class

/** * Global set a custom weight load balancing policy *@author DT
 * @date2021/8/7 men * /
@Configuration
public class GlobalRibbonConfig {

    @Bean
    public IRule getRule(a) {
        // Implement a load balancing policy with weights
        return newMyWeightRule(); }}Copy the code

1.3 Customizing weights To achieve load balancing

/** * Customize a load balancing policy@author DT
 * @date2021/8/7 and * /
public class MyWeightRule extends AbstractLoadBalancerRule {

    @Autowired
    private NacosDiscoveryProperties discoveryProperties;

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {}/** * Customize the method of implementing the load balancing policy */
    @Override
    public Server choose(Object key) {
        try {
            // Call the superclass method to get the current load balancer in use
            BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer) this.getLoadBalancer();
            // Get the name of the current service
            String serviceName = baseLoadBalancer.getName();
            // Get the nacOS service discovery API
            NamingService namingService = discoveryProperties.namingServiceInstance();
            // NacOS implements the weight load balancing algorithm
            Instance instance = namingService.selectOneHealthyInstance(serviceName);
            // Print the output
            String threadName = Thread.currentThread().getName();
            System.out.println("Thread - > > >" + threadName + "->>> Send request");
            System.out.println("IP port - > > >"+instance.getIp()+":"+instance.getPort());
            return new NacosServer(instance);
        } catch (NacosException e) {
            e.printStackTrace();
        }
        return null; }}Copy the code

1.4 Setting the weight ratio of Nacos service instances

We set one to 0.3 and the other to 0.7, which means that if there are 10 requests, they will almost always go to port 8082, because 8082 has the highest weight and should have the highest number of calls.

1.4 Testing load Balancing

http://localhost:8081/order/test

Ten requests are triggered, seven or so of which will reach the 8082 service.

6. Common Ribbon configurations

ribbon:
  ConnectTimeout: 1000Service request connection timeout (ms) ReadTimeout:3000# service request timeout (ms) OkToRetryOnAllOperations:true# to timeout request enable MaxAutoRetriesNextServer retry mechanism:1MaxAutoRetries:1Retry after # switch case maximum times NFLoadBalancerRuleClassName: com. Dt. Springcloud. Ribbon. The config. GlobalRibbonConfig # modified load balancing algorithmCopy the code

For the purposes of this article, the global configuration is used, although you can also specify the configuration for individual services:

Dt-order-service: ribbon: ConnectTimeout:1000Service request connection timeout (ms) ReadTimeout:3000# service request timeout (ms) OkToRetryOnAllOperations:true# to timeout request enable MaxAutoRetriesNextServer retry mechanism:1MaxAutoRetries:1Retry after # switch case maximum times NFLoadBalancerRuleClassName: com. Dt. Springcloud. Ribbon. The config. GlobalRibbonConfig # modified load balancing algorithmCopy the code

conclusion

Well, the above content is today’s output, after we continue to in-depth study the use of other components of micro-services and principle analysis, creation is not easy, like please pay attention to small series CSDN: blog.csdn.net/qq_41107231 and nuggets: juejin.cn/user/394024…