Balanceamento de Carga com PHP - Parte I
Filed Under (Clustering, PHP) by admin on 18-08-2009
Empresas que possuem um número alto de requisições em seus servidores ou que precisam de alta-disponibilidade em seus sistemas, adotam soluções de cluster adaptadas as sua realidade. Dos três tipos conhecidos (Alto Desempenho, Alta Disponibilidade e Balanceamento de Carga) vou tentar passar as configurações básicas para o Balanceamento de Carga para PHP.
As configurações que vou apresentar podem ser aplicadas em máquinas físicas ou em um ambiente virtualizado.
O primeiro problema a ser resolvido é o das sessões. O PHP por padrão salva os dados de sessões em arquivos dentro
de um diretório local. Em um cluster configurado para balanceamento de carga o PHP então não saberia encontrar os dados da sessão de um usuário ou qual foi o ID criado para ele e etc… Pois, cada máquina, teria seu próprio gerenciador de sessões.
Existem algumas soluções para este problema e a que vou apresentar aqui é a persistência de sessões em banco de dados. Um ponto único de gravação e leitura de sessões com o suporte da transação gerenciada pelo banco.
O banco de dados utilizado aqui será o MySQL, mas o código PHP necessário para o gerenciamento
de sessões pode ser facilmente migrado para qualquer outro banco. Uma boa prática é usar o PDO como camada de
acesso ao banco.
Vamos ao código, o PHP permite alterar o gerenciamento de sessões através da função session_set_save_handler .
Esta função espera seis funções de callback como parâmetro que são:
open
close
read
write
destroy
gc
Então o primeiro passo é definir a classe session que implementará estes métodos:
session.class.php
<?php
class session {
var $life_time;
var $connection;
function session($connection) {
$this->connection = $connection;
$this->life_time = get_cfg_var(”session.gc_maxlifetime”);
//Olha session_set_save_handler aqui!!!
session_set_save_handler(
array( &$this, “open” ),
array( &$this, “close” ),
array( &$this, “read” ),
array( &$this, “write”),
array( &$this, “destroy”),
array( &$this, “gc” )
);
}
function open( $save_path, $session_name ) {
global $sess_save_path;
$sess_save_path = $save_path;
return true;
}
function close() {
return true;
}
function read( $id ) {
$num_rows = 0;
$data = ”;
$time = time();
$newid = mysql_real_escape_string($id); //prefira PDO e bindParams ao mysql_real_escape_string
$result =mysql_query(”SELECT `session_data` FROM `sessions` WHERE `session_id` = “.$newid.” AND `expires` > “.$time, $this->connection);
if ($result) {
$num_rows = mysql_num_rows($result,$this->connection);
if($num_rows > 0) {
$row = mysql_fetch_array($result);
$data = $row['session_data'];
}
}
return $data;
}
function write( $id, $data ) {
$time = time() + $this->life_time;
$newid = mysql_real_escape_string($id); //prefira PDO e bindParams ao mysql_real_escape_string
$newdata = mysql_real_escape_string($data);
$sql = “REPLACE `sessions` (`session_id`,`session_data`,`expires`) VALUES(’$newid’, ‘$newdata’, $time)”;
$rs = mysql_query($sql,$this->connection);
return true;
}
function destroy( $id ) {
$newid = mysql_real_escape_string($id);
$sql = “DELETE FROM `sessions` WHERE `session_id` = ‘$newid’”;
mysql_query($sql, $this->connection);
return true;
}
function gc() {
$sql = ‘DELETE FROM `sessions` WHERE `expires` < UNIX_TIMESTAMP();’;
mysql_query($sql,$this->connection);
return true; //Sempre retorna true
}
}
?>
Agora vamos criar uma página para testes:
teste.php
<?php
require_once(”session.class.php”);
$connection = mysql_connect(”192.168.56.1″,”root”,”");
mysql_select_db(”sessions”, $connection) or die( “Erro ao selecionar a base de dados”);
$session = new session($connection);
session_start();
$_SESSION['time']= date(”H:i:s”);
$_SESSION['server']= “server 1″;
print_r($_SESSION);
?>
E por fim a tabela que irá armazenar os dados das sessões:
CREATE TABLE IF NOT EXISTS `sessions` (
`session_id` varchar(100) NOT NULL DEFAULT ”,
`session_data` text NOT NULL,
`expires` int(11) NOT NULL DEFAULT ‘0′,
PRIMARY KEY (`session_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Rode a aplicação e veja o resultado gravado na tabela.
E agora que já temos toda parte de sessão resolvida vamos para a segunda parte: as configurações de balanceamento.

