在视频聊天开发过程中,负载均衡如何设计与实现?

前言

在视频聊天开发进行服务器部署时,为了避免单点故障,通常将服务采用集群化部署,那么用户应该调用视频聊天开发的哪个服务提供者实例呢?这就涉及到服务的负载均衡(load balance)。一般情况下,负载均衡策略需要将请求均匀分配到各个服务节点,避免出现请求集中在视频聊天开发的某一点上。有时会考虑节点权重,会话粘连等需求。

在这里插入图片描述
按照执行负载均衡策略的角色可分为视频聊天开发的客户端或服务端负载均衡,但无论哪种方式,其适用的负载均衡策略是相通的,常见的几种负载均衡策略如下:

  • 随机
  • 轮询
  • 最小活跃数
  • 一致性哈希

每种策略都有其适用的场景,下面依次介绍

1. 随机

顾名思义,随机策略会从视频聊天开发服务列表中随机选择一个节点进行服务调用,简单的实现如下所示

private Node select(List<Node> servers){

    Random r = new Random();

    int serverSize = servers.size();

    return servers.get(r.nextInt(serverSize));

}

若视频聊天开发的每个节点权重不一样(例如某个节点配置较好,则权重较大,预期承担更多的请求),则需要按照概率进行随机,使得权重更高的节点有更高的概率被随机到

视频聊天开发中的权重既可以是预先静态配置,也可以根据系统运行动态变化,例如节点刚启动时有预热阶段,一开始权重可以很小,随着时间慢慢增加到预定义权重

下面是一段按权重随机的实现代码:

private Node select(List<Node> servers){

    // 计算所有节点权重和

  int totalWeight = calTotalWeight(servers);



    // 随机数,范围:[0,totalWeight)

  int offset = new Random().nextInt(totalWeight);



    for (int i = 0;i<servers.size();i++){

        totalWeight -= servers.get(i).weight;

        if(totalWeight < 0){

            return servers.get(i);

        }

    }

    return null;

}

2. 轮询

轮询策略为依次遍历节点列表,选择请求调用的服务节点。不同于视频聊天开发应用的随机策略,轮询策略会使得就算在请求量小的情况下,每个节点也能均匀地获得请求。
同样,若视频聊天开发的节点间权重不同,某些节点理应承担更多的请求,因此在轮询时需要考虑权重因素。带权重的轮询一般分为普通权重轮询,以及平滑权重轮询。

2.1 普通权重轮询

该算法在视频聊天开发中比较简单实现,会在短时间内请求某个节点符合其权重占比的次数,再转移到下个节点继续请求。

例如权重分别为1,2,3的3该节点A,B,C,会先请求A一次,再请求B两次,再请求C三次
以上操作确实将请求按照节点的权重进行了分配,但会让视频聊天开发在短时间内只请求一个节点,导致该节点压力过大,增大宕机风险,而其他节点闲置,资源没有有效利用。下面的平滑权重轮询能有效缓解该问题

2.2 平滑权重轮询

所谓平滑, 即在一定的时间内, 不仅视频聊天开发的服务器被选择的次数分布和权重一致,满足权重要求,且调度算法还能比较均匀的选择节点分配请求。

先介绍该算法的实现,可能有点绕,后面会举例子详细说明,并简单证明其正确性

  // 所有节点原始权重总和

private int totalWeight;

  // 所有节点原始权重

private int[] nodeOriginWeight;

  // 所有节点当前权重

private int[] nodeCurWeights;

totalWeight:保存所有节点的权重和,该值在后续流程中保持不变
nodeOriginWeight:保持每个节点的原始权重,在后续流程中也保持不变
nodeCurWeights:保存每个节点的当前权重,该数组在后续每次计算请求应该分配到哪个节点时都会发生变化,初始化为每个节点的权重

private Node select(List<Node> servers){

    int maxIndex = 0;

    int maxCurWeight = servers.get(0).weight;

    

    // 找出当前权重最大的节点

  for (int i = 1;i<nodeCurWeights.length;i++){

        if(maxCurWeight < nodeCurWeights[i]){

            maxCurWeight = i;

            maxCurWeight = nodeCurWeights[i];

        }

    }

    

    // 将当前权重最大的节点的的值减去totalWeight

  nodeCurWeights[maxIndex] -= totalWeight;

    

    // 将每个当前权重加上每个节点的原始权重

  for (int i = 0;i<servers.size();i++){

        nodeCurWeights[i] += nodeOriginWeight[i];

    }

    

    // 返回选中的节点

  return servers.get(maxIndex);

}

