文章目录
使用Ribbon自带负载均衡算法
添加负载均衡算法Configuration
java
//注意package位置假设启动器为@ComponentScan("com.test.springcloud")
package com.test.config
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MySelfRule
{
@Bean
public IRule myRule()
{
return new RandomRule();//定义为随机
}
}
注意:
官方文档明确给出了警告 :
这个自定义配置类不能放在@ComponentScan所扫描的当前包下以及子包下,
否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,达不到特殊化定制的目的了。
RestTemplate使用上面负载均衡算法
java
package com.test.springcloud.config
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ApplicationContextConfig
{
@Bean
@LoadBalanced //添加负载均衡配置注解,如果自定义的话不需要使用该注解否则报错
public RestTemplate getRestTemplate()
{
return new RestTemplate();
}
}
自定义负载均衡算法
负载均衡算法实现
定义负载均衡算法接口
java
public interface LoadBalancer
{
ServiceInstance instances(List<ServiceInstance> serviceInstances);
}
实现负载均衡算法
java
@Component
public class MyLB implements LoadBalancer
{
//通过CAS(乐观锁)的方式进行,本质是通过CompareAndSet,先比较后赋值的方式,只有当前值和期望值相同时才可以进行赋值
private AtomicInteger atomicInteger = new AtomicInteger(0);
public final int getAndIncrement()
{
int current;
int next;
do {
current = this.atomicInteger.get();
next = current >= 2147483647 ? 0 : current + 1;
}while(!this.atomicInteger.compareAndSet(current,next));
System.out.println("*****第几次访问,次数next: "+next);
return next;
}
//负载均衡算法:rest接口第几次请求数 % 服务器集群总数量 = 实际调用服务器位置下标 ,每次服务重启动后rest接口计数从1开始。
@Override
public ServiceInstance instances(List<ServiceInstance> serviceInstances)
{
int index = getAndIncrement() % serviceInstances.size();
return serviceInstances.get(index);
}
}
以上实现负载均衡算法的instance可自定义
RestTemplate
java
package com.test.springcloud.config
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ApplicationContextConfig
{
@Bean
//@LoadBalanced //去掉这个注解
public RestTemplate getRestTemplate()
{
return new RestTemplate();
}
}
在Controller中使用该负载均衡算法
java
public class Controller{
@GetMapping(value = "/consumer/payment/lb")
public String getPaymentLB()
{
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
if(instances == null || instances.size() <= 0)
{
return null;
}
// 在下面有解释ServiceInstance
ServiceInstance serviceInstance = loadBalancer.instances(instances);
URI uri = serviceInstance.getUri();
return restTemplate.getForObject(uri+"/payment/lb",String.class);
}
}
ServiceIInstance解释
ServiceInstance 是 Spring Cloud 提供的一个接口,用于表示服务的实例信息。它提供了获取服务实例的相关信息和元数据的方法。
ServiceInstance 接口定义了以下常用方法:
- String getServiceId(): 获取服务名称(serviceId)。
- String getHost(): 获取服务实例的主机名。
- int getPort(): 获取服务实例的端口号。
- boolean isSecure(): 返回服务实例是否使用安全协议(如 HTTPS)进行通信。
- URI getUri(): 获取服务实例的完整 URI。
- Map<String, String> getMetadata(): 返回服务实例的元数据,这些元数据可以由服务提供方自定义。
- 通过使用 DiscoveryClient(服务发现客户端)获取到的服务实例列表,可以进一步使用 ServiceInstance 接口来获取每个服务实例的具体信息。
示例:
java
@Autowired
private DiscoveryClient discoveryClient;
public void getServiceInstances(String serviceName) {
List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);
for (ServiceInstance instance : instances) {
String serviceId = instance.getServiceId();
String host = instance.getHost();
int port = instance.getPort();
boolean isSecure = instance.isSecure();
URI uri = instance.getUri();
Map<String, String> metadata = instance.getMetadata();
// 打印服务实例信息
System.out.println("Service ID: " + serviceId);
System.out.println("Host: " + host);
System.out.println("Port: " + port);
System.out.println("Is Secure: " + isSecure);
System.out.println("URI: " + uri);
System.out.println("Metadata: " + metadata);
}
}