您的当前位置:首页正文

初识Spring Cloud--Ribbon客户端负载均衡

2024-11-08 来源:个人技术集锦

首先来看一下Ribbon的作用:

ribbon 是一个客户端负载均衡器,主要是实现类似于 nginx的负载均衡的功能。

SpringCloud提供了7种负载均衡的算法,如下表所示,ribbon 默认使用轮询算法(RoundRobinRule)来实现负载均衡,

策略名策略声明策略描述实现说明
BestAvailableRulepublic class BestAvailableRule extends ClientConfigEnabledRoundRobinRule    选择一个最小的并发请求的server逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server
AvailabilityFilteringRulepublic class AvailabilityFilteringRule extends PredicateBasedRule    过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值)    使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态
WeightedResponseTimeRulepublic class WeightedResponseTimeRule extends RoundRobinRule    根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低。    一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetim
RetryRulepublic class RetryRule extends AbstractLoadBalancerRule    对选定的负载均衡策略机上重试机制。    在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server
RoundRobinRulepublic class RoundRobinRule extends AbstractLoadBalancerRule    roundRobin方式轮询选择server    轮询index,选择index对应位置的server
RandomRulepublic class RandomRule extends AbstractLoadBalancerRule    随机选择一个server    在index上随机,选择index对应位置的server
ZoneAvoidanceRulepublic class ZoneAvoidanceRule extends PredicateBasedRule    复合判断server所在区域的性能和server的可用性选择server    使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server)

下面我们通过代码来实现Ribbon的负载均衡功能;不同于dubbo的rpc调用,SpringCloud采用的rest方式进行服务调用,创建一个RemoteController类来模拟调用:

@RestController
@RequestMapping("/remote")
public class RemoteController {
    private static final String URL_PREFIX = "http://SERVICE01";
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/getService")
    public Object getRemoteService() {
        return restTemplate.getForObject(URL_PREFIX + "/local/getServiceInfo", Object.class);
    }
}

其中的RestTemplate类需要手动的加载到IOC容器中,在启动类中添加如下的代码:

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }

接着我们创建service01的多个实例:

通过postman模拟请求,分别会调用这四个服务中的一个,并且调用的服务顺序是有序的。

那么如何调用其他的6种负载均衡算法呢?

很简单,我们只要在启动类种添加如下的代码即可:

    @Bean
	public IRule getRule(){
		return new RandomRule();
	}

这时候可能又有一个疑问了,这个负载均衡的算法只能使用SpringCloud提供的7种算法吗?如果想要自己定义一个算法又该如何实现呢?

假如这边有一个比较变态的需求,我只要service06给我提供服务那怎么操作呢?

依然简单,我们可以新建一个配置类:

@Configuration
public class CustomRule {
    @Bean
    public IRule getRule() {
         return new SingleRule();
    }
}

自定义负载均衡算法:

public class SingleRule extends AbstractLoadBalancerRule {
    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        }
        Server server = null;

        while (server == null) {
            if (Thread.interrupted()) {
                return null;
            }
            List<Server> upList = lb.getReachableServers();
            List<Server> allList = lb.getAllServers();

            int serverCount = allList.size();
            if (serverCount == 0) {
                return null;
            }
            server = upList.get(0);
            if (server == null) {
                Thread.yield();
                continue;
            }
            if (server.isAlive()) {
                return (server);
            }
            // Shouldn't actually happen.. but must be transient or a bug.
            server = null;
            Thread.yield();
        }
        return server;
    }

    @Override
    public Server choose(Object o) {
        return choose(getLoadBalancer(), o);
    }

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }
}

 

这里有一点需要注意:

也就是说,这个配置类不能和之前的启动类放到启动类的同一个包下面,不然所有的ribbon客户端都会采用这个自定义的负载均衡算法。

 

至此,一个自定义的负载均衡算法就实现啦,当然实际中估计没有人会这么用,具体的算法还是需要依据不同的业务来确定。

Top