Quem sou eu

quarta-feira, 28 de julho de 2010

Cassandra + PHP

No post anterior eu expliquei sobre o funcionamento do Cassandra. Agora vamos colocar a mão na massa e vamos configurar o nosso servidor Debian para criar aplicações em PHP que interajam com o Cassandra.

O PHP precisa de uma biblioteca chamada Thrift para se comu

nicar com o Cassandra. Temos duas formas de trabalhar com ela, a primeira é usando a biblioteca dentro do diretório da nossa aplicação e a segunda é compilar um módulo nativo para o PHP. O módulo nativo proporciona muito mais velocidade. Vamos mostrar abaixo como configurar as duas formas.

1- Configuração do servidor

Passos para instalar o Thrift no servidor sem o módulo nativo do PHP:

- apt-get install libboost-dev automake libtool flex bison pkg-config g++
- wget http://ftp.unicamp.br/pub/apache/incubator/thrift/0.2.0-incubating/thrift-0.2.0-incubating.tar.gz
- tar -xzvf thrift-0.2.0-incubating.tar.gz
- cd thrift-0.2.0
- ./configure
- make
- ./compiler/cpp/thrift -gen php ../PATH-TO-CASSANDRA/interface/cassandra.thrift
- mkdir -p /usr/share/php5/Thrift- cp -R gen-php/ /usr/share/php5/Thrift/packages/
- cp -R lib/php/src/* /usr/share/5php/Thrift/

Passos para instalar o módulo nativo do PHP:

- cd PATH-TO-THRIFT/lib/php/src/ext/thrift_protocol
- apt-get install php5-dev
- phpize
- ./configure --enable-thrift_protocol
- make
- cp modules/thrift_protocol.so /usr/lib/php5/20060613/

(A pasta lib do PHP vai depender da versão instalada no seu servidor)- vi /etc/php5/cli/conf.d/thrift_protocol.ini
extension=thrift_protocol.so
- Verificar instalação:
php -i | grep -v "PWD" | grep "thrift_protocol"
- /etc/init.d/apache2 restart

2- Inserindo dados no Cassandra com o PHP

Agora que já temos o servidor configurado e pronto para funcionar, vamos fazer alguns testes inserindo dados no cassandra. Vamos usar como base o exemplo do post anterior.

Re-lembrando os dados:

ColumnFamily: Usuarios

['junior']['login'] = ['junior']
['junior']['nome'] = ['Nivaldo']
['junior']['sobrenome'] = ['Montenegro']
['junior']['email'] = ['nivaldomjunior@gmail.com']
['usuario2']['login'] = ['usuario2']
['usuario2']['nome'] = ['Fulano']
['usuario2']['sobrenome'] = ['de tal']
['usuario2']['email'] = ['fulano@gmail.com']
['usuario2']['fone'] = ['(83)1234-1234']

SuperColumn: Agenda

['junior']['amigo1']['nome'] = ['Amigo 1']
['junior']['amigo1']['telefone'] = ['(88)1234-1234']
['junior']['amigo2']['nome'] = ['Amigo 2']
['junior']['amigo2']['telefone'] = ['(99)4312-4312']
['usuario2']['amigox']['nome'] = ['amigox']
['usuario2']['amigox']['telefone'] = ['(77)9987-0987']
['usuario2']['amigoy']['nome'] = ['Amigo y']
['usuario2']['amigoy']['email'] = ['fulano@gmail.com']
['usuario2']['amigoy']['fone'] = ['(83)1234-1234']

O código do arquivo php está em um arquivo de imagem, mas vou disponibilizar posteriormente o arquivo php para download.

Código do arquivo criar.php:

Clique aqui para baixar o arquivo criar.php.

3- Consultando dados no Cassandra

As consultas são realizadas em cima dos índices, ou seja, não dá para consultarmos diretamente os valores das chaves como estamos acostumados a fazer em um banco de dados SQL.

Por exemplo, vamos consulta os dados da Agenda do usuário junior:

4- Mais informações

Bom, este foi um exemplo rápido sobre como podemos usar o Cassandra com PHP. Espero que sirva como base para que você inicie no desenvolvimento com PHP e Cassandra.

Alguns links de referência:

- Using Cassandra with PHP

- ThriftExamples

- Site do projeto Cassandra

Até a próxima! :)

sexta-feira, 23 de julho de 2010

Entendendo o banco de dados NoSQL Cassandra

Por necessidade, resolvi realizar testes em bancos de dados NoSQL. Estava precisando de um banco de dados que comporte pelo menos 1.5 milhões de registros por dia e que forneça uma forma rápida para realizar consultas.

Testei três NoSQL: Cassandra, MongoDB e CouchDB.

Criei uma pequena aplicação em PHP para inserir 500 milhões de registros (exagerei né? Mas precisava ter certeza) e um PHP para listar a quantidade de registros. Percebi que ainda tem poucos tutoriais que mostram de forma clara como as coisas funcionam e por isso resolvi escrever alguns pequenos posts mostrando o caminho das pedras.

Resolvi então escrever alguns posts sobre banco de dados NoSQL com PHP.

Vamos começar falando sobre o Cassandra com PHP.

1- Por onde começar?

A primeira coisa a fazer é acessar o site do projeto http://cassandra.apache.org e fazer o download do Cassandra. A versão que usei para os testes foi o Cassandra 0.6.3.

Passos para baixar e iniciar o Cassandra:

- wget http://ftp.unicamp.br/pub/apache/cassandra/0.6.3/apache-cassandra-0.6.3-bin.tar.gz
- tar -xzvf apache-cassandra-0.6.3
- cd apache-cassandra-0.6.3
- ./bin/cassandra -f

Depois desses comandos o Cassandra estará funcionando com as configurações padrão. Mas antes de começarmos a usar é necessário entenderemos a estrutura desse banco de dados NoSQL. Pra quem é acostumar com bancos de dados tradicionais, é necessário um pouco de esforço para a quebra de paradígma.

2- Conhecendo a estrutura do Cassandra

O Cassandra é um banco de dados NoSQL e armazena as informações no formato chave = valor, mas para quem está acostumado com bancos de dados tradicionais, tabelas, joins, normalização, etc., é difícil colocar na cabeça que tudo o que você aprendeu a vida toda foi por água abaixo. :)

Li vários artigos e tutoriais para entender o esquema de armazenamento e indexação do Cassandra. Um excelente ponto de partida é este artigo: WTF is a SuperColumn? An Intro to the Cassandra Data Model.

Pra quem não sabe o que significa WTF: What the fuck... ou seja, que porra é uma supercolumn?!?! :)

Com este artigo dá para entender bem o funcionamento do esquema de armazenamento e indexação, por isso, não explicarei detalhadamente como funciona, apenas superficialmente através de exemplo para complementar o artigo citado.

De forma bem simplificada:

- Column: Armazena chave, valor e timestamp. Todos os dados são armazenados em columns. A column não precisa ser criada em arquivo de configuração, basta inserir uma nova column com chave/valor que o banco de dados cria automaticamente. Column - ['id']['chave'] = ['valor']

- SuperColumn: Armazena chave = chave/valor/timestamp. É como se fosse um conjunto de columns. A SuperColumn na verdade é uma ColumnFamily do tipo Super. Possui duas chaves. SuperColumn - ['id']['chave1']['chave2'] = valor

- ColumnFamily: É uma família de colunas, ou seja, é o agrupamento de várias chave = valor. É necessário criar a ColumnFamily dentro das configurações do cassandra (storage-conf.xml). Ou seja, as Columns ficam armazenadas em uma ColumnFamily.

Exemplo:

ColumnFamily: Usuarios

['junior']['login'] = ['junior']
['junior']['nome'] = ['Nivaldo']
['junior']['sobrenome'] = ['Montenegro']
['junior']['email'] = ['nivaldomjunior@gmail.com']
['usuario2']['login'] = ['usuario2']
['usuario2']['nome'] = ['Fulano']
['usuario2']['sobrenome'] = ['de tal']
['usuario2']['email'] = ['fulano@gmail.com']
['usuario2']['fone'] = ['(83)1234-1234'] 
 

Usuarios = { // ColumnFamily
    junior: {   // Esta é a chave da CF (id)
        // Dentro da CF podemos ter um número infinito de chave/valor
        login: "junior",
        nome: "Nivaldo",
        sobrenome: "Montenegro",
        email: "phatduckk@example.com",
    }, // Fim
    usuario2: {   // Esta é a chave para outra linha na CF (id)
        // Podemos inserir outro número infinito de chave/valor e não precisa ter as mesmas chaves/valor que outras linhas da CF
        login: "junior",
        nome: "Nivaldo",
        sobrenome: "Montenegro",
        email: "phatduckk@example.com",         fone: "(83) 1234-1234"
    },
}

- KeySpace: É um conjunto de ColumnFamily. Analogamente, é como se fosse um banco de dados criado dentro do cassandra. É necessário realizar configurações no arquivo storage-conf.xml para criar as KeySpaces e realizar um restart no Cassandra.

Evoluindo o exemplo dado para a ColumnFamily, podemos transformar a ColumnFamily em uma SuperColumn e termos dados mais organizados sobre os clientes.

Exemplo SuperColumn:

Exemplo:

SuperColumn: Agenda

['junior']['amigo1']['nome'] = ['Amigo 1']
['junior']['amigo1']['telefone'] = ['(88)1234-1234']
['junior']['amigo2']['nome'] = ['Amigo 2']
['junior']['amigo2']['telefone'] = ['(99)4312-4312']
['usuario2']['amigox']['nome'] = ['amigox']
['usuario2']['amigox']['telefone'] = ['(77)9987-0987']
['usuario2']['amigoy']['nome'] = ['Amigo y']
['usuario2']['amigoy']['email'] = ['fulano@gmail.com']
['usuario2']['amigoy']['fone'] = ['(83)1234-1234'] 

Agenda = { // SuperColumn
    junior: {   // ColumnFamily        amigo1: { //Chave da ColumnFamily
              // Dentro da CF podemos ter um número infinito de chave/valor
              nome: "Amigo 1",
              telefone: "(88)1234-1234",
        } //Fim do amigo1
        amigo2: { //Outra chave na ColumnFamily 
              nome: "Amigo 2",
              telefone: "(99)4312-4312",
        } // Fim do amigo 2

    }, // Fim da CF junior
    usuario2: {   // Outra ColumnFamily
        amigox: { //Chave da ColumnFamily

              // Podemos inserir outro número infinito de chave/valor e não precisa ter as mesmas chaves/valor que outras linhas da CF
              nome: "amigox",
              telefone: "(77)99870987",
        } //Fim amigox
        amigoy: { //Outra CF

              nome: "Amigo Y",
              fone: "(83)1234-1234"

              email: "fulano@gmail.com",
        } //Fim amigoy
    }, //Fim da CF usuario2
}

Ou seja, temos os seguintes níveis no Cassandra:

KeySpaces

    ColumnFamily
         Columns
    SuperColumn
         ColumnFamily
               Columns 

Um fato importante é que as buscas necessariamente precisam ser realizadas usando os índices, ou seja, as chaves das ColumnFamilys. Não tem como fazermos as consultas usando os valores finais das chaves diretamente no banco de dados. Para isso é necessário buscarmos todos os dados e realizarmos a consulta usando a linguagem de programação. Por isso, é extremamente importante criar índices que realmente sejam utilizados e não usar números sequencias como costumamos fazer nos campos id das tabelas em um banco de dados tradicional.

3- Configurando o cassandra para atender o exemplo acima

É necessário configurar o Cassandra para criar as KeySpaces, ColumnFamilys e SuperColumns (ColumnFamily do tipo Super) que iremos precisar para armazenar os nossos dados. As configurações são relativamente simples, mas precisamos definir qual o tipo de ordenação que faremos para cada ColumnFamily e SuperFamily, pois os dados são armazenados e ordenados automaticamente de acordo com a configuração criada para a ColumnFamily ou SuperColumn.

Exemplo de configuração:

    <Keyspace Name="Teste">
        <!-- Definição da ColumnFamily -->
        <ColumnFamily CompareWith="UTF8Type" Name="Usuarios"/>
        <!-- Definição da SuperColumn -->
        <ColumnFamily CompareWith="UTF8Type" Name="Agenda"
            CompareSubcolumnsWith="UTF8Type" ColumnType="Super"/>
    </Keyspace>

O parâmetro CompareWith nas ColumnFamilys é o que vai determinar a forma de ordenação da ColumnFamily. O CompareWith no nosso exemplo vai ser usado para ordenar a chave da ColumnFamily, que no nosso exemplo tem dois valores: junior e usuario2. No artigo citado acima (esse link) tem um exemplo bem detalhado sobre a forma de ordenação.

Já nas SuperColumns, o parâmetro CompareWith ordena o nome da ColumnFamily, no nosso exemplo os valores junior e usuario2, e o parâmetro CompareSubColumnsWith ordena a chave da ColumnFamily, que no nosso exemplo tem os valores amigo1, amigo2, amigox e amigoy.

4- Conclusão

O Cassandra é um banco de dados NoSQL extremamente flexível e poderoso, principalmente quando se pensa em escalabilidade, mas a organização dos dados é o que vai determinar o sucesso da utilização desse tipo de banco de dados. É necessário realizar um trabalho minucioso em cima dos índices para que as buscas sejam realmente rápidas e eficientes, minimizando a filtragem de dados usando a linguagem de programação.

Espero que eu tenha esclarecido as suas dúvidas e no próximo post vou falar um pouco sobre como utilizar o Cassandra com PHP em um servidor com Debian.

 

quinta-feira, 1 de julho de 2010

Instalando e configurando o FOP2 para monitorar o seu Asterisk

Esses dias tava navegando em sites sobre Asterisk e vi o pessoal falando sobre o FOP 2 (Flash Operator Panel). Lembrei que tinha testado a primeira versão do FOP, mas não tinha gostado muito. Achei a interface um feinha.
Resolvi então testar o FOP 2 e gostei muito, compramos inclusive uma licença para monitorar mais de 15 ramais.
Estou usando no PABX da empresa monitorando todos os ramais, os dois E1s, os troncos SIP e IAX, as portas analógicas FXO (interface de celular), as filas de atendimento e as salas de conferência e estamos muito satisfeitos com o desempenho e funcionamento.

O procedimento de instalação e configuração é bem simples.

1- Faça o download do FOP 2 em http://www.fop2.com/download.php

2- Descompacte a versão que você baixou, no meu caso Debian Lenny

# cd /usr/src/
# tar -xzvf fop2-2.11-debian-i386.tgz

3- Instale o FOP 2 executando make install:

# cd fop2/
# make install

Este será o resultado do comando:

New configuration file /usr/local/fop2/fop2.cfg.new installed.
Original fop2.cfg preserved.
New configuration file /var/www/fop2/config.php.new installed.
Original config.php preserved.update-rc.d: warning: /etc/init.d/fop2 missing LSB information
update-rc.d: see  System startup links for /etc/init.d/fop2 already exist.Done!

4- Edite o arquivo fop2.cfg para configurar o FOP2

# cd /usr/local/fop2/
# vi fop2.cfg

- Configure o manager através dos parâmetros:

; AMI definitions
manager_host=localhost
manager_port=5038
manager_user=admin
manager_secret=senha

- Configure os usuários que terão acesso ao FOP2 e defina um arquivo de botões

user=8195:1234:all
buttonfile=buttons.cfg

No meu caso, 8195 é também o nome do meu usuário SIP. Dessa forma eu poderei interagir com o FOP2 para executar comandos de discagem, transferência, etc e tudo será direcionado para o telefone IP da minha mesa.

- Comente a última linha do arquivo:
;#exec autoconfig-users-freepbx.sh

5- Crie um arquivo com as configurações dos seus ramais SIP, trunks, salas de conferência e filas (buttons.cfg, conforme definido no fop2.cfg):

Exemplo de arquivo:

# vi buttons.cfg
[SIP/8195]
type=extension
extension=8195
context=Ramais
label=Junior

[QUEUE/Fila-XYZ]
type=queue
label=SAC
extension=100
context=ramais

[DAHDI/1]
type=trunk
label=E1 da Embratel
channel=DAHDI/1
channel=DAHDI/2
channel=DAHDI/3
channel=DAHDI/4

[CONFERENCE/1000]
type=conference
label=Sala de conferencia
server=1
extension=8177
context=ramais

6- Após configurar os arquivos necessários, precisamos iniciar o serviço do FOP server para que o FOP2 funcione. Faça isso executando o comando:

# /etc/init.d/fop2 start

7- Acesse a URL http://IP_SERVIDOR/fop2 e utilize o usuário e senha criado no fop2.cfg para ter acesso aos recursos do FOP

Caso você não esteja conseguindo acessar o FOP depois de digitar o login e senha, você pode iniciar o servidor manualmente usando o comando /usr/local/fop2_server e verificar qual a mensagem de erro que está sendo mostrada na inicialização do serviço.

Usando as configurações do fop2.cfg, é possível definir grupos de acesso e associá-los aos usuários. Dessa forma você poderá montar paines de operadora diferentes de acordo com cada usuário que acessar.

Para maiores informações sobre o FOP, é só consultar a documentação online dele no endereço: http://www.fop2.com/documentation.php

Então é isso! :)

Um breve tutorial de como instalar e configurar o FOP.