加入收藏 | 设为首页 | 会员中心 | 我要投稿 云计算网_泰州站长网 (http://www.0523zz.com/)- 视觉智能、AI应用、CDN、行业物联网、智能数字人!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

PHP实现负载均衡的加权轮询技巧分析

发布时间:2022-06-30 15:25:29 所属栏目:PHP教程 来源:互联网
导读:本文实例讲述了PHP实现负载均衡的加权轮询方法。分享给大家供大家参考,具体如下: 1. 负载均衡算法有哪些? 轮询法:将请求按顺序轮流地分配到后端服务器上,它均衡地对待后端的每一台服务器,而不关心服务器实际的连接数和当前的系统负载。 随机法:通过系
  本文实例讲述了PHP实现负载均衡的加权轮询方法。分享给大家供大家参考,具体如下:
 
  1. 负载均衡算法有哪些?
 
  轮询法:将请求按顺序轮流地分配到后端服务器上,它均衡地对待后端的每一台服务器,而不关心服务器实际的连接数和当前的系统负载。
 
  随机法:通过系统的随机算法,根据后端服务器的列表大小值来随机选取其中的一台服务器进行访问。
 
  源地址哈希法:根据获取客户端的IP地址,通过哈希函数计算得到一个数值,用该数值对服务器列表的大小进行取模运算,得到的结果便是客服端要访问服务器的序号。采用源地址哈希法进行负载均衡,同一IP地址的客户端,当后端服务器列表不变时,它每次都会映射到同一台后端服务器进行访问。
 
 
  2.如何用PHP实现加权轮询?
 
  实现思路:
 
  通过传入不同的用户id,然后给他们分配不同的主机。
 
  首先,需要一个接收用户id的数组。
 
  其次,需要一个存主机的数组,这些主机有不同的权重,这里的权重可以这么考虑:
 
  假设有abc三台主机,权重分别为3,1,1,那么a的占比为0.6,b和c的占比各为0.2。
 
  直接遍历主机的数组,假如用户来了100个人,到a的时候,a的占比是0.6,就从用户数组里随机取60个人分给a;轮到b时,b的占比是0.2,就从用户数组里随机取20人;同理,c20人,这样就完成了100个请求的转发。
 
  可是真实场景不是固定一批用户,而是持续不断的用户请求,由于转发非常快,当来的新用户非常少时,每次从用户队列中取完、转发后立马去用户队列中取,很有可能每次只取2条,造成请求全部给了a,b和c一直没有的情况。这时候可以考虑按照不同策略从用户队列中取数据。假设以前5ms就处理完一次转发,则现在定义两种策略,如果用户队列中有100个用户时,就取出来,按着主机占比进行转发,如果用户队列中不足100人,但是当前时间和上一次取值时间相差10ms,就取出来进行转发,这样就可以累积5ms,而这5ms里队列中又会多一些用户请求,这样就不会把所有请求都分给一台机器了。
 
  代码:
 
  <?php
  // php实现负载均衡的加权轮询(WRR)
  class WRR {
       // 各机器的占比
      $total = 0;
      foreach ($this->machines as $machine => $weight) {
        $total += $weight;
      }
      $this->proportion['a'] = $this->machines['a'] / $total;
      $this->proportion['b'] = $this->machines['b'] / $total;
      $this->proportion['c'] = $this->machines['c'] / $total;
    }
    public function getUsers() {
      // 用户人数
      $cnt = count(self::$user_ids);
      $a_num = 0;
      $b_num = 0;
      $c_num = 0;
      if ($cnt >= self::num) { // 队列超过100人
        $a_num = round(self::num * $this->proportion['a']);
        $b_num = round(self::num * $this->proportion['b']);
        $c_num = $cnt - $a_num - $b_num;
      } else { // 队列不足100人
        $last_time = $this->last_time; // 上次访问时间
        while (true) {
          $current_time = $this->getMillisecond();
          if (($current_time - $last_time) >= 10) { // 当前时间和上一次取值时间超过10ms
            $a_num = round($cnt * $this->proportion['a']);
            $b_num = round($cnt * $this->proportion['b']);
            $c_num = $cnt - $a_num - $b_num;
            $this->last_time = self::getMillisecond();  // 更新访问时间
            break;
          }
        }
   // 测试
  $wrr = new WRR();
  for ($i = 0; $i < 3; $i++) {// 模拟持续不断的用户请求
    $random = rand(10, 120);
    $user_ids = range(1, $random);
    WRR::$user_ids = $user_ids;
    $users = $wrr->getUsers();
    print_r($users);
  }
  真实的算法比这个复杂多了,它需要考虑一点,就是来过的用户要保持原来分配的机器,除非原来的机器挂了,这样做的原因是缓存,很多基于内存的缓存,都是基于用户级别的,所以相同的用户保持同一台机器,有助于提升性能。

(编辑:云计算网_泰州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读