Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to analyze the problem of service invocation by Ribbon in SpringCloud

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article will explain in detail how to analyze the Ribbon in SpringCloud for service invocation. The content of the article is of high quality, so the editor shares it for you as a reference. I hope you will have some understanding of the relevant knowledge after reading this article.

1. Overview of Robbon1.1 and Ribbon

1. What is Ribbon?

SpringCloud-Ribbon is a set of client load balancing tools based on Netflix Ribbon.

To put it simply, Ribbon is an open source project released by Netflix, and its main function is to provide software load balancing algorithms and service calls on the client side. The Ribbon client component provides a series of complete configurations such as connection timeout, pickup, and so on. To put it simply, all the machines behind Load Balancer (LB) are listed in the configuration file, and Ribbon will automatically help you connect these machines based on certain rules (such as simple polling, immediate connection, etc.). We can easily use Ribbon to implement custom load balancing algorithms.

In a word, load balancer + RestTemplate calls.

(2) the official website of Ribbon

Official website address

And now it has entered the maintenance mode.

(3), load balancing (LB)

Load balancing is to distribute users' requests evenly to multiple services, so as to achieve the HA (high availability) of the system. The common load balancing is made up of software nginx, LVS and F5.

1. Centralized LB: a separate LB facility (such as hardware, such as F5, or software, such as nginx) is used between the consumer and provider of the service, which is responsible for forwarding access requests to the service provider through a certain policy.

two。 In-process LB: integrate the LB logic into the consumer, which learns which addresses are available from the service registry, and then selects a suitable server from these addresses. Ribbon belongs to in-process LB, it is just a class library, integrated with the consumer process, the consumer uses it to obtain the address of the service provider.

(4) the difference between Ribbon local load balancing client and Nginx server load balancing

Nginx is a server load balancer, and all requests from the client are forwarded to nginx for forwarding. That is, load balancing is implemented by the server.

Ribbon local load balancer, when calling the micro-service interface, will cache it locally to JVM after the registration information list is obtained by the registry, thus implementing the RPC remote service invocation technology locally.

1.2.Demo of Ribbon load balancing

(1), architecture description

Ribbon is actually a client component of soft load balancing, which can be used in conjunction with other required clients, and eureka is just one of them.

Ribbon is divided into two steps at work

The first step is to choose EurekaServer, which gives priority to server with less load in the same area.

In the second step, according to the policy specified by the user, select an address from the service registration list obtained from server. Ribbon provides a variety of strategies, such as polling, random, and weighted based on response time.

(2), POM file

So the integration package that introduces Eureka includes the jar package that integrates Ribbon.

So the alternate access between 8001 and 8002 we implemented earlier is the so-called load balancing.

(3) description of RestTemplate

GetForObject: the returned object is the object converted from the data in the response body, which can basically be understood as Json. GetForEntity: the return object is a ResponseEntity object, which contains some important information in the response, such as response header, response status code, response body, and so on. PostForObjectpostForEntity

1.3.The core component of Ribbon IRule

1. Major load rules

RoundRobinRule: polling

RandomRule: random

RetryRule: first obtain the service according to the policy of RoundRobinRule. If you fail to obtain the service, you will retry within the specified time.

WeightedResponseTimeRule: for the extension of RoundRobinRule, the faster the response is, the larger the weight of instance selection is, and the easier it is to be selected.

BestAvailableRule: first filter out the service that is in the circuit breaker tripping state due to multiple access failures, and then select a service with the least concurrency

AvailabilityFilteringRule: filter out failed instances first, and then select instances with less concurrency

ZoneAvoidanceRule: default rule, composite to determine the performance of the area where server is located and the availability of server to select the server

two。 How to replace load rules

Modify the configuration under the cloud-consumer-order80 package.

Our custom configuration class cannot be placed under the current package and subpackages scanned by @ ComponentScan, otherwise our custom configuration class will be shared by all Ribbon clients and will not achieve the purpose of special customization.

Create a new myrule child package under the com.xiao package.

Create a new MySelfRule configuration class under the myrule package

Import com.netflix.loadbalancer.IRule;import com.netflix.loadbalancer.RandomRule;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class MySelfRule {@ Bean public IRule getRandomRule () {return new RandomRule (); / / New Random access payload Rule}}

Modify the main startup class as follows:

Import com.xiao.myrule.MySelfRule;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;@SpringBootApplication@EnableEurekaClient@RibbonClient (name = "CLOUD-PAYMENT-SERVICE", configuration = MySelfRule.class) public class OrderMain80 {public static void main (String [] args) {SpringApplication.run (OrderMain80.class,args);}}

6. The test results are accessed randomly in our latest configuration.

1.4. Ribbon load balancing algorithm 1.4.1, polling algorithm principle load balancing algorithm:

The number of requests for rest interface% the total number of server clusters = the actual invocation server location subscript. The rest interface count starts from 1 after each service restart.

