dubbo负载均衡。

1.搭建zookeeper集群,搭建过程参考网上资料(地址为192.168.200.141:2182,192.168.200.141:2183,192.168.200.141:2184)。

2.搭建dubbo服务生产者和消费者项目工程,github地址:https://github.com/kickTec/dubboDemo,详细过程请参考https://www.cnblogs.com/hd3013779515/p/6895998.html。

dubbo服务提供方项目工程结构:

dubbo负载均衡。_第1张图片

dubbo服务提供方spring配置:

dubbo负载均衡。_第2张图片

服务提供方通过main方法启动。

package com.kenick.main;

import com.kenick.service.HelloService;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        // spring环境初始化,同时通过spring将服务注册到zookeeper上
        System.out.println("spring环境初始化!");
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"dubbo-provider-dev.xml"});
        context.start();

        try {
            // 测试服务注入到spring中是否成功
            HelloService helloService = context.getBean("helloService", HelloService.class);
            String ret = helloService.hello("kenick-provider");
            System.out.println(ret);

            System.in.read(); // 程序等待输入卡住
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

服务消费方项目工程目录:

dubbo负载均衡。_第3张图片

服务消费方spring配置文件:

dubbo负载均衡。_第4张图片

服务消费方配置代码:

package com.kenick.main;

import com.kenick.service.HelloService;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        try {
            // spring环境初始化
            System.out.println("开始spring环境初始化!");
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"dubbo-consumer-dev.xml"});
            context.start();

            int provider1Sum = 0;
            int provider2Sum = 0;
            for(int i=0;i<2000;i++){
                // 开始通过spring和dubbo获取远程服务实例
                HelloService helloService = context.getBean("helloService", HelloService.class);

                // 调用提供的服务hello
                String ret = helloService.hello("kenick-consumer");
                System.out.println(ret);

                // 统计调用次数
                if(ret.contains("provider1")){
                    provider1Sum += 1;
                }else if(ret.contains("provider2")){
                    provider2Sum += 1;
                }
                System.out.println("provider1Sum:"+provider1Sum+","+provider1Sum*1.0/(provider1Sum+provider2Sum));
                System.out.println("provider2Sum:"+provider2Sum+","+provider2Sum*1.0/(provider1Sum+provider2Sum));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3.dubbo默认随机负载均衡-random

服务提供方配置

服务消费方调用2000次,分配为999:1001,基本为1:1。

4.dubbo负载均衡-roundrobin

两个服务提供方都配置为roundrobin,权重都为100,如下:

服务消费方调用2000次,其中提供方1、提供方2为1000:1000,比较平均。

将服务提供者2的权重调整到300(服务提供者1权重:100),服务提供2:服务提供1为1724:276,约等于6.25:1,权重起了一点作用,但比例不怎么匹配。

5.dubbo负载均衡-leastactive

最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差;使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。

服务消费者配置(timeout超时,actives:Activity最大的并发数,如果超过这个并发数,在invoke时将会等待)。

同时配置服务提供者1的服务sleep(模拟网络不好,减少同一时间内的调用次数)。

dubbo负载均衡。_第5张图片

在服务消费方这边需要使用多线程测试调用情况,代码如下:

package com.kenick.main;

import com.kenick.service.HelloService;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.concurrent.locks.ReentrantLock;

public class Main1 {
    public static void main(String[] args) {
        try {
            // spring环境初始化
            System.out.println("开始spring环境初始化!");
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"dubbo-consumer-dev.xml"});
            context.start();

            // 启动两个线程调用服务
            ServiceInvokeRunnable serviceInvokeRunnable1 = new ServiceInvokeRunnable(context);
            ServiceInvokeRunnable serviceInvokeRunnable2 = new ServiceInvokeRunnable(context);
            Thread thread1 = new Thread(serviceInvokeRunnable1, "thread1");
            Thread thread2 = new Thread(serviceInvokeRunnable2, "thread2");
            thread1.start();
            thread2.start();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    static class ServiceInvokeRunnable implements Runnable{
        private static Integer invokeTimes = 2000; // 总调用次数
        private ClassPathXmlApplicationContext context; // spring上下文
        private static ReentrantLock locker = new ReentrantLock(); // 锁住调用次数
        private Integer provider1Sum = 0; // 调用服务提供者1次数
        private Integer provider2Sum = 0;// 调用服务提供者2次数

        public ServiceInvokeRunnable(ClassPathXmlApplicationContext context){
            this.context = context;
        }

        public void run() {
            // 多线程处理调用次数
            while(invokeTimes >0){
                locker.lock();
                try {
                    if(invokeTimes>0){
                        invokeTimes--;
                    }else{
                        break;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }finally {
                    locker.unlock();
                }

                // 调用提供的服务hello
                String threadName = Thread.currentThread().getName();
                HelloService helloService = context.getBean("helloService", HelloService.class);
                String ret = helloService.hello("kenick-consumer");

                // 统计调用次数
                if(ret.contains("provider1")){
                    provider1Sum++;
                }else if(ret.contains("provider2")){
                    provider2Sum++;
                }
                System.out.println(threadName+":"+"provider1Sum:"+provider1Sum+","+provider1Sum*1.0/(provider1Sum+provider2Sum));
                System.out.println(threadName+":"+"provider2Sum:"+provider2Sum+","+provider2Sum*1.0/(provider1Sum+provider2Sum));
            }
        }
    }
}

服务消费方调用2000次,线程2调用服务提供方1 153次,服务提供方2 868次;线程1调用服务提供方1 160次,线程2调用服务提供方819次;两个线程调用服务提供方1总次数为313次,调用服务提供方2总次数为1687次,负载均衡策略起到了相应的作用。

6.ConsistentHash LoadBalance 一致性Hash

相同参数的请求总是发到同一提供者;当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。

你可能感兴趣的:(java)