SpringCloud-Ribbon Load Balancing

1. Introduction to Spring Cloud Ribbon

Spring Cloud Ribbon is a set of client load balancing tools based on Netflix Ribbon.
Simply put, Ribbon is an open source project published by Netflix that provides client-side software load balancing algorithms and service calls. The Ribbon client component provides a complete set of configuration items such as connection timeouts, retries, and so on. Simply put, by listing all the machines behind Load Balancer (LB) in the configuration file, Ribbon will automatically help you connect them based on certain rules (such as simple polling, random connections, etc.). It is easy to use Ribbon to implement custom load balancing algorithms


2. Ribbon provides seven load balancing strategies

Nameexplain
RoundRobinRuleRound Robin strategy
RandomRuleRandom strategy
BestAvailableRuleAfter filtering out the failed server, select one with the smallest concurrency
WeightedResponseTimeRuleWeighted polling for response time
AvailabilityFilteringRuleA filtering strategy is available that first filters out some service instances that are failing or have concurrent requests greater than the threshold, then selects one from the filtered list of instances in a linear polling fashion
ZoneAvoidanceRuleSelect a service instance with the best performance from the set of best region instances
RetryRuleSelect a Server, and if it fails, re-select a Server to try again

3. How to use Ribbon in a microservice architecture

Only the following steps are required:

  1. A service provider only needs to start multiple service instances and register with one registry or multiple associated service registries
  2. Specify polling rules for services
  3. Service consumers (which pull a list of registration information from the registry) make service-oriented interface calls directly by calling RestTemplate decorated with the @LoadBalanced annotation

3.1 Introducing ribbon dependency

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

3.2 Fill the container with RestTemplate

// Use the @LoadBalanced annotation to give RestTemplate load balancing capabilities
@Bean
@LoadBalanced
public RestTemplate createRestTemplate(){
    return new RestTemplate();
}

3.3 Specify polling rules for clients

Injection load balancing rule, polling by default
Custom ribbon's polling rules cannot be configured under the @ComponentScan annotation's scan package or will take effect on all @RibbonClient s

@Configuration
public class MyRibbonRuleConfig {
    @Bean
    public IRule myRule(){
        return new RandomRule();
    }
}


// Startup class specifies load balancing rules for a service
@SpringBootApplication
@EnableEurekaClient
// Modify the rotation rules for the PROVIDER-PAYMENT-8001-3 service. If multiple different services use different rules, then configure multiple @RibbonClients in @RibbonClients
@RibbonClients(value = {@RibbonClient(name="PROVIDER-PAYMENT-8001-3",configuration = MyRibbonRuleConfig.class)})
public class EurekaOrder80Start {
    public static void main(String[] args) {
        SpringApplication.run(EurekaOrder80Start.class,args);
    }
}

3.4 Use RestTemplate to invoke services

 // Called by a microservice name registered on eureka
public static final String PAYMENT_SRV = "http://PROVIDER-PAYMENT-8001-3/study";

@Resource
private RestTemplate restTemplate;

// 127.0.0.1/study/consumer/payment/create?serial=xiaohong
@GetMapping("/consumer/payment/create")
public CommonResult create(Payment payment)
{
    return restTemplate.postForObject(PAYMENT_SRV + "/provider/payment/insertPayment",payment,CommonResult.class);
}

4. How to use RestTemplate

4.1 GET Request

4.1.1 getForObject

getForObject has three overload methods

  • public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables)
    This method provides three parameters, where url is the address of the request, responseType is the wrapper type of the body of the request response, and urlVariables is the parameter binding in the url

  • public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
    This method is similar to the one above except that the parameters are encapsulated in a map.

  • public <T> T getForObject(URI url, Class<T> responseType)
    Encapsulate request addresses and parameters using a uniform resource identifier

/**
 * Call demo for the three overloaded methods of getForObject
 * 127.0.0.1/study/restTemplateTestOrder/payment/getObject_1/1
 * @param id
 * @return
 */
@GetMapping("/restTemplateTestOrder/payment/getObject_1/{id}")
public CommonResult getPayment(@PathVariable Long id)
{
	CommonResult commonResult = new CommonResult();
	Map<String,CommonResult> resultMap = new HashMap<>();
	// getForObject(String url, Class<T> responseType, Object... uriVariables)
	CommonResult result1 = restTemplate.getForObject(PAYMENT_SRV + "/restTemplateTestPayment/payment/get_1/" + id, CommonResult.class, id);
	CommonResult result2 = restTemplate.getForObject(PAYMENT_SRV + "/restTemplateTestPayment/payment/{1}/{2}", CommonResult.class, "get_1",id);

	CommonResult result3 = restTemplate.getForObject(PAYMENT_SRV + "/restTemplateTestPayment/payment/get_2?id=" + id, CommonResult.class, id);
	CommonResult result4 = restTemplate.getForObject(PAYMENT_SRV + "/restTemplateTestPayment/payment/get_2?id={1}&serial={2}", CommonResult.class, id,"Xiao Ming");
	resultMap.put("result1",result1);
	resultMap.put("result2",result2);
	resultMap.put("result3",result3);
	resultMap.put("result4",result4);

	// getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
	Map<String, Object> param = new HashMap<>();
	param.put("id",id);
	param.put("get_1","get_1");
	param.put("serial","Xiaowang");
	CommonResult result5 = restTemplate.getForObject(PAYMENT_SRV + "/restTemplateTestPayment/payment/{get_1}/{id}", CommonResult.class, param);
	CommonResult result6 = restTemplate.getForObject(PAYMENT_SRV + "/restTemplateTestPayment/payment/get_2?id={id}&serial={serial}", CommonResult.class, param);
	resultMap.put("result5",result5);
	resultMap.put("result6",result6);

	// getForObject(URI url, Class<T> responseType)
	MultiValueMap<String,String> mapParam = new LinkedMultiValueMap();
	mapParam.add("serial","Xiao Wang 1");
	mapParam.add("serial","Xiao Wang 2");
	URI uri = UriComponentsBuilder.fromUriString(PAYMENT_SRV + "/restTemplateTestPayment/payment/get_2?id={id}")
			.queryParams(mapParam) // Set Query Parameters
			.build()
			.expand(id) // Replace template parameters in url
			.encode(StandardCharsets.UTF_8) // Set Encoding
			.toUri();
	CommonResult result7 = restTemplate.getForObject(uri, CommonResult.class);
	resultMap.put("result7",result7);

	commonResult.setData(resultMap);
	return commonResult;
}

4.1.2 getForEntity

  • public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables)
  • public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)
  • public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType)

These three methods and 4.1. The three methods in 1 correspond. Only ResponseEntity is returned.
Response headers, response status, response volume, and other information can be obtained through responseEntity.
//Status Information
HttpStatus statusCode = responseEntity.getStatusCode();
int statusCodeValue = responseEntity.getStatusCodeValue();

//Request Header Information
HttpHeaders headers = responseEntity.getHeaders();

//Response Body
T body = responseEntity.getBody();

4.2 POST Request

Description of the second parameter, Object request, in the post request:

As you can see from the source code, if we passed in a non-HttpEntity, it would be encapsulated as a HttpEntity. During the actual invocation, we can use a parameter of type Object that is passed into the body of the request, just as the front end sends a post request. We can then invoke the service provider's post interface.

4.2.1 postForObject

  • public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType,Object... uriVariables)
  • public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType,Map<String, ?> uriVariables)
  • public <T> T postForObject(URI url, @Nullable Object request, Class<T> responseType)

4.2.2 postForObject

  • public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request,Class<T> responseType, Object... uriVariables)
  • public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request,Class<T> responseType, Map<String, ?> uriVariables)
  • public <T> ResponseEntity<T> postForEntity(URI url, @Nullable Object request, Class<T> responseType)

4.2.3 postForLocation

  • public URI postForLocation(String url, @Nullable Object request, Object... uriVariables)
  • public URI postForLocation(String url, @Nullable Object request, Map<String, ?> uriVariables)
  • public URI postForLocation(URI url, @Nullable Object request)
    This method implements submitting a resource with a POST request and returns the URI of the new resource. This allows us to call the public <T> ResponseEntity<T> postForObject/postForEntity (URI url, @Nullable Object request, Class <T> responseType) or public <T> T getForObject/getForEntity/(URI url, Class <T> responseType) methods as parameters. This enables redirection.

5. @LoadBalanced Principle (to be completed)

spring-cloud-consul-discovery-2.2.1.RELEASE.jar
spring.factories
org.springframework.cloud.consul.discovery.RibbonConsulAutoConfiguration
org.springframework.cloud.client.loadbalancer.LoadBalancerClient


6. Configuration of Ribbon

ribbon:
  #Refers to the time taken to establish a connection, and is applicable to the time taken to connect both ends under normal network conditions.
  ReadTimeout: 6000
  #Refers to the time taken to read the available resources from the server after a connection has been established
  ConnectTimeout: 6000
  eureka:
    enabled: true

You can also set different timeouts for each Ribbon client, specified by the service name (ribbon-config-demo):
ribbon-config-demo.ribbon.ConnectTimeout=2000
ribbon-config-demo.ribbon.ReadTimeout=5000

Manually configure the address of the ribbon-config-demo service when Eureka is disabled (ribbon.eureka.enabled=false)
ribbon-config-demo.ribbon.listOfServers=localhost:8081,localhost:8083


7. Demo example

gitee Address cloud-eureka-consumer-order80 and cloud-eureka-provider-payment8001-3 modules

Reference address:
https://www.jianshu.com/p/1bd66db5dc46
https://zhuanlan.zhihu.com/p/262660637
https://www.springcloud.cc/spring-cloud-greenwich.html#spring-cloud-ribbon

Keywords: Load Balance Spring Cloud ribbon RestTemplate

Added by ankhmor on Sat, 01 Jan 2022 11:09:15 +0200