Ribbon负载均衡
负载均衡即在服务注册中心查找空闲的服务端口不会将全部的访问压力给到一个端口
restTemplate中getForObject与getForEntity区别
getForObject返回的是json形式
@GetMapping("/consumer/payment/get/{id}")
public CommonResult<Payment> getPayment(@PathVariable("id") Long id)
{
return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
}
getForEntity返回的是ResponseEntity形式,包含一些响应头,状态码,响应体等信息
@GetMapping("/consumer/payment/getForEntity/{id}")
public CommonResult<Payment> getPayment1(@PathVariable("id") Long id){
ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_URL+"/payment/get/"+id, CommonResult.class);
if(entity.getStatusCode().is2xxSuccessful()){
return entity.getBody();
}else {
return new CommonResult<>(400,"操作失败");
}
}
Ribbon中IRule自带的算法
RoundRobinRule轮询
RandomRule随机
RetryRule先按照RoundRobinRule的策略获取服务,如果获取失败则在指定时间内会进行重试,获取可用的服务
WeighedResponseTimeRule对RoundRobinRule的扩展,响应速度越快的实例选择权重越大,越容易被选择
Best AvailableRule会过滤掉由于多次访问故障而处于短路器跳匝状态的服务(熔断,限流),然后选择一个并发量最小的服务
AvailabilityFilteringRule先过滤掉故障实例,再选择并发较小的实例
ZoneAvoidanceRule默认规则,复合判断server所在区域的性能和server的可用性选择服务器
替换默认IRule轮转算法
添加配置类MySelfRule并在启动类上添加注解@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration= MySelfRule.class)
@Configuration public class MySelfRule { @Bean public IRule myRule() { return new RandomRule();//定义为随机 } }
警告:
自定义配置类不可放在@ComponenScan所扫描的当前包下及其子包
即不能放在启动类包下及其子包
RoundRobinRule原理
算法:实际调用服务器位置=rest接口第几次请求数%服务器集群总数(每次服务器重启后rest=1)
自己实现负载均衡算法
创建lb包创建LoadBalancer接口//收集现有的服务器数量
public interface LoadBalancer { ServiceInstance instance(List<ServiceInstance> serviceInstances);//收集现有的服务器数量 }
创建实现类
@Component public class MyLB implements LoadBalancer{ 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; } @Override public ServiceInstance instance(List<ServiceInstance> serviceInstances) { int index=getAndIncrement()%serviceInstances.size();//实际调用服务器位置=rest接口第几次请求数%服务器集群总数 return serviceInstances.get(index); } }
切记关闭@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration= MySelfRule.class)注解
controller层代码实现:
@GetMapping("/consumer/payment/lb") public String getPaymentLB(){ List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");//获取这个名称的服务 if(instances==null||instances.size()<=0){ return null; } ServiceInstance serviceInstance=loadBalancer.instance(instances);//传入服务 URI uri = serviceInstance.getUri(); return restTemplate.getForObject(uri+"/payment/lb",String.class); }
结果显示