1.4.2. RoundRobinRule source code import com.netflix.client.config.IClientConfig;import java.util.List;import java.util.concurrent.atomic.AtomicInteger;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class RoundRobinRule extends AbstractLoadBalancerRule {private AtomicInteger nextServerCyclicCounter; private static final boolean AVAILABLE_ONLY_SERVERS = true; private static final boolean ALL_SERVERS = false; private static Logger log = LoggerFactory.getLogger (RoundRobinRule.class); public RoundRobinRule () {this.nextServerCyclicCounter = new AtomicInteger (0) } public RoundRobinRule (ILoadBalancer lb) {this (); this.setLoadBalancer (lb);} public Server choose (ILoadBalancer lb, Object key) {if (lb = = null) {log.warn ("no load balancer"); return null;} else {Server server = null; int count = 0 While (true) {if (server = = null & & count++)

< 10) { // 获取状态为up的服务提供者 List reachableServers = lb.getReachableServers(); // 获取所有的服务提供者 List allServers = lb.getAllServers(); int upCount = reachableServers.size(); int serverCount = allServers.size(); if (upCount != 0 && serverCount != 0) { // 对取模获得的下标进行获取相关的服务提供者 int nextServerIndex = this.incrementAndGetModulo(serverCount); server = (Server)allServers.get(nextServerIndex); if (server == null) { Thread.yield(); } else { if (server.isAlive() && server.isReadyToServe()) { return server; } server = null; continue; } log.warn("No up servers available from load balancer: " + lb); return null; } if (count >

= 10) {log.warn ("No available alive servers after 10 tries from load balancer:" + lb);} return server;} private int incrementAndGetModulo (int modulo) {int current; int next Do {/ / add module again and again current = this.nextServerCyclicCounter.get (); next = (current + 1)% modulo; / / CAS judge, return true if the judgment is successful, otherwise it will spin} while (! this.nextServerCyclicCounter.compareAndSet (current, next)); return next;} 1.4.3, handwritten polling algorithm

1. Modify the Controller of the payment module

Add the following

@ GetMapping (value = "/ payment/lb") public String getPaymentLB () {return ServerPort;}

2. Remove the @ LoadBalanced comment from ApplicationContextConfig

3. LoadBalancer interface

Import org.springframework.cloud.client.ServiceInstance;import java.util.List;public interface LoadBalancer {/ / collect the total number of machines that can provide services on the server, and put ServiceInstance instances (List serviceInstances) in list;}

4. Write MyLB classes

Import org.springframework.cloud.client.ServiceInstance;import org.springframework.stereotype.Component;import java.util.List;import java.util.concurrent.atomic.AtomicInteger;@Componentpublic class MyLB implements LoadBalancer {private AtomicInteger atomicInteger = new AtomicInteger (0); / / coordinate private final int getAndIncrement () {int current; int next; do {current = this.atomicInteger.get (); next = current > = 2147483647? 0: current + 1 } while (! this.atomicInteger.compareAndSet (current,next)); / / the first parameter is the expected value, and the second parameter is the modified value System.out.println ("* number of visits, times next:" + next); return next;} @ Override public ServiceInstance instances (List serviceInstances) {/ / get the list of machines int index = getAndIncrement ()% serviceInstances.size () / / get the subscript location of the server return serviceInstances.get (index);}}

5. Modify the OrderController class

Import com.xiao.cloud.entities.CommonResult;import com.xiao.cloud.entities.Payment;import com.xiao.cloud.lb.LoadBalancer;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cloud.client.ServiceInstance;import org.springframework.cloud.client.discovery.DiscoveryClient;import org.springframework.http.ResponseEntity;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;import javax.annotation.Resource;import java.net.URI;import java.util.List;@RestController@Slf4jpublic class OrderController {/ / public static final String PAYMENT_URL = "http://localhost:8001"; public static final String PAYMENT_URL =" http://CLOUD-PAYMENT-SERVICE"; @ Resource private RestTemplate restTemplate; @ Resource private LoadBalancer loadBalancer; @ Resource private DiscoveryClient discoveryClient @ GetMapping ("/ consumer/payment/create") public CommonResult create (Payment payment) {return restTemplate.postForObject (PAYMENT_URL+ "/ payment/create", payment,CommonResult.class); / / write operation} @ GetMapping ("/ consumer/payment/get/ {id}") public CommonResult getPayment (@ PathVariable ("id") Long id) {return restTemplate.getForObject (PAYMENT_URL+ "/ payment/get/" + id,CommonResult.class) } @ GetMapping ("/ consumer/payment/getForEntity/ {id}") public CommonResult getPayment2 (@ PathVariable ("id") Long id) {ResponseEntity entity = restTemplate.getForEntity (PAYMENT_URL+ "/ payment/get/" + id,CommonResult.class); if (entity.getStatusCode (). Is2xxSuccessful ()) {/ / log.info (entity.getStatusCode () + "\ t" + entity.getHeaders ()); return entity.getBody () } else {return new CommonResult (444, operation failed);} @ GetMapping (value = "/ consumer/payment/lb") public String getPaymentLB () {List instances = discoveryClient.getInstances ("CLOUD-PAYMENT-SERVICE"); if (instances = = null | | instances.size ()

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report