本篇示例我就以Nacos注册中心为例了,下面是我注册的两个服务。其中nacos-payment-provider
服务是集群,有两个实例。
如果使用的Nacos为注册中心的时候会发现一个问题,当引入的依赖版本比较高的时候,RestTemplate
+@LoadBalanced
通过服务名称调用的时候会报错,使用其他注册中心默认都会引用ribbon依赖,因此我们只需要在注入RestTemplate
的时候加上@LoadBalanced
就可以实现根据名称负载均衡调用。
而nacos高版本依赖包没有引用ribbon依赖。ribbon早就已经彻底停更了,spring又自己出了一个
loadbalancer
负载均衡框架,来配合RestTemplate
使用。但是他并没有自动引用loadbalancer依赖所以我们需要自己引用才可以使用。
@Configuration
public class ApplicationContextBean {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
使用如下获取ip端口的前提:引用了loadbalancer来作为负载均衡
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-loadbalancerartifactId>
dependency>
loadBalancerClient.choose()
这个方法就是负载均衡的核心方法。假如服务名称为nacos-payment-provider有两个实例,一个9001一个9002,通过如下方法调用会发现每次都是在轮询。
@Autowired
private LoadBalancerClient loadBalancerClient;
@GetMapping("/getServiceInstance")
public ServiceInstance getServiceInstance() {
ServiceInstance serviceInstance = loadBalancerClient.choose("nacos-payment-provider");
System.out.println(serviceInstance.getHost()); // ip
System.out.println(serviceInstance.getPort()); // 端口
System.out.println(serviceInstance.getInstanceId()); // 实例id
System.out.println(serviceInstance.getServiceId()); // 服务id
System.out.println(serviceInstance.getMetadata()); // 与服务实例关联的元数据
System.out.println(serviceInstance.getScheme()); // 返回服务实例的方案
System.out.println(serviceInstance.getUri().toString()); // 返回服务的uri地址
return serviceInstance;
}
loadbalancer源码:
这种方式其他注册中心也可以使用!
@Resource
private DiscoveryClient discoveryClient;
@GetMapping("/getServiceInstanceList")
public List getServiceInstanceList() {
// 根据服务名称查找所有的实例
return discoveryClient.getInstances("nacos-payment-provider");
}
DiscoveryClient这个其实是个接口存放于cloud-commons包当中。
既然是接口为什么他能获取到呢?我们可以看他的实现类,是有如下实现类的,也就是在nacos的服务发现依赖当中会存在他的实现类,并注入到容器当中了。其他注册中心也是同样如此。可以说这个接口是共用的,其他的注册中心都可以来实现。
这个是nacos独有的!
@Autowired
private NacosServiceManager nacosServiceManager;
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;
@GetMapping("/nacos")
public List getGatewayAddress() {
String res = null;
try {
NamingService namingService = nacosServiceManager.getNamingService(nacosDiscoveryProperties.getNacosProperties());
List allInstances = namingService.getAllInstances("nacos-payment-provider");
return allInstances;
} catch (NacosException e) {
e.printStackTrace();
return null;
}
}