Nginx和Ribbon实现负载均衡的区别

网上有很多写的很好的文章,这里参考他人的文章给出自己的理解。

首先给出结论,有两种说法,是基于不同角度来说的:

1、Nginx是服务端的负载均衡,Ribbon是客户端的负载均衡

2、Nginx是集中式的负载均衡,Ribbon是消费者内部线程实现的负载均衡

对于nginx服务器,所有请求到达nginx服务器后,由nginx服务器进行请求路由的分发,实现负载均衡。

对于Ribbon,是是由客户端主动拉取注册中心的服务列表,然后通过负载均衡算法选取一个可用服务实例(其中通过自旋锁的cas来保证服务不被多个线程重复获取)。

下面是Ribbon的负载均衡服务器选择源码(来源:https://blog.csdn.net/mmmmhello/article/details/112370827):

    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            log.warn("no load balancer");
            return null;
        } else {
            Server server = null;
            int count = 0;

            while(true) {
                if (server == null && count++ < 10) {
                    List reachableServers = lb.getReachableServers();
                    List allServers = lb.getAllServers();
                    int upCount = reachableServers.size();
                    int serverCount = allServers.size();
                    if (upCount != 0 && serverCount != 0) {
                        int nextServerIndex = this.incrementAndGetModulo(serverCount);
                        server = (Server)allServers.get(nextServerIndex);
                        if (server == null) {
                            Thread.yield();
                        } else {
                            if (server.isAlive() && server.isReadyToServe()) {
                                return server;
                            }

                            server = null;
                        }
                        continue;
                    }

                    log.warn("No up servers available from load balancer: " + lb);
                    return null;
                }

                if (count >= 10) {
                    log.warn("No available alive servers after 10 tries from load balancer: " + lb);
                }

                return server;
            }
        }
    }


    private int incrementAndGetModulo(int modulo) {
        int current;
        int next;
        do {
            current = this.nextServerCyclicCounter.get();
            next = (current + 1) % modulo;
            //while 自旋操作
        } while(!this.nextServerCyclicCounter.compareAndSet(current, next));

        return next;
    }

举例说明:

用户下单,假设存在两个模块订单模块和商品模块,两个模块均部署了多个服务用于实现负载均衡,并注册在同一个注册中心。用户发送下单请求后,请求先到达nginx,由nginx进行负载均衡将请求转发给订单服务,订单服务处理业务后,需要调用商品服务扣减库存,内部服务一般使用rpc通信,订单服务调用商品服务扣减库存的时候,通过Ribbon先从注册中心获取所有商品服务,然后通过负载均衡算法选取一个可用服务进行调用,过程结束,这个过程是发生在订单服务内的。

综合上面的例子

一、为什么说Nginx是服务端的负载均衡,Ribbon是客户端的负载均衡呢?

1.用户发送请求到nginx,nginx是服务端。

2.Ribbon是微服务之间通信的负载均衡,订单服务调用商品服务时,订单服务就是客户端,商品服务就是服务端。

二、为什么说Nginx是集中式的负载均衡,Ribbon是消费者内部线程实现的负载均衡呢?

1.nginx是所有请求都会通过nginx进行分发,所以是集中式的负载均衡。

2.订单服务在调用商品服务时,在订单服务内部通过Ribbon的负载均衡算法选出商品服务后进行调用,所以是消费者内部线程实现的负载均衡。

你可能感兴趣的:(Java,java,nginx,ribbon,负载均衡)