Analysis of Weighted Polling Method for Load Balancing in PHP

  • 2021-11-01 02:41:40
  • OfStack

This paper describes the weighted polling method of PHP to realize load balancing. Share it for your reference, as follows:

1. What are the load balancing algorithms?

Polling: The requests are distributed sequentially and alternately to the back-end servers. It treats every one back-end server in a balanced manner, regardless of the actual number of connections to the servers and the current system load. Random method: Through the random algorithm of the system, one server is randomly selected to access according to the list size value of the back-end server. Source address hashing method: According to the IP address of the client, a numerical value is calculated by hashing function, and the size of the server list is modularized with this numerical value, and the result is the serial number of the server that the customer service end wants to access. The source address hashing method is used for load balancing. When the backend server list is unchanged, the client with the same address 1IP will be mapped to the same backend server for access every time. Weighted polling method: Different back-end servers may have different machine configurations and current system loads, so their stress resistance is also different. Configure higher weight for machines with high configuration and low load, so that they can handle more requests; However, the machines with low configuration and high load are assigned lower weights to reduce their system load. Weighted polling can deal with this problem well, and distribute requests to the back end in order and according to weights. Weighted random method: Like weighted polling method, weighted random method also distributes different weights according to the configuration of back-end machines and the load of the system. The difference is that it requests back-end servers randomly according to weight, not sequentially. Minimum connection number method: Because the backend servers are configured differently, The minimum connection number method dynamically selects one server with the least backlog connection number to process the current request according to the current connection situation of the back-end server, so as to improve the utilization efficiency of the back-end service as much as possible and distribute the responsibility to every one server reasonably.

2. How to implement weighted polling with PHP?

Implementation ideas:

By passing in different users id, they are assigned different hosts.

First, you need an array to receive user id.

Secondly, you need an array of hosts, which have different weights. The weight here can be considered as follows:

Assuming that there are three hosts of abc with weights of 3, 1 and 1 respectively, the proportion of a is 0.6, and the proportion of b and c is 0.2 each.

Directly traverse the array of hosts. If there are 100 users, when a, the proportion of a is 0.6, 60 people will be randomly selected from the user array and distributed to a;; When it is b's turn, the proportion of b is 0.2, and 20 people are randomly selected from the user array; Similarly, c has 20 people, thus completing the forwarding of 100 requests.

However, the real scene is not a fixed batch of users, but continuous user requests. Because the forwarding is very fast, when there are very few new users, they will be taken from the user queue every time, and then they will be taken from the user queue immediately after forwarding. It is very likely that only two requests will be taken at a time, resulting in the situation that all requests are given to a, and b and c1 are not available. At this time, we can consider fetching data from the user queue according to different strategies. Assuming that 5ms has processed one forwarding before, You now define two policies, If there are 100 users in the user queue, they will be taken out and forwarded according to the proportion of hosts. If there are less than 100 users in the user queue, but the difference between the current time and the last value time is 10ms, they will be taken out and forwarded, so that 5ms can be accumulated, and there will be one more user request in the queue in this 5ms, so that all requests will not be distributed to one machine.

Code:


<?php
// php Weighted polling for load balancing ( WRR ) 
class WRR {
  //  Each fetch 100 People 
  const num = 100;
  //  Last value time, second timestamp 
  public $last_time;
  //  Weight  machine=>weight
  public $machines = array(
    'a' => 3, // 0.6
    'b' => 1, // 0.2
    'c' => 1 // 0.2
  );
  //  Proportion 
  public $proportion = array();
  //  User queue 
  public static $user_ids = array();
  public function __construct() {
    //  Proportion of each machine 
    $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() {
    //  Number of users 
    $cnt = count(self::$user_ids);
    $a_num = 0;
    $b_num = 0;
    $c_num = 0;
    if ($cnt >= self::num) { //  Queue exceeds 100 People 
      $a_num = round(self::num * $this->proportion['a']);
      $b_num = round(self::num * $this->proportion['b']);
      $c_num = $cnt - $a_num - $b_num;
    } else { //  Insufficient Queue 100 People 
      $last_time = $this->last_time; //  Last Access Time 
      while (true) {
        $current_time = $this->getMillisecond();
        if (($current_time - $last_time) >= 10) { //  Current time and 1 The second value time exceeds 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();  //  Update access time 
          break;
        }
      }
    }
    $a = array_splice(self::$user_ids, 0, $a_num);
    $b = array_splice(self::$user_ids, 0, $b_num);
    $c = array_splice(self::$user_ids, 0, $c_num);
    return array(
      'a' => $a,
      'b' => $b,
      'c' => $c
    );
  }
  //  Get a millisecond timestamp 
  public function getMillisecond() {
    list($t1, $t2) = explode(" ", microtime());
    return (float)sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000);
  }
}
//  Test 
$wrr = new WRR();
for ($i = 0; $i < 3; $i++) {//  Simulate continuous user requests 
  $random = rand(10, 120);
  $user_ids = range(1, $random);
  WRR::$user_ids = $user_ids;
  $users = $wrr->getUsers();
  print_r($users);
}

The real algorithm is much more complicated than this. It needs to consider one point, that is, the users who have been here should keep the original assigned machine unless the original machine hangs up. The reason for this is caching. Many memory-based caches are based on the user level, so keeping the same users on the same machine helps improve performance.

For more readers interested in PHP related contents, please check the special topics of this site: "PHP Data Structure and Algorithm Tutorial", "php Programming Algorithm Summary", "php String (string) Usage Summary", "PHP Array (Array) Operation Skills Complete Book", "PHP Common Traversal Algorithms and Skills Summary" and "PHP Mathematical Operation Skills Summary"

I hope this article is helpful to everyone's PHP programming.


Related articles: