4 years ago, I published a PHP solution on the blog for choosing the right server from a servers list, based on the available bandwidth configured: Asymmetric Load Balancing Server Solution.
The algorithm can be used in Load Balancing proxy servers, for CDNs as well as for any other needs where a balanced distribution of resources is required;
Recently I am working on a cache plugin written in PHP, developed for any kind of web pages (non CMS) as well as for Wordpress: page, object and database.
You must be wondering why I don’t choose a plugin that is already free?
Because most of them are too complex, and they have long lost their perspective on simplicity, utility and performance!
And when I came to the implementation of a solution for CDN, I remembered the php function published over 2 years ago … but after so long it seems that my brain has advanced more in the optimization segment, the old solution seemed to me “heavy”.. So after less than 5 minutes I realized that the method of choosing a server was still very good, but there was still room for optimization!
So, below is a new version for Asymmetric Load Balancing Server, much faster and even simpler! (2024 Update as Class)
class ByREV_Asym_LB_Server{
public $Server_List = [];
private $Server_LBS = [];
private $Sum_Bandwidth = 0;
private function prepareLBS()
{
// Sort server list in ascending order, based on the bandwidth.
// Mandatory requirement for Load Balanced algorithm to work!
asort($this->Server_List);
$this->Server_LBS = [];
$segment_bandwidth = 0;
foreach ($this->Server_List as $server=>$bandwidth) {
$segment_bandwidth+= $bandwidth;
$this->Server_LBS[$server] = $segment_bandwidth;
}
$this->Sum_Bandwidth = end( $this->Server_LBS );
}
// Preferentially and pseudorandomly choose a server from the list based on a criterion like:
// bandwidth, average latency, computing power, response time, number of requests per minute.
public function getServer()
{
// Choose a server from the list
$rand_bandwidth = mt_rand(1, $this->Sum_Bandwidth);
// Scan list until find one
foreach ($this->Server_LBS as $server=>$bandwidth) {
if ($rand_bandwidth <= $bandwidth)
break;
}
// Returns the data for the chosen server
return $server;
}
public function __construct(Array $Servers=[])
{
$this->Server_List = $Servers;
// prepare server list for Load Balanced algorithm and save for later use.
$this->prepareLBS();
}
}
/* ~~~~~~~~~~~~~~~~~~ Use Case ~~~~~~~~~~~~~~~~~~~~~ */
$srv_cdn = [
'cdn1.cdnserverxyz.com' => 15,
'cdn2.cdnserverxyz.com' => 30,
'cdn3.cdnserverxyz.com' => 120,
'cdn4.cdnserverxyz.com' => 75,
'cdn5.cdnserverxyz.com' => 10,
];
$LBS = new ByREV_Asym_LB_Server($srv_cdn);
echo $LBS;
- class ByREV_Asym_LB_Server{
-
- public $Server_List = [];
- private $Server_LBS = [];
- private $Sum_Bandwidth = 0;
- private function prepareLBS()
- {
- // Sort server list in ascending order, based on the bandwidth.
- // Mandatory requirement for Load Balanced algorithm to work!
- asort($this->Server_List);
- $this->Server_LBS = [];
- $segment_bandwidth = 0;
- foreach ($this->Server_List as $server=>$bandwidth) {
- $segment_bandwidth+= $bandwidth;
- $this->Server_LBS[$server] = $segment_bandwidth;
- }
-
- $this->Sum_Bandwidth = end( $this->Server_LBS );
- }
- // Preferentially and pseudorandomly choose a server from the list based on a criterion like:
- // bandwidth, average latency, computing power, response time, number of requests per minute.
- public function getServer()
- {
- // Choose a server from the list
- $rand_bandwidth = mt_rand(1, $this->Sum_Bandwidth);
-
- // Scan list until find one
- foreach ($this->Server_LBS as $server=>$bandwidth) {
- if ($rand_bandwidth <= $bandwidth)
- break;
- }
- // Returns the data for the chosen server
- return $server;
- }
- public function __construct(Array $Servers=[])
- {
- $this->Server_List = $Servers;
- // prepare server list for Load Balanced algorithm and save for later use.
- $this->prepareLBS();
- }
- }
- /* ~~~~~~~~~~~~~~~~~~ Use Case ~~~~~~~~~~~~~~~~~~~~~ */
- $srv_cdn = [
- 'cdn1.cdnserverxyz.com' => 15,
- 'cdn2.cdnserverxyz.com' => 30,
- 'cdn3.cdnserverxyz.com' => 120,
- 'cdn4.cdnserverxyz.com' => 75,
- 'cdn5.cdnserverxyz.com' => 10,
- ];
- $LBS = new ByREV_Asym_LB_Server($srv_cdn);
- echo $LBS;
class ByREV_Asym_LB_Server{
public $Server_List = [];
private $Server_LBS = [];
private $Sum_Bandwidth = 0;
private function prepareLBS()
{
// Sort server list in ascending order, based on the bandwidth.
// Mandatory requirement for Load Balanced algorithm to work!
asort($this->Server_List);
$this->Server_LBS = [];
$segment_bandwidth = 0;
foreach ($this->Server_List as $server=>$bandwidth) {
$segment_bandwidth+= $bandwidth;
$this->Server_LBS[$server] = $segment_bandwidth;
}
$this->Sum_Bandwidth = end( $this->Server_LBS );
}
// Preferentially and pseudorandomly choose a server from the list based on a criterion like:
// bandwidth, average latency, computing power, response time, number of requests per minute.
public function getServer()
{
// Choose a server from the list
$rand_bandwidth = mt_rand(1, $this->Sum_Bandwidth);
// Scan list until find one
foreach ($this->Server_LBS as $server=>$bandwidth) {
if ($rand_bandwidth <= $bandwidth)
break;
}
// Returns the data for the chosen server
return $server;
}
public function __construct(Array $Servers=[])
{
$this->Server_List = $Servers;
// prepare server list for Load Balanced algorithm and save for later use.
$this->prepareLBS();
}
}
/* ~~~~~~~~~~~~~~~~~~ Use Case ~~~~~~~~~~~~~~~~~~~~~ */
$srv_cdn = [
'cdn1.cdnserverxyz.com' => 15,
'cdn2.cdnserverxyz.com' => 30,
'cdn3.cdnserverxyz.com' => 120,
'cdn4.cdnserverxyz.com' => 75,
'cdn5.cdnserverxyz.com' => 10,
];
$LBS = new ByREV_Asym_LB_Server($srv_cdn);
echo $LBS;
Execution speed tests performed in PHP 7.4.2 showed that the above version is 40% faster than the one published 2 years ago.
------ Speed Test ------
CPU: (Ryzen 4800H), ~ 10% load
test: 10000000 req
time: 1.2596859931946 s
req/s: 7.94 milions
------------------------
- ------ Speed Test ------
- CPU: (Ryzen 4800H), ~ 10% load
- test: 10000000 req
- time: 1.2596859931946 s
- req/s: 7.94 milions
- ------------------------
------ Speed Test ------
CPU: (Ryzen 4800H), ~ 10% load
test: 10000000 req
time: 1.2596859931946 s
req/s: 7.94 milions
------------------------
Conclusion: Software Optimization Never END!
Be First to Comment