Springcloud_H版-alibaba学习笔记(十一) 服务调用-Ribbon(负载均衡调用)

十一、服务调用-Ribbon(负载均衡调用)

1.概述

1.Ribbon是什么

Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon来实现的,包括后续我们将要介绍的Feign,它也是基于Ribbon实现的工具。所以,对Spring Cloud Ribbon的理解和使用,对于我们使用Spring Cloud来构建微服务非常重要。

实现负载均衡的算法

2.官网

https://github.com/Netflix/ribbon/wiki/Getting-Started

3.能干嘛

LB(负载均衡):集中式LB、进程内LB
一句话概括:负载均衡+RestTemplate调用。

2.RestTemplate的使用

getForObject/postForObject方法:返回json格式
getForEntity/postEntity方法:返回Entity格式, 之外还带有更加详细的信息,如头信息等。

3.pom

spring-cloud-starter-netflix-eureka-client包中包含spring-cloud-starter-netflix-ribbon包, 故不需要额外引入。

4.Ribbon核心组件IRule

作用:根据特定算法从服务列表中选取一个要访问的服务。

1.IRule算法列表

  • com.netflix.loadbalancer.RoundRobinRule
    • 轮询
  • com.netflix.loadbalancer.RandomRule
    • 随机
  • com.netflix.loadbalancer.RetryRule
    • 先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内进行重试,获取可用的服务
  • WeightedResponseTimeRule
    • 对RoundRobinRule的扩展,响应速度越快的实例选择权重越多大,越容易被选择
  • BestAvailableRule
    • 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
  • AvailabilityFilteringRule
    • 先过滤掉故障实例,再选择并发较小的实例
  • ZoneAvoidanceRule
    • 默认规则,复合判断server所在区域的性能和server的可用性选择服务器

2.替换默认IRule算法

1.在eureka-order80工程中新建规则定义包com.dt.myrule

注意,不能与主启动类在同一个包下!

2.创建规则配置类MySelfRule
package com.dt.myrule;  
  
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 diyRule() {  
        // 随机算法  
        return new RandomRule();  
    }  
}
3.主启动类添加@RibbonClient
package com.dt.springcloud;  
  
import com.dt.myrule.MySelfRule;  
import org.springframework.boot.SpringApplication;  
import org.springframework.boot.autoconfigure.SpringBootApplication;  
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;  
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;  
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;  
import org.springframework.cloud.netflix.ribbon.RibbonClient;  
  
/**  
 * 主启动类  
 * 若项目不需要连接数据库,需要增加:@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})  
 */@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})  
@EnableEurekaClient  
@EnableDiscoveryClient  
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE", configuration = MySelfRule.class)// 作用是替换ribbon负载均衡规则  
public class OrderMain80 {  
    public static void main(String[] args) {  
        SpringApplication.run(OrderMain80.class, args);  
    }  
}

5.Ribbon负载均衡算法

1.原理

rest接口第几次请求次数 % 服务器集群总数量 = 实际调用服务器位置下标,每次服务器重启后,rest接口计数从1开始。

在这里插入图片描述

2.自定义本地负载均衡器。

1.支付8001和8002controller增加获得端口方法。
/**  
 * 获得服务及端口。  
 * @return  
 */@GetMapping("/payment/lb")  
public String getPaymentLB()  
{  
    return serverPort;  
}
2.订单80的ApplicationContextConfig 注释掉@LoadBalanced ,以便使用自己的Lb算法。
3.自定义LoadBalancer接口
package com.dt.springcloud.loadbalanced;  
  
import org.springframework.cloud.client.ServiceInstance;  
  
import java.util.List;  
  
/**  
 * LoadBalancer 接口  
 */  
public interface LoadBalancer {  
  
    /**  
     * 收集服务器总共有多少台能够提供服务的机器,并放到list里面  
     * <p>  
     * 因为有List<ServiceInstance> serviceInstanceList = discoveryClient.getInstances(PAYMENT_SERVICE_NAME);     *     * @param serviceInstances:  
     */    ServiceInstance instances(List<ServiceInstance> serviceInstances);  
}
4.LoadBanlancer实现类
package com.dt.springcloud.loadbalanced;  
  
import lombok.extern.slf4j.Slf4j;  
import org.springframework.cloud.client.ServiceInstance;  
import org.springframework.stereotype.Component;  
  
import java.util.List;  
import java.util.concurrent.atomic.AtomicInteger;  
  
/**  
 * LoadBalancer实现类 
 * */
@Component  
@Slf4j  
public class MyLoadBalancer implements LoadBalancer {  
  
    private final AtomicInteger atomicInteger = new AtomicInteger(0);  
  
  
    /**  
     * 获取下一次要调用的服务实例 下标  
     */  
    @Override  
    public ServiceInstance instances(List<ServiceInstance> serviceInstances) {  
        int index = this.getAndIncrement() % serviceInstances.size();  
        return serviceInstances.get(index);  
    }  
  
  
    /**  
     * 自写负载均衡算法: rest接口第几次请求数% 服务集群实例总数量 = 实际调用服务实例下标 ,每次重启后rest接口计数从1开始  
     */  
    private int getAndIncrement() {  
        int current;  
        int next;  
        // atomicInteger.compareAndSet  自旋锁  
        do {  
            current = this.atomicInteger.get();  
            // 2147483647 就是Integer.MAX_VALUE  
            next = current >= 2147483647 ? 0 : current + 1;  
        } while (!this.atomicInteger.compareAndSet(current,next));  
        log.info("====>*******第几次访问,次数next:{}",next);  
        return next;  
    }  
}
5.业务类改造,新增以下内容
    /**  
     * 注入自定义负载均衡对象  
     */  
    @Autowired  
    private LoadBalancer myLoadBalancer;  
    /**  
     * 注入RestTemplate对象  
     */  
    @Autowired  
//    @Qualifier("diyLoadBalancedRestTemplate")  
    private RestTemplate myLoadBalancedRestTemplate;  
  
    /**  
     * 自定义负载均衡算法Test  
     * 返回对象为ResponseEntity对象,包含了响应体的重要信息: 响应头、响应状态码、响应体等  
     *  
     * @return R     */    @GetMapping("/consumer/diyLoadBalancedTest")  
    public String getPaymentLoadBalanced() {  
        log.info("/consumer/diyLoadBalancedTest");  
        List<ServiceInstance> instances = discoveryClient.getInstances("cloud-payment-service");  
        log.info("instancesSize=" + instances.size());  
        if (instances == null || instances.size() <= 0) {  
            return null;  
        }  
        ServiceInstance serviceInstance = myLoadBalancer.instances(instances);  
        URI uri = serviceInstance.getUri();  
        log.info("uri:" + uri);  
        return myLoadBalancedRestTemplate.getForObject(uri + "/payment/lb/getServerPort", String.class);  
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值