Ribbon负载均衡器

两种:

1.1 集中式负载均衡,服务端负载均衡

硬件

nginx 轮询、负载、哈希、随机、权重

为什么要做负载均衡?

1.2 客户端负载均衡器

用客户端 负载均衡器 很多机制可以自定义

小知识:不想让别人调自己,只想用别人的,怎么做?

只需要不注册

spring.cloud.nacos.discovery.register-enabled = false

2.Ribbon

Spring Cloud Ribbon是基于Netflix Ribbon 实现的一套客户端的负载均衡工具,Ribbon客户端组件提供一系列的完善的配置,如超时机制,重试配置等。通过Load Balancer获取到服务提供的所有机器实例,Ribbon会自动基于某种规则(轮询,随机)去调用这些服务。Ribbon也可以实现我们自己的负载均衡算法。

spring cloud中的ribbon,客户端会有一个服务器地址列表,在发送请求前通过负载均衡算法选择一个服务器,然后进行访问,这是客户端负载均衡;即在客户端就进行负载均衡算法分配。

3.常见的负载均衡算法

如果使用的RestTemplate进行服务调用,那么创建RestTemplate的方法上面加@LoadBalanced注解就会开启Ribbon的负载均衡,Ribbon负载均衡有以下7中规则,默认轮询

  • 随机,通过随机选择服务进行执行,一般这种方式使用较少;

  • 轮询,负载均衡默认实现方式,请求来之后排队处理;

  • 加权轮询,通过对服务器性能的分型,给高配置,低负载的服务器分配更高的权重,均衡各个服务器的压力;

  • 地址Hash,通过客户端请求的地址的HASH值取模映射进行服务器调度。 ip --->hash

  • 最小链接数,即使请求均衡了,压力不一定会均衡,最小连接数法就是根据服务器的情况,比如请求积压数等参数,将请求分配到当前压力最小的服务器上。 最小活跃数

4.Nacos中使用Rabbion

nacos-discovery已经包含Ribbon的依赖,不需要再单独引入Ribbon

@LoadBalanced注解

java 复制代码
@Configuration
public class RestConfig {
    @Bean
    @LoadBalanced
//    负载器LoadBalance
    //如果使用了注册中心,必须加@LoadBalanced
    //作用:RestTemplate 就会把url上面的一级目录最为服务名,去注册中心找到对应的ip列表
    //根据算法使用其中一个ip,调用该ip对应的接口
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

5.Ribbon负载均衡策略

6.修改默认负载均衡策略

使用自己的规则-使用注解配置

java 复制代码
//@Configuration
//@RibbonClient(name = "nacos-a",configuration = MyRule.class)
//@RibbonClients(defaultConfiguration = RoundRobinRule.class)//全局定义负载规则
public class RibbonConfig {

    //@Bean //全局定义负载规则
    public IRule rule(){
//        return new NacosRule();
//        return new RandomRule();
        return new RoundRobinRule();//默认轮询
//        return new MyRule();
    }
}

自定义规则

java 复制代码
//@Component//需要注入,所以需放在组件里
@Slf4j
public class MyRule extends AbstractLoadBalancerRule {

    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;
//    NacosDiscovery 相关的属性
    @Autowired
    private NacosServiceManager nacosServiceManager;

//    JUC包 AtomicInteger高并发情况下保证原子性的类
    private static AtomicInteger cout  = new AtomicInteger(0);
   @Override
   @SneakyThrows
//   直接帮我们生成异常程序的,简化代码
//   key:default key指的是集群名称
    public Server choose(Object key) {
/*自定义规则流程:1.先找group
       2.通过group找到namingService
       3.通过namingService找到目前相关用的实例
         3.1 实例为空,做出一个报警
         3.2 实例不为空,找到拿出最大和最小权重,通过算法(逢5过)

*/
//            获取集群,然后加载
//            String clusterName = this.nacosDiscoveryProperties.getClusterName();
            String group = this.nacosDiscoveryProperties.getGroup();
            DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer)this.getLoadBalancer();
            String name = loadBalancer.getName();
//                 name 是服务名
            NamingService namingService = this.nacosServiceManager.getNamingService(this.nacosDiscoveryProperties.getNacosProperties());
//           可用的服务列表
            List<Instance> instances = namingService.selectInstances(name, group, true);
            if (CollectionUtils.isEmpty(instances)) {
                log.warn("no instance in service {}", name);
                return null;
            }
//                List<Instance> instancesToChoose = instances;
//                if (StringUtils.isNotBlank(clusterName)) {
//                    List<Instance> sameClusterInstances = (List)instances.stream().filter((instancex) -> {
//                        return Objects.equals(clusterName, instancex.getClusterName());
//                    }).collect(Collectors.toList());
//                    if (!CollectionUtils.isEmpty(sameClusterInstances)) {
//                        instancesToChoose = sameClusterInstances;
//                    } else {
//                        log.warn("A cross-cluster call occurs,name = {}, clusterName = {}, instance = {}", new Object[]{name, clusterName, instances});
//                    }
//                }

