• 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注解

    1. @Configuration
    2. public class RestConfig {
    3. @Bean
    4. @LoadBalanced
    5. // 负载器LoadBalance
    6. //如果使用了注册中心,必须加@LoadBalanced
    7. //作用:RestTemplate 就会把url上面的一级目录最为服务名,去注册中心找到对应的ip列表
    8. //根据算法使用其中一个ip,调用该ip对应的接口
    9. public RestTemplate restTemplate(){
    10. return new RestTemplate();
    11. }
    12. }

    5.Ribbon负载均衡策略

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

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

    1. //@Configuration
    2. //@RibbonClient(name = "nacos-a",configuration = MyRule.class)
    3. //@RibbonClients(defaultConfiguration = RoundRobinRule.class)//全局定义负载规则
    4. public class RibbonConfig {
    5. //@Bean //全局定义负载规则
    6. public IRule rule(){
    7. // return new NacosRule();
    8. // return new RandomRule();
    9. return new RoundRobinRule();//默认轮询
    10. // return new MyRule();
    11. }
    12. }

    自定义规则

    1. //@Component//需要注入,所以需放在组件里
    2. @Slf4j
    3. public class MyRule extends AbstractLoadBalancerRule {
    4. @Autowired
    5. private NacosDiscoveryProperties nacosDiscoveryProperties;
    6. // NacosDiscovery 相关的属性
    7. @Autowired
    8. private NacosServiceManager nacosServiceManager;
    9. // JUC包 AtomicInteger高并发情况下保证原子性的类
    10. private static AtomicInteger cout = new AtomicInteger(0);
    11. @Override
    12. @SneakyThrows
    13. // 直接帮我们生成异常程序的,简化代码
    14. // key:default key指的是集群名称
    15. public Server choose(Object key) {
    16. /*自定义规则流程:1.先找group
    17. 2.通过group找到namingService
    18. 3.通过namingService找到目前相关用的实例
    19. 3.1 实例为空,做出一个报警
    20. 3.2 实例不为空,找到拿出最大和最小权重,通过算法(逢5过)
    21. */
    22. // 获取集群,然后加载
    23. // String clusterName = this.nacosDiscoveryProperties.getClusterName();
    24. String group = this.nacosDiscoveryProperties.getGroup();
    25. DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer)this.getLoadBalancer();
    26. String name = loadBalancer.getName();
    27. // name 是服务名
    28. NamingService namingService = this.nacosServiceManager.getNamingService(this.nacosDiscoveryProperties.getNacosProperties());
    29. // 可用的服务列表
    30. List instances = namingService.selectInstances(name, group, true);
    31. if (CollectionUtils.isEmpty(instances)) {
    32. log.warn("no instance in service {}", name);
    33. return null;
    34. }
    35. // List instancesToChoose = instances;
    36. // if (StringUtils.isNotBlank(clusterName)) {
    37. // List sameClusterInstances = (List)instances.stream().filter((instancex) -> {
    38. // return Objects.equals(clusterName, instancex.getClusterName());
    39. // }).collect(Collectors.toList());
    40. // if (!CollectionUtils.isEmpty(sameClusterInstances)) {
    41. // instancesToChoose = sameClusterInstances;
    42. // } else {
    43. // log.warn("A cross-cluster call occurs,name = {}, clusterName = {}, instance = {}", new Object[]{name, clusterName, instances});
    44. // }
    45. // }
    46. Instance maxInstance = instances.stream().max(Comparator.comparing(Instance::getWeight)).get();
    47. Instance minInstance = instances.stream().min(Comparator.comparing(Instance::getWeight)).get();
    48. int count2 = cout.incrementAndGet();
    49. // 数量加1
    50. // 取余
    51. int mod = count2 % 5;
    52. if ((mod == 0)) {
    53. log.debug("count={},mod={},使用min",count2,mod);
    54. return new NacosServer(minInstance);
    55. }else {
    56. log.debug("count={},mod={},使用max",count2,mod);
    57. return new NacosServer(maxInstance);
    58. }
    59. }
    60. @Override
    61. public void initWithNiwsConfig(IClientConfig iClientConfig) {
    62. }
    63. }

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

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

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

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

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

    7.饥饿加载

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

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

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

    1. #ribbon.eager-load.enabled=true
    2. #开启ribbon饥饿加载
    3. #ribbon.eager-load.clients=nacos-a
    4. #配置order-service使用ribbon饥饿加载,多个使用逗号分隔

    8.内核原理

    代码详情springcloud: springcloud

  • 相关阅读:
    SpringMVC的请求处理流程及核心组件
    面试:ArrayList和LinkedList
    【虚拟机】VMWare的NAT静态IP设置
    笔记 | 算法时间复杂度T(n)的计算方法
    华为python面试题目
    厦门大学《信号与系统》考试大纲
    uni-app简介、条件编译、App端Nvue开发、HTML5+、开发环境搭建、自定义组件、配置平台环境、uniCloud云开发平台
    Mixlab 创造力团队的中秋祝福
    02-2解析JsonPath
    TinyOs操作系统---第2章 任务间共享资源保护
  • 原文地址:https://blog.csdn.net/qq_52963857/article/details/133012727