Java接口方法内调用不同方法实现负载均衡方式

业务场景:现有个接口,非方法级负载均衡,而是在接口内部实在,实现方法均摊。具体代码如下。

这里使用平均数来生成判断走那个逻辑,可能会出现均衡度不一样情况,比如高并发调用一千次,可能第一个走600,第二第三各走200。这样就无法实现比较均衡的平均分配。 

100线程循环1000次,想当于调用10w次 

具体代码:

/**
     * @program: 工具箱
     * @description
     * 使用同步锁和洗牌算法 展示了如何在处理四个数字(a、b、c、d)的情况下实现均衡的累加。
     * <p>
     * 在 `saveOne()` 方法中,通过循环执行 `numRequests` 次请求。在每次循环中,我们首先使用 `getRandomIndex()` 方法获取一个随机索引,该方法会对索引进行随机打乱以实现均衡分布。
     * <p>
     * 然后,使用 `switch` 语句根据随机索引对 `a`、`b`、`c` 和 `d` 进行累加操作。
     * <p>
     * 接下来,我们输出当前的执行次数 `total`,以及每个数字的计数值 `a`、`b`、`c` 和 `d`。
     * <p>
     * 在 `getRandomIndex()` 方法中,我们将索引数组 `{0, 1, 2, 3}` 传递给 `shuffleArray()` 方法进行随机打乱,并返回打乱后的数组中的第一个索引。
     * <p>
     * `shuffleArray()` 方法使用 Fisher-Yates 洗牌算法来打乱数组元素的顺序,确保每个索引以均衡的方式出现。
     * <p>
     * 在 `main()` 方法中,我们创建 `TestController` 实例,并启动 30 个线程,每个线程执行 `saveOne(100)` 方法来模拟并发执行。
     * <p>
     * 通过以上代码,您可以观察到每个数字(a、b、c、d)的计数值在不同线程间进行均衡的累加,并输出执行次数和各数字的计数情况。这样可以实现较为均衡的处理。请注意,由于线程调度和竞争条件的存在,无法保证每个数字的计数完全相等,但整体上可以达到较好的均衡效果。
     */
    private int total = 0;
    private int a = 0;
    private int b = 0;
    private int c = 0;
    private int d = 0;

    public void saveOne(int numRequests) {
        for (int i = 0; i < numRequests; i++) {
            int randomIndex = getRandomIndex();
            switch (randomIndex) {
                case 0:
                    a++;
                    break;
                case 1:
                    b++;
                    break;
                case 2:
                    c++;
                    break;
                case 3:
                    d++;
                    break;
            }
            total++;
            System.out.println("执行了第->" + total);
            System.out.println("a: " + a);
            System.out.println("b: " + b);
            System.out.println("c: " + c);
            System.out.println("d: " + d);
        }
    }

    /**
     * Fisher–Yates shuffle 洗牌算法
     * 这里的{0, 1, 2, 3}和上面case 0 1 2 4 一一对应.
     */
    private int getRandomIndex() {
        int[] indices = {0, 1, 2, 3};
        shuffleArray(indices);
        return indices[0];
    }

    /**
     * Fisher–Yates shuffle 洗牌算法
     * @param array
     */
    private void shuffleArray(int[] array) {
        Random random = new Random();
        for (int i = array.length - 1; i > 0; i--) {
            int index = random.nextInt(i + 1);
            int temp = array[index];
            array[index] = array[i];
            array[i] = temp;
        }
    }

    public static void main(String[] args) {
        TestController example = new TestController();
        for (int i = 0; i < 30; i++) {
            Thread thread = new Thread(() -> example.saveOne(100));
            thread.start();
        }
    }

    private final Object lock = new Object(); // 添加同步锁

    @ApiOperation(value = "负载均衡测试", notes = "负载均衡测试")
    @GetMapping("/oneMQ1")
    public void oneMQ1() {
        int randomIndex = getRandomIndex();
        synchronized (lock) {
            total++;
            switch (randomIndex) {
                case 0:
                    a++;
                    break;
                case 1:
                    b++;
                    break;
                case 2:
                    c++;
                    break;
                case 3:
                    d++;
                    break;
            }
        }
        System.out.println("执行了第->" + total);
        System.out.println("a: " + a);
        System.out.println("b: " + b);
        System.out.println("c: " + c);
        System.out.println("d: " + d);
    }

使用压测工具调用执行结果:

执行了第->100000
a: 25234
b: 25276
c: 24769
d: 24721 

可以看出非常均匀的进行部分运算了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值