Ribbon总结

206 阅读3分钟

首先看下Ribbon的组成

创建二个SpringBoot项目,pom.xml配置文件如下:

 <dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>tk.mybatis</groupId>
        <artifactId>mapper-spring-boot-starter</artifactId>
        <version>2.1.5</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.38</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.12</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Greenwich.SR1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>0.9.0.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

然后注入RestTemplate就可以使用Ribbon,怎么使用这里就不说了,Ribbon是使用客户端的负载均衡规则的,Ribbon内置的负载均衡规则有下面几种

Ribbon默认使用轮询的规则,但是如果我们想其它的路由规则怎么办?? 我们可以创建一个类

 @Configuration
 //只针对一个微服务配置,name是服务名称
//@RibbonClient(name = "content-center",configuration = RibbonConfig.class)
//针对所有微服务配置
@RibbonClients(defaultConfiguration = RibbonConfig.class)
 public class ContentRibbonConfig {

}

然后编写RibbonConfig.class类,但是切记,这个类一定要在SpringBoot启动类之外,这里涉及到Spring的父子上下文,如果写在启动类里面,那么就会被重复扫描,因为Ribbon也有一个自己的上下文。如果被重复扫描会有意想不到的问题。

但是这里有一个坑,如果你配置的路由规则是随机的,但是你只起了一个实例,那么就会出现No instances available for content-center] with root cause这样的异常

以上是基于Java代码配置,当然也可以通过配置文件配置:

、在使用Nacos时候还可以基于权重来进行负载均衡

权重值为0,1,权重值越大被选中的概率越高,所以在性能较低的机器我们可以设置为0,性能高的就设置为1.但是Ribbon内置的是没有基于权重的负载均衡算法的,所以我们要自己写

package com.coco.config;

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;

/**
 * Ribbon基于Nacos权重实现负载均衡,在Nacos的管理界面我们在
 * 服务管理->服务列表->(选择某一个服务)详情->集群配置->编辑->权重
 * 权重的值只有[0,1],值为 1 被选中的概率越大,所以在某些性能不好的机器上就可以设置为 0
 * 但是这个类需要配置到Ribbon,可以使用Java代码或者使用配置文件,可以参考 Ribbon自定义负载均衡
 */
@Slf4j
public class NacosWeightRule extends AbstractLoadBalancerRule {

    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;

@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
       //读取配置文件并初始化,不实现
}

@Override
public Server choose(Object key) {
    try{
        BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer();
        //想要请求的微服务的名称
        String name = loadBalancer.getName();
        //拿到服务发现的相关API
        NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
        //nacos Client自动通过基于权重的负载均衡算法,给我们选择一个实例
        Instance instance = namingService.selectOneHealthyInstance(name);
        log.info("选择的实例是:" + instance);
        return new NacosServer(instance);
    }catch (Exception e){
        e.printStackTrace();
        return  null;
    }
}
}

然后使用Java代码或者配置上这个类,具体配置就在上面的自定义配置