       Instance maxInstance = instances.stream().max(Comparator.comparing(Instance::getWeight)).get();
       Instance minInstance = instances.stream().min(Comparator.comparing(Instance::getWeight)).get();

       int count2 = cout.incrementAndGet();
//       数量加1
//       取余
       int mod = count2 % 5;
       if ((mod == 0)) {
           log.debug("count={},mod={},使用min",count2,mod);
           return new NacosServer(minInstance);
       }else {
           log.debug("count={},mod={},使用max",count2,mod);
           return new NacosServer(maxInstance);
       }
    }

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {
    }
}

基于配置文件配置,调用指定微服务提供的服务时,使用对应的负载均衡算法

java 复制代码
#配置全局的负载均衡规则(不生效)
default.ribbon.NFLoadBalancerRuleClassName = com.netflix.loadbalancer.RandomRule
#配置具体某一个服务个性化规则
nacos-a.ribbon.NFLoadBalancerRuleClassName = com.zxy.rule.MyRule

如果同时应用了以上两种方式去配置负载均衡,注解的优先级更高,则以注解为准.

因为配置文件的加载顺序在注解之前,后加载的配置会覆盖先前配置。

推荐使用配置文件,可以放进nacos,比较灵活

7.饥饿加载

在进行服务调用的时候,如果网络情况不好,第一次调用会超时。

Ribbon默认懒加载,意味着只有在发起调用的时候才会创建客户端。

开启饥饿加载,解决第一次调用慢的问题

java 复制代码
#ribbon.eager-load.enabled=true
#开启ribbon饥饿加载
#ribbon.eager-load.clients=nacos-a
#配置order-service使用ribbon饥饿加载,多个使用逗号分隔

8.内核原理

代码详情springcloud: springcloud

相关推荐
这儿有个昵称15 小时前
Java面试场景:从音视频到微服务的技术深挖
java·spring boot·spring cloud·微服务·面试·kafka·音视频
Remember_99315 小时前
深入理解 Java String 类:从基础原理到高级应用
java·开发语言·spring·spring cloud·eclipse·tomcat
鸽鸽程序猿1 天前
【JavaEE】【SpringCloud】注册中心_nacos
java·spring cloud·java-ee
递归尽头是星辰1 天前
Spring Cloud Alibaba 核心理论体系:Nacos、Sentinel、Seata深度解析
spring cloud·nacos·sentinel·seata·微服务治理
lpfasd1231 天前
springcloud docker 部署问题排查与解决方案
spring·spring cloud·docker
蓝眸少年CY1 天前
(第七篇)spring cloud之Hystrix断路器
spring·spring cloud·hystrix
蓝眸少年CY1 天前
(第八篇)spring cloud之zuul路由网关
后端·spring·spring cloud
We....2 天前
SpringBoot 微服务拦截器与负载均衡实践
java·spring boot·微服务·负载均衡
码出财富2 天前
SpringBoot 内置的 20 个高效工具类
java·spring boot·spring cloud·java-ee
daladongba2 天前
Spring Cloud Gateway
java·spring cloud·gateway