problem
A service instance can process requests is limited. If the concurrent access of a service instance is relatively large, we will start multiple service instances and let these service instances process concurrent requests with certain policy balancing (polling, weight, random, hash, etc.). How is the service load balancing (Nacos client load balancing) applied in Nacos?
LoadBalancerClient application
The LoadBalancerClient object can obtain the service instance from nacos based on the service name, and then call the load balancing method based on a specific algorithm in the project. The case implementation is as follows:
Step 1: modify the ConsumerController class, inject the LoadBalancerClient object, add the doRestEcho2 method, and then access the service
@Autowired private LoadBalancerClient loadBalancerClient; @Value("${spring.application.name:8090}") private String appName; @GetMapping("/consumer/doRestEcho02") public String doRestEcho02(){ ServiceInstance serviceInstance = loadBalancerClient.choose("sca-provider"); String url = String.format("http://%s:%s/provider/echo/%s",serviceInstance.getHost(),serviceInstance.getPort(),appName); System.out.println("request url:"+url); return restTemplate.getForObject(url, String.class); } }
Step 2: open the Idea service startup configuration, as shown in the figure:
Step 3: modify the concurrent Run option (if this option is not found, we need to find the corresponding solution through the search engine based on combined query, such as searching idea allow parallel run), as shown in the figure:
Step 4: modify the configuration file port of SCA provider and start it in the mode of 80818082 port respectively.
server: port: 8082 spring: application: name: sca-provider cloud: nacos: server-addr: localhost:8848
Step 5: after successful startup, access the service list of nacos and check whether the service is successfully registered, as shown in the figure:
Step 6: start the SCA consumer project module, open the browser to access the consumer service, refresh constantly during access, and detect the changes of page data.
Note: the way multiple instances provide services concurrently here is load balancing. The default implementation of load balancing here is because Nacos integrates the Ribbon. The Ribbon can easily access services with RestTemplate.
Ribbon is one of the core components of Spring Cloud. The most important function it provides is the load balancing of the client (the client can adopt certain algorithms, such as polling access and accessing the instance information of the server). This function allows us to easily automatically convert the service-oriented REST template requests into service calls in the client load balancing mode.
@LoadBalanced
When using RestTemplate for remote service calls, if load balancing is required, you can also use @ LoadBalanced to modify the method of building RestTemplate when building RestTemplate object. For example, build a RestTemplate object named loadBalancedRestTemplate in ConsumerApplication:
@Bean @LoadBalanced public RestTemplate loadBalancedRestTemplate(){ return new RestTemplate(); }
Next, in the method of the corresponding service caller, the service can be called with the help of the service name based on RestTemplate, for example:
@GetMapping("/consumer/doRestEcho3") public String doRestEcho03(){ String url=String.format("http://%s/provider/echo/%s","sca-provider",appName); //Send an http request to the service provider to obtain the response data return loadBalancedRestTemplate.getForObject( url,//The address of the service to request String.class);//String.class is the response result type of the request service }
RestTemplate will be intercepted by LoadBalancerInterceptor when sending a request. It is used for load balancing of RestTemplate. Loadbalancerinceptor gives the core logic of load balancing to loadBalancer. The core code is as follows (understand):
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException { final URI originalUri = request.getURI(); String serviceName = originalUri.getHost(); return this.loadBalancer.execute(serviceName, requestFactory.createRequest(request, body, execution)); }
@The LoadBalanced annotation belongs to Spring, not the Ribbon. When Spring initializes the container, if it detects that the Bean is @ LoadBalanced annotated, Spring will set the interceptor of loadbalancerinceptor for it.