1、概述
-
是什么
-
官网资料
地址
Ribbon目前也进入维护模式
-
用途
LB(负载均衡)
- 集中式LB
- 进程内LB
2、Ribbon负载均衡演示
-
架构说明
总结:
Ribbon其实就是一个软负载均衡的客户端组件, 他可以和其他所需请求的客户端结合使用,和eureka结合只是其中一个实例.
-
RestTemplate的使用
-
官网
-
getForObject方法/getForEntity方法
@GetMapping("/consumer/payment/get/{id}") public CommonResult<Payment> getPayment(@PathVariable("id") Long id) { return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class); } @GetMapping("/consumer/payment/getForEntity/{id}") public CommonResult<Payment> getPayment2(@PathVariable("id") Long id) { ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_URL + "/payment/get/" + id, CommonResult.class); if (entity.getStatusCode().is2xxSuccessful()) { log.info("#############" + entity.getStatusCodeValue() + "################\t" + entity.getHeaders()); return entity.getBody(); } else { return new CommonResult<>(444, "操作失败"); } }
-
postForObject/postEntity
@GetMapping("/consumer/payment/create") public CommonResult<Payment> create(Payment payment) { return restTemplate.postForObject(PAYMENT_URL + "/payment/create", payment, CommonResult.class); }
-
3、Ribbon核心组件IRule
IRule:根据特定算法从服务列表中选取一个要访问的服务
如何替换
-
修改cloud-consumer-order80
-
注意配置细节
- 新建package
-
上面包下新建MySelfRule规则类
@Configuration public class MySelfRule { @Bean public IRule myRule() { // 定义为随机 return new RandomRule(); } }
-
主启动类添加@RibbonClient
@SpringBootApplication @EnableEurekaClient @RibbonClient(name = "CLOUD-PAYMENT-SERVICE", configuration = MySelfRule.class) public class OrderMain80 { public static void main(String[] args) { SpringApplication.run(OrderMain80.class, args); } }
-
测试
http://localhost/consumer/payment/get/31
4、Ribbon负载均衡算法
- 原理
-
源码
public Server choose(ILoadBalancer lb, Object key) { if (lb == null) { log.warn("no load balancer"); return null; } else { Server server = null; int count = 0; while(true) { if (server == null && count++ < 10) { List<Server> reachableServers = lb.getReachableServers(); List<Server> allServers = lb.getAllServers(); int upCount = reachableServers.size(); int serverCount = allServers.size(); if (upCount != 0 && serverCount != 0) { int nextServerIndex = this.incrementAndGetModulo(serverCount); server = (Server)allServers.get(nextServerIndex); if (server == null) { Thread.yield(); } else { if (server.isAlive() && server.isReadyToServe()) { return server; } server = null; } continue; } log.warn("No up servers available from load balancer: " + lb); return null; } if (count >= 10) { log.warn("No available alive servers after 10 tries from load balancer: " + lb); } return server; } } } private int incrementAndGetModulo(int modulo) { int current; int next; do { current = this.nextServerCyclicCounter.get(); next = (current + 1) % modulo; } while(!this.nextServerCyclicCounter.compareAndSet(current, next)); return next; }
-
自己试着写一个本地负载均衡器
-
7001/7002集群启动
-
8001/8002集群启动
1、controller改造
@GetMapping(value = "/payment/lb") public String getPaymentLB() { return serverPort; }
-
80订单微服务改造
1、ApplicationContextBean去掉注解@LoadBalanced
2、LoadBalancer接口
public interface LoadBalancer { ServiceInstance instance(List<ServiceInstance> serviceInstances); }
3、MyLB
@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 >= 214743647 ? 0 : current + 1; }while (!this.atomicInteger.compareAndSet(current,next)); System.out.println("##############naext:"+next); return next; } @Override public ServiceInstance instance(List<ServiceInstance> serviceInstances) { int index= getAndIncrement() % serviceInstances.size(); return serviceInstances.get(index); } }
-
**4、OrderController**
```java
@Resource
private DiscoveryClient discoveryClient;
@Resource
private LoadBalancer loadBalancer;
@GetMapping(value = "/consumer/payment/lb")
public String getPaymentLB() {
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PROVIDER-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);
}
```
**5、测试**
http://localhost/consumer/payment/lb
欢迎转载和分享,记得点赞呀