Netflix Ribbon - 客户端负载均衡

144 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。


netflix ribbon 负载均衡 - 直联方式

启动服务实例

用8763和8764两个端口号启动两个服务实例。

服务的客户端(基于ribbon)

<dependency>
    <groupId>com.netflix.ribbon</groupId>
    <artifactId>ribbon</artifactId>
</dependency>

<dependency>
    <groupId>com.netflix.ribbon</groupId>
    <artifactId>ribbon-httpclient</artifactId>
</dependency>
// 服务名称是:eureka-provider-ribbon-p2p.ribbon
ConfigurationManager.getConfigInstance().setProperty("eureka-provider-ribbon-p2p.ribbon" + ".listOfServers", "localhost:7073,localhost:7074");

RestClient namedClient =
        (RestClient) ClientFactory.getNamedClient("eureka-provider-ribbon-p2p");
for (int i = 0; i < 10; i++) {
    try {
        namedClient.executeWithLoadBalancer(HttpRequest.newBuilder().uri("/product").build());
    } catch (Exception e) {
        log.info("nothing");
    }
}

10次请求,均匀分布在了两个服务实例上,每个服务实例承载了5次请求。

ILoadBalancer原生接口以及IRule内置的规则

ILoadBalancer原生的负载均衡器接口

默认使用round robin轮询策略,直接从服务器列表里轮询

RestClient底层就是基于默认的BaseLoadBalancer来选择一个server

ILoadBalancer balancer = new BaseLoadBalancer();

List<Server> serverList = Arrays.asList(8080, 8081).stream().map(port -> new Server(
        "localhost", port)).collect(Collectors.toList());

balancer.addServers(serverList);

for (int i = 0; i < 10; i++) {
    Server server = balancer.chooseServer(null);
    log.info("server : {}", server);
}

自定义负载均衡的规则

ILoadBalancer负载均衡器,底层是基于IRule,负载均衡算法,从服务器list中选择一个server出来

负载均衡器是基于一个IRule接口指定的负载均衡规则,来从服务器列表里获取每次要请求的服务器的。

负载均衡的一些底层API主要是ILoadBalancer和IRule。

ILoadBalancer balancer = new BaseLoadBalancer();

List<Server> serverList = Arrays.asList(8080, 8081).stream().map(port -> new Server(
        "localhost", port)).collect(Collectors.toList());

balancer.addServers(serverList);

class MyRule implements IRule {

    private ILoadBalancer iLoadBalancer;

    @Override
    public Server choose(Object o) {
        List<Server> allServers = iLoadBalancer.getAllServers();
        Server server = allServers.get(0);
        return server;
    }

    @Override
    public void setLoadBalancer(ILoadBalancer iLoadBalancer) {
        this.iLoadBalancer = iLoadBalancer;
    }

    @Override
    public ILoadBalancer getLoadBalancer() {
        return iLoadBalancer;
    }
}

((BaseLoadBalancer) balancer).setRule(new MyRule());

for (int i = 0; i < 10; i++) {
    Server server = balancer.chooseServer(null);
    log.info("server : {}", server);
}

IRule 内置的负载均衡规则

RoundRobinRule:系统内置的默认负载均衡规范,直接round robin轮询,从一堆server list中,不断的轮询选择出来一个server,每个server平摊到的这个请求,基本上是平均的

AvailabilityFilteringRule:这个rule就是会考察服务器的可用性

如果3次连接失败,就会等待30秒后再次访问;如果不断失败,那么等待时间会不断边长

如果某个服务器的并发请求太高了,那么会绕过去,不再访问

WeightedResponseTimeRule:带着权重的,每个服务器可以有权重,权重越高优先访问,如果某个服务器响应时间比较长,那么权重就会降低,减少访问

ZoneAvoidanceRule:根据区域和服气来进行负载均衡,说白了,就是机房的意思

BestAvailableRule:忽略那些连接失败的服务器,然后尽量找并发比较低的服务器来请求

RandomRule:随机找一个服务器

RetryRule:可以重试,就是通过round robin找到的服务器请求失败,可以重新找一个服务器

ribbon主打的就是负载均衡,网络通信,别的一些东西,都是次要,只要是看ribbon提供的各种负载均衡的算法的实现,另外一个是看ribbon + eureka + spring cloud如何整合使用的,看看ribbon源码里面去找比较重要的一些配置的参数