简介
- 用来做本地负载均衡
- 首先用户会访问到一台服务器(nginx负载均衡),然后通过用户指定的策略在服务器提供的服务注册表中选择一个地址(ribbon负载均衡)
- ribbon = 负责均衡+RestTemplate的调用
依赖
一般封装在eureka-client中,也可以单独调用
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>`在这里插入代码片`
RestTemplate
方法:postForObject 、getForObject、 postForObject、getForObject
- Object :json串
- Entity:一个对象,里面更加细致的划分了请求体、请求对象等
- 正常情况下推荐使用Object,需要详细信息就使用enitiy
使用
手写轮询
主要解决两个问题,轮询和加锁
- 轮询:设置一个变量,每次请求+1,之后得到的服务器是这个变量%总服务器数
- 加锁:自旋锁
自定义接口
public interface LoadBalancer {
// 这个方法负责接收服务实例列表,根据轮询返回一个
ServiceInstance instances(List<ServiceInstance> serviceInstanceList);
}
接口实现类
@Component
public class MyPolling implements LoadBalancer {
AtomicInteger atomicInteger = new AtomicInteger(0);
private final int getAndIncrement() { // 自旋锁实现的自增
int current;
int next;
do {
current = atomicInteger.get();
next = current == Integer.MAX_VALUE ? 0 : current + 1;
} while (!atomicInteger.compareAndSet(current, next));
return next;
}
@Override
public ServiceInstance instances(List<ServiceInstance> serviceInstanceList) {
int index = getAndIncrement() % serviceInstanceList.size();
return serviceInstanceList.get(index);
}
}
使用自定义轮询
@Resource
LoadBalancer loadBalancer;// 自己定义的接口
@Resource
DiscoveryClient discoveryClient;
@Resource
RestTemplate template;// 使用restTemplate访问restful接口 参数(url,请求参数,http响应被转换成的对象)
@GetMapping("/port")
public String getPort() {
List<ServiceInstance> instances = discoveryClient.getInstances("PAYMENT-SERVICE");
if (instances == null || instances.size() == 0) {
System.out.println("这个服务不存在");
return null;
}
ServiceInstance instance = loadBalancer.instances(instances);
return template.getForObject(instance.getUri() + "payment/port", String.class);
}