Ribbon

负载均衡的两种方式

  • 服务器端负载均衡
  • 客户端侧负载均衡

实现一个简单的客户端侧负载均衡

  1. 使用DiscoveryClient的getInstances()方法,传入需要调用的服务名称,获取服务列表
  2. 根据服务列表获取url列表
  3. 随机一个url,通过RestTemplate调用服务
List instances = discoveryClient.getInstances("user-center");
List urlList = instances.stream().map(serviceInstance -> 
                serviceInstance.getUri().toString() + "/xxx/xxx").collect(Collectors.toList());
int i = ThreadLocalRandom.current().nextInt(urlList.size());

使用Ribbon实现负载均衡

  1. 不需要添加依赖,spring-cloud-starter-alibaba-nacos-discovery已经包含依赖
  2. 添加注解
@Bean
@LoadBalanced
public RestTemplate restTemplate(RestTemplateBuilder builder){
    return builder.build();
}
  1. 不需要添加配置

Ribbon组成

Ribbon_第1张图片
Ribbon组成.png

Ribbon内置负载均衡规则

Ribbon_第2张图片
Ribbon负载均衡规则.png

Ribbon配置方式

细粒度配置

Ribbon_第3张图片
Ribbon支持的配置.png
#服务名称
user-center:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
    NFLoadBalancerPingClassName: com.netflix.loadbalancer.PingUrl

配置饿加载

ribbon:
  eager-load:
    enabled: true
    clients: user-center,xxx,xxx

扩展Ribbon-支持Nacos权重

  1. 创建NacosWeightedRule类
package com.istimeless.contentcenter.configuration;

import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties;
import org.springframework.cloud.alibaba.nacos.ribbon.NacosServer;

/**
 * @author lijiayin
 */
@Slf4j
public class NacosWeightedRule extends AbstractLoadBalancerRule {
    
    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;
    
    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {
        //读取配置文件,并初始化
    }

    @Override
    public Server choose(Object o) {
        try {
            BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer();
            //想要请求的微服务名称
            String name = loadBalancer.getName();
            //实现负载均衡算法
            //拿到服务发现相关API
            NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
            //nacos client自动通过基于权重的负载均衡算法,给我们选择一个实例。
            Instance instance = namingService.selectOneHealthyInstance(name);
            
            log.info("选择的实例是:port = {}, instance = {}", instance.getPort(), instance);
            return new NacosServer(instance);
        } catch (NacosException e) {
            log.error("选择实例异常:{}", e.getMessage(), e);
            return null;
        }
    }
}
  1. 创建RibbonConfiguration类
package com.istimeless.ribbonconfiguration;

import com.istimeless.contentcenter.configuration.NacosWeightedRule;
import com.netflix.loadbalancer.IRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author lijiayin
 */
@Configuration
public class RibbonConfiguration {
    
    @Bean
    public IRule ribbonRule() {
        return new NacosWeightedRule();
    }
}

特别注意:RibbonConfiguration要建在启动类扫描不到的地方,如图所示:

Ribbon_第4张图片
目录结构.png

  1. 创建UserCenterRibbonConfiguration类,实现全局配置
package com.istimeless.contentcenter.configuration;

import com.istimeless.ribbonconfiguration.RibbonConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.context.annotation.Configuration;

/**
 * @author lijiayin
 */
@Configuration
@RibbonClients(defaultConfiguration = RibbonConfiguration.class)
public class UserCenterRibbonConfiguration {
}

你可能感兴趣的:(Ribbon)