每次选择节点,都会执行以下3步

在视频聊天开发时选出当前权重中,值最大节点a
将a的当前权重值减去totalWeight
将每个当前权重加上每个节点的原始权重

该算法比较抽象,为什么它能在视频聊天开发时做到既满足权重要求,又可以穿插其他节点呢?
可以这么理解,该算法每次会选出最大当前权重的节点,并减去所有节点权重总和
因此,若视频聊天开发中某个节点增长越快,则越有概率被选中,而增长的速度和权重大小成正比,因此节点权重越大,越有概率被选中。相反或节点权重越小,增长成为最大当前权重节点的速度越慢,被选中的概率较低,从而达到按权重分配请求的效果

在视频聊天开发时,当每个节点被选中后,减去的值都相等,由于减去了一个较大的值(所有节点原始权重总和),使得该节点在下几次请求中,被选中的概率较低,因为恢复成为最大值需要时间。从而达到平滑的效果

3. 最小活跃数

活跃数指一个节点正在处理的请求个数

最小活跃数策略为,视频聊天开发会监控每个节点当前的活跃请求数,每次将请求分配到活跃数最小的节点。
其基于的原理是:活跃请求数小的节点,其负载也可能小。一方面避免给活跃数已经很大的节点增大负担,一方面让活跃数最小的节点增加负载

那怎么知道每个节点的活跃数呢?可以在每个请求开始前给该节点的计数加1,请求结束将该节点的计数减一。若为视频聊天开发客户端负载均衡,则这里只会记录当前客户端发起的请求。若为视频聊天开发服务端负载均衡,可以记录到所有请求数,使得最小活跃数更为精确

该策略可配合随机及轮询使用,比如当出现多个节点的最小活跃数相同时,可以从这些相同的节点随机取一个,总体实现如下:

 // 记录每个节点的活跃数

private Map<Node,Integer> activeCount;



private Node select(List<Node> servers){

    // 记录拥有最小活跃数节点的下标,因为可能多个最小值相同,这里使用数组

    int[] minIndexs = new int[servers.size()];

    // 活跃数等于最小活跃数的节点个数

    int nodeCount = 0;

    int minActiveCount = Integer.MAX_VALUE;



    for (int i = 0;i<servers.size();i++){

        int curCount = activeCount.get(servers.get(i));

        // 发现新的最小值

        if(curCount < minActiveCount){

            minActiveCount = curCount;

            nodeCount = 0;

            minIndexs[nodeCount++] = i;

        // 和之前的最小值相同,加入minIndexes

        } else if(curCount == minActiveCount){

            minIndexs[nodeCount++] = i;

        }

    }



    // 最小值只有一个,就是他!

    if(nodeCount == 1){

        return servers.get(minIndexs[0]);

    }

    

    // 多个节点活跃数相同,且都等于最小值,那么随机选一个

    return servers.get(minIndexes[new Random().nextInt(minIndexs.length)]);

}

和其类似的还有最小响应时间策略,监控每个节点中对每个请求的响应时间,每次将请求分配到平均响应时间最小的节点,这里的隐含逻辑是:平均响应时间小的节点,负载也可能小

4. 一致性哈希

一致性哈希算法更多用于视频聊天开发中数据,缓存存储时的路由策略。因为其需要考虑增加删除节点后的数据的失效范围,及数据迁移成本。但一般的视频聊天开发服务器集群请求调用都是无状态,每次是否请求到同一节点关系不大,都能正常执行业务并返回响应。在某些情况下可能需要,例如会话保持需求。

一般情况下哈希是不一致的,这里的不一致指当节点数量发生变化后,请求很可能不会分配到原先的节点,这在某些场景下是难以接受的,例如视频聊天开发的文件存储系统,相当于每次增加节点,都需要将所有节点的所有文件重新分配,以免出现文件找不到的情况。

一致性哈希算法需要保持以下特性:

单调性:若已经有一些请求已经分配到一些节点上,此时新增加了一个节点,需要保证这些请求需要被分配到原有节点或新增节点上。该条性质使得一致性哈希区别于其他分配策略。

平衡性:尽量保证每个节点处理请求个数均匀。体现在实现上则为哈希环中每个节点距离尽量相等。若计算哈希值比较集中,考虑换均匀性更好的哈希函数

总结

本文介绍了在视频聊天开发中几种常见的负载均衡策略,这些策略实现方式不同,但从不同的角度思考如何分配请求,使得负载能够均衡的问题。大家也可以针对具体业务构想自己的负载均衡策略。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值