Requisitos para instalação do IBM BPM Suite no Red Hat

Filed Under (BPM, Clustering) by admin on 13-11-2009

Estou trabalhando em um projeto de clusterização de várias ferramentas da IBM, entre elas está a suite de BPM. O sistema operacional definido foi o Red Hat Enterprise Linux (RHEL) 5.0 Server/Advanced (Update 1). Então pra quem for fazer uma instalação parecida, aí vai a pequena lista de bibliotecas necessárias para a execução desta tarefa:

compat-libstdc++-33-3.2.3-61
compat-db-4.2.52-5.1
libXp-1.0.0-8
libXmu-1.0.2-5
libXtst-1.0.1-3.1
pam-0.99.6.2-3.26.el5
rpm-build-4.4.2-37.architecture.el5 or later
elfutils-0.125-3.el5
elfutils-libs-0.125-3.el5

So sad :-)

Balanceamento de Carga com PHP - Parte II

Filed Under (Clustering, PHP) by admin on 19-08-2009

Esse tipo de cluster tem como função controlar a distribuição equilibrada do processamento.
Requer um monitoramento constante na sua comunicação e em seus mecanismos de redundância,
pois se ocorrer alguma falha haverá uma interrupção no seu funcionamento.
Wikipédia

Vou assumir que já temos duas máquinas rodando a aplicação criada no passo I e devidamente configuradas para gravar
as sessões em um terceiro servidor, o banco de dados.
Estas máquinas podem ser configuradas com qualquer sistema operacional que suporte um servidor web com PHP
Para o servidor responsável pelo balanceamento de carga eu utilizo o Linux, e neste exemplo o Ubuntu Linux.

Bom, selecionei duas formas de balanceamento para exemplificar: por DNS e por Proxy.
Para o DNS vamos usar o software BIND9 e para o Proxy o Apache + mod_proxy_balancer
A tarefa destes softwares é receber as requisições e dividi-las entre os dois servidores PHP utilizando o algorítimo
mais simples de balancemento: o Round Robin.
Round Robin divide as requisições de forma igual, uma para o servidor A - outra pro servidor B,
sem levar em consideração se A já está executando muitas tarefas ou se B está com consumo muito alto de CPU e etc…
Existe vários tipos de algorítimos e o melhor deve ser escolhido após um estudo aprofundado que leve em consideração
o número de máquinas disponíveis para balanceamento e suas configurações de memória, CPU, link de rede, número de sistemas instalados…

Balanceamento por DNS

Para instalar o BIND9 no Ubuntu basta digitar a linha abaixo
sudo apt-get install bind9

Após a instalação, o servidor já está configurado para ser um servidor de DNS e ouvindo na porta 53.
O próximo passo é configurá-lo de forma que as requisições para o domínio www.exemplo.com.br
sejam redirecionadas para as máquinas com o PHP.

Criaremos então o arquivo /etc/bind/db.exemplo

$TTL 0
IN SOA dns1.exemplo.com.br. email.exemplo.com.br. (
2 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
IN MX 10 mail

mail IN A 192.168.56.107

www IN A 192.168.56.101
IN A 192.168.56.103

Note que em www eu adicionei os IPs dos servidores que vão rodar a aplicação PHP, isso já faz com que o BIND use o Round Robin
para balancear as requisições.

E agora adicionamos uma referência ao db.exemplo no arquivo /etc/bind/named.conf

zone “localhost” {
type master;
file “/etc/bind/db.local”;
};

zone “127.in-addr.arpa” {
type master;
file “/etc/bind/db.127″;
};

zone “0.in-addr.arpa” {
type master;
file “/etc/bind/db.0″;
};

zone “255.in-addr.arpa” {
type master;
file “/etc/bind/db.255″;
};

zone “exemplo.com.br” {
type master;
file “/etc/bind/db.exemplo”;
};

include “/etc/bind/named.conf.local”;

Reinicie o serviço com a linha abaixo:
sudo /etc/init.d/bin9 restart

É interessante neste momento alterar uma linha do arquivo teste.php para melhor visualização do balanceamento:

Servidor A: $_SESSION['server']= “server 1″;

Servidor B: $_SESSION['server']= “server 2″;

Hora de testar: abra a URL http://www.exemplo.com.br/teste.php com o browser e veja o resultado do balanceamento.

Balanceamento via Proxy

O Apache2 possui um módulo chamado mod_proxy_balancer. Ele é uma extensão do mod_proxy, que portanto também deve estar presente
na configuração do balanceamento de carga. O proxy balancer suporta os protocolos HTTP, FTP e AJ13.

Para quem não possui o apache2 instalado pode instalar a partir da linha abaixo:
sudo apt-get install apache2

Para instalar o mod_proxy_balance devemos copiar os arquivos do diretório /etc/apache2/mods-available

proxy_balancer.load
proxy.load
proxy.conf
proxy_http.load

para o diretório:
/etc/apache2/mods-enabled

Vamos agora configurar o módulo para operar no modo reverse proxy (ou gateway). Neste modo a requisição chega ao servidor proxy que decide quem a atenderá, e retorna o resultado ao cliente origem.
Para isso alteramos no arquivo proxy.conf  a diretiva ProxyRequests para o valor off.

Segue abaixo um exemplo de como deve ficar o  arquivo proxy.load

<IfModule mod_proxy.c>
         ProxyRequests Off

        <Proxy *>
                AddDefaultCharset off
                Order deny,allow
           Allow from all #Isso é apenas um exemplo, configure seu proxy com segurança!!!!
        </Proxy>

 <Proxy balancer://meucluster>
  BalancerMember http://192.168.56.103:80 #Servidor PHP A
  BalancerMember http://192.168.56.102:80 #Servidor PHP B
 </Proxy>
 ProxyPass /teste balancer://meucluster
</IfModule>

 

Reinicie o Apache:
sudo /etc/init.d/apache2 restart

Neste exemplo meu servidor proxy atende pela URL www.appteste.com.br e redireciona para os IPs 192.168.56.103 e 192.168.56.102 que estão rodando a aplicação de teste.
Hora de testar: abra a URL http://www.appteste.com.br/teste/teste.php com o browser e veja o resultado do balanceamento.

Bom, acho que consegui passar uma visão de como podemos configurar um balanceamento com PHP. O assunto, claro,
não para por aqui. Existem inúmeras outras situações, configurações, problemas, soluções, algorítimos… Mas, um problema que fica claro na solução acima é o fato do load balancer se tornar mais um ponto de falha na arquitetura. Basta imaginar que se ele cair, todo trabalho está perdido e será um assunto que quero tratar nos próximos posts.
Valeu!

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.