这里多个实例并发提供服务的方式为负载均衡,这里的负载均衡实现默认是因为Nacos集成了Ribbon来实现的,Ribbon配合RestTemplate,可以非常容易的实现服务之间的访问。Ribbon是Spring Cloud核心组件之一,它提供的最重要的功能就是客户端的负载均衡(客户端可以采用一定算法,例如轮询访问,访问服务端实例信息),这个功能可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡方式的服务调用。
@LoadBalanced注解是属于Spring,而不是Ribbon的,Spring在初始化容器的时候,如果检测到Bean被@LoadBalanced注解修饰,Spring会为其设置LoadBalancerInterceptor的拦截器。
1.1 修改sca-provider的配置文件端口,分别以8081,8082端口方式进行启动。
server:
port: 8081
spring:
application:
name: sca-provider
cloud:
nacos:
server-addr: localhost:8848
1.2 修改ConsumerController文件
package com.jt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.context.annotation.Bean;
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.activation.MailcapCommandMap;
import java.util.Random;
/**
* @author 小新
* @date 2021/08/17 10:49
*/
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
/**创建RestTemplate对象,然后基于此对象进行远程服务调用 */
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
@Bean
@LoadBalanced//这个注解描述RestTemplate对象时,系统底层会对RestTemplate对象的请求进行拦截
public RestTemplate loadBanlancerRestTemplate(){
return new RestTemplate();
}
@RestController
public class ConsumerController{
@Autowired
private RestTemplate restTemplate;
@Autowired
private RestTemplate loadBanlancerRestTemplate;
//负载均衡客户端对象(基于此对象可以从nacos中获取服务列表,并且可以基于一定的算法
//从列表中获取一个服务实例)
@Autowired
private LoadBalancerClient loadBalancerClient;
@Value("${spring.application.name}")
private String appName;
/**
* 负载均衡方式的调用1
* http://localhost:8090/consumer/ech1
* //1.手动负载均衡调用provider服务,url写死了,不灵活
* @return
*/
@GetMapping("/consumer/echo1")
public String doRestEcho1() {
//调用谁? sca-provider中的一个url
String url1 = "http://localhost:8081/provider/echo/"+appName;
String url2 = "http://localhost:8080/provider/echo/"+appName;
String urls[] = new String[]{url1,url2};
//随机获取一个小于urls数组长度的整数
int n = new Random().nextInt(urls.length);
System.out.println("n="+n);
//如何调用
return restTemplate.getForObject(urls[n],String.class);
}
/**
* 负载均衡方式的调用2
* http://localhost:8090/consumer/echo2
* //2.基于loadBanlancerClient方式获取服务实例
* @return
*/
@GetMapping("/consumer/echo2")
public String doRestEcho2(){
//2.基于loadBanlancerClient方式获取服务实例
String serviceId = "sca-provider";//这个名字要在nacos的服务列表中
ServiceInstance choose = loadBalancerClient.choose(serviceId);
String ip = choose.getHost();
int port = choose.getPort();
String url = String.format("http://%s:%s/provider/echo/%s", ip,port,appName);
return restTemplate.getForObject(url,String.class);
}
/**
* 负载均衡方式的调用3
* http://localhost:8090/consumer/echo3
* RestTemplate在发送请求的时候会被LoadBalancerInterceptor拦截,封装url地址
* @return
*/
@GetMapping("/consumer/echo3")
public String doRestEcho3(){
String serviceId = "sca-provider";//这个名字要在nacos的服务列表中
String url = String.format("http://%s/provider/echo/%s",serviceId,appName);
return loadBanlancerRestTemplate.getForObject(url,String.class);
}
}
}