Archive for outubro \24\-02:00 2011

PHP e Computação em Nuvem com Zend_Cloud

Posted on outubro 24, 2011. Filed under: PHP, Tuning, Zend Framework |

Muito se fala hoje me dia sobre computação em nuvem. Gostaria de abordar esse tema junto com a linguagem PHP. Nuvens oferecem ilimitados recursos para sua aplicação. Você tem diversas opções disponíveis de plataformas Cloud: Amazon, Rackspace, Microsoft, Google e diversas outras. A maioria delas oferecem dois tipos de serviços em Cloud, IaaS (Infrastructure-as-a-Service) e PaaS (Platform-as-a-Service):

IaaS (Infrastructure-as-a-Service) – As máquinas virtuais estão sob seu total controle. Você tem acesso root e portanto toda manutenção/instalação esta em sua responsabilidade. Incluíndo também o firewall, balanceamento, etc.

PaaS (Platform-as-a-Service) – Abordagem também através de máquinas virtuais. Porém o controle da infraestrutura não é sua responsabilidade. Você se preocupa somente com o desenvolvimento de sua aplicação. Para que isso seja possível, a plataforma de cloud computing disponibiliza APIs para que você possa interagir com a plataforma. Normalmente as APIs são disponibilizadas através de protocolo REST via WebService. Windows Azure, Amazon são exemplos desse tipo de arquitetura.

SimpleCloud

Como já citamos anteriormente temos diversas opções de plataformas para cloud. Cada uma dessas opções tem suas próprias APIs para interação com a plataforma. Gostaria de chamar atenção aqui para o projeto da Zend chamado SimpleCloud que tem o objetivo de fornecer uma camada de abstração para as APIs das plataformas de computação em nuvem. A boa notícia é que esse projeto transformou-se em um componente do Zend Framework, chamado Zend_Cloud. Baixe a última versão do Zend Framework para poder utilizar esse recurso.

Amazon

Como citei anteriormente, o Zend_Cloud fornece uma camada de abstração para plataformas de Cloud Computing. Portanto vamos utilizar os serviços de Cloud da Amazon como backend para os teste deste artigo. Poderíamos usar o Windows Azure ou outra opção disponpivel, porém neste artigo vamos trabalhar com a Amazon. Antes de continuar, será necessário criar uma conta no AWS da Amazon (gratuito). Acesse o link para criar sua conta.

Após criar a conta você precisará obter seu AWS Key e AWS Secret Key que serão utilizados para acessar os serviços de Cloud quer iremos ver mais adiante. Para obter as chaves, acesse o link Account -> Security Credentials.

Serviço de Storage

O serviço de Storage permite armazenar qualquer tipo de dados em qualquer hora de qualquer parte da web. Os tipos de armazenagem normalmente são imagens, arquivos para download, vídeos, distribuição de arquivos temporários, etc. Para disponibilizar os dados para usuários da sua aplicação, você pode disponibilizar links diretos, ou você pode construir um aplicação para intermediar o acesso. Lembre-se que aqui não deve ser armazenado arquivos da sua aplicação, mas arquivos para o usuário. (imagens, vídeos, arquivos para download, etc.)

O serviço de storage do Amazon chamá-se Amazon S3. Você precisa habilitar esse serviço na sua conta do Amazon. Para isso acesse o link abaixo:

http://aws.amazon.com/s3/

Você precisa informar um número de cartão de crédito válido. Você não será cobrado até que o serviço seja utilizado. Como estamos usando para testes, o valor cobrado será mínimo. Para você ter uma idéia, para testar os exemplos utilizados neste artigo gastei somente $0,03. No próprio link acima você pode consultar as tabelas de preço para esse serviço.

Para começar a armazenar seus arquivos no storage será necessário criar aquilo que chamamos de bucket. Todos dados são armazenados em buckets. Pense no bucket como se fosse um driver separado em seu computador. Lembre-se também que um bucket esta em um namespace compartilhado com todos os outros usuários do Amazon S3, portanto o nome do bucket tem que ser único.

Os arquivos armazenados no bucket são chamados de objetos. Podemos manter uma estrutura hierarquica dos objetos dentro dos buckets como se eles estivessem dentro de diretórios, como por exemplo, chamando o objeto de imagens/zend-logo.png.

Vamos criar o bucket através do console de gerenciamento da Amazon. Poderíamos ter feito através de código PHP utilizando sua API, porém vamos usar o console para facilitar nossa tarefa. Logado no site da Amazon com seu usuário, acesse o console de gerenciamento do S3 e crie o seu bucket clicando no botão Create Bucket.

Agora que temos um bucket, podemos criar nosso script php para inserir arquivos dentro do S3. Primeiro crie o arquivo cloud.ini onde iremos parametrizar os dados para acessar o storage. Dessa forma, você não precisa inserir esses dados em todos scripts que você for trabalhar com o Zend_Cloud:

cloud.storage_adapter="Zend_Cloud_StorageService_Adapter_S3"
cloud.aws_accesskey="XXXXXXXXXXXXXXXXXXXX"
cloud.aws_secretkey="1234567890123456789012345678901234567890"
cloud.bucket_name="pasquati"

Abaixo é o código usado para inserir arquivos no Storage da Amazon. Neste exemplo, estamos inserindo um logotipo do Zend Framework.

<?php
/* includes */
require_once ("Zend/Cloud/StorageService/Factory.php");
require_once ("Zend/Cloud/StorageService/Adapter.php");
require_once ("Zend/Config/Ini.php");

/* carregar as configuracoes para o Zend_Cloud  */
$config = new Zend_Config_Ini('cloud.ini');

/* instancia do storage */
$storage = Zend_Cloud_StorageService_Factory::getAdapter($config->cloud);

/*
 * nome do objeto (id) que sera inserido no storage
 * Quando precisarmos acessar esse objeto utilizaremos esse nome
 */
$caminhoArquivo = 'imagens/zend-logo.png';

/* conteudo do arquivo que sera enviado ao storage */
$data = file_get_contents('zend-logo.png');

/*
 * inserindo o objeto no storage.
 * setamos permisao de leitura para todos usarios
 */

$storage->storeItem($caminhoArquivo, $data, array(
        Zend_Cloud_StorageService_Adapter_S3::METADATA => array(
            Zend_Service_Amazon_S3::S3_ACL_HEADER => Zend_Service_Amazon_S3::S3_ACL_PUBLIC_READ,
        )
));

echo "Arquivo enviado ao storage com sucesso!\r\n";

Por padrão, ao inserirmos um arquivo dentro do storage, ele possui permissões de leitura e gravação somente para o nosso usuário. Porém, no exemplo anterior, setamos permissão que qualquer pessoa na web possa acessar o nosso arquivo. Caso você queira disponibilizar os arquivos do storage na web, a URL deve ser montada de acordo com o modelo abaixo:

http://<bucket-name>.s3.amazonaws.com/imagens/zend-logo.png

ou

http://s3.amazonaws.com/<bucket-name>/imagens/zend-logo.png

Podemos também fazer o download dos arquivos do storage através de um script php. Segue abaixo exemplo do código que fará o download do logo da zend e o armazenará em disco.

<?php
/* includes */
require_once ("Zend/Cloud/StorageService/Factory.php");
require_once ("Zend/Cloud/StorageService/Adapter.php");
require_once ("Zend/Config/Ini.php");

/* carregar as configuracoes para o Zend_Cloud  */
$config = new Zend_Config_Ini('cloud.ini');

/* instancia do storage */
$storage = Zend_Cloud_StorageService_Factory::getAdapter($config->cloud);

/*
 * nome do objeto (id) que sera obtido do storage
 */
$caminhoArquivo = 'imagens/zend-logo.png';

/* obtendo os dados do arquivo a partir do storage */
$dados = $storage->fetchItem($caminhoArquivo);

/* salvando o arquivo restaurado em disco */
file_put_contents("zend-logo-restaurado.png", $dados);

echo "Arquivo recebido do storage com sucesso!\r\n";

Document Service

O componente Document Service do Zend_Cloud abstrai funcionalidades do serviços como Amazon SimpleDB e Azure Table Storage. Conhecido como “bancos de documentos” são fontes de dados categorizados como banco de dados não-relacionais. É uma estrutura desenvolvida especificamente para alta perfomance, escabilidade e flexibilidade. O usuário não precisa se preocupar com administração do banco de dados mais, preocupa-se somente com o desenvolvimento da aplicação.

Para utilizar o Document Service fornecido pela Amazon, registre-se através do link http://aws.amazon.com/simpledb/.

Para utilizar o serviço configure o cloud.ini da seguinte forma:

cloud.document_adapter="Zend_Cloud_DocumentService_Adapter_SimpleDb"
cloud.aws_accesskey="XXXXXXXXXXXXXXXXXXXX"
cloud.aws_secretkey="1234567890123456789012345678901234567890"

Primeiramente iremos criar um collection onde iremos armazenar dados. Pense em collections como se fossem tabelas em um banco de dados relacional.

<?php
/* includes */
require_once ("Zend/Cloud/DocumentService/Factory.php");
require_once ("Zend/Cloud/DocumentService/Adapter.php");
require_once ("Zend/Config/Ini.php");

/* carregar as configuracoes para o Zend_Cloud  */
$config = new Zend_Config_Ini('cloud.ini');

/* instancia do DocumentService */
$adapter = Zend_Cloud_DocumentService_Factory::getAdapter($config->cloud);

/* cria collection */
$adapter->createCollection("usuarios");

echo "Collection criada com sucesso \r\n";

Após criado o collection, podemos inserir documentos nele. Todo documento inserido deve ser identificado através do que chamamos de “Document ID”. Cada documento pode ter sua própria estrutura. Não é necessário que os documentos armazenados em um mesmo collection tenham a mesma estrutura.

Inserindo documentos no collection:

<?php
/* includes */
require_once ("Zend/Cloud/DocumentService/Factory.php");
require_once ("Zend/Cloud/DocumentService/Adapter.php");
require_once ("Zend/Config/Ini.php");

/* carregar as configuracoes para o Zend_Cloud  */
$config = new Zend_Config_Ini('cloud.ini');

/* instancia do DocumentService */
$adapter = Zend_Cloud_DocumentService_Factory::getAdapter($config->cloud);

/*
 * ao obter a class do adpter, garantimos que eh uma classe
 * direta ou que extende Zend_Cloud_DocumentService_Document
 */
$class = $adapter->getDocumentClass();

/* chave primaria do registro */
$primaryKey = 'doug123';

/* dados que a serem inseridos no collection */
$doc = new $class(array(
        'nome' => 'Douglas',
        'apelido' => 'Doug',
        'email' => 'douglas.pasqua@gmail.com',
        'idade' => 29,
        'pais' => 'Brasil',
        'idioma' => 'PHP',),
        $primaryKey
);

/* insere os dados em uma collection (tabelas) */
$adapter->insertDocument("usuarios", $doc);

echo "Dados inseridos com sucesso\r\n";

Documentos podem ser obtidos através do ID ou através de “query” no collection.

<?php
/* includes */
require_once ("Zend/Cloud/DocumentService/Factory.php");
require_once ("Zend/Cloud/DocumentService/Adapter.php");
require_once ("Zend/Config/Ini.php");

/* carregar as configuracoes para o Zend_Cloud  */
$config = new Zend_Config_Ini('cloud.ini');

/* instancia do DocumentService */
$adapter = Zend_Cloud_DocumentService_Factory::getAdapter($config->cloud);

/* montando a query */
$query = $adapter->select();
$query->where("email = ?", "douglas.pasqua@gmail.com");

/* fazendo a query no collection */
$r = $adapter->query('usuarios', $query);

/* iterando atraves dos dados obtidos na query */
foreach($r as $reg) {
        echo "Nome: " . $reg->nome . PHP_EOL;
}

Temos vários outros métodos para trabalhar com Documents no Zend Cloud, consulte a documentação para mais exemplos:

http://framework.zend.com/manual/en/zend.cloud.documentservice.html

Queue Service

O Queue Service permite um tipo de computação de dados de forma assíncrona. A implementação permite distribuir mensagens de forma confiável e escalável. Um exemplo de aplicação que utiliza esse serviço seria um “Job Dispatching”. O Frontend dispara o job para o Queue Service de forma assíncrona e temos uma outra aplicação que processa os jobs como se estivesse em background. Esse cenário pode ser útil em várias outras situações. Caso queira habilitar o Queue Serice da Amazon, é necessário habilitar o serviço na sua conta através do link http://aws.amazon.com/sqs/. Para exemplos de utilização no Zend Framework, acesse o link http://framework.zend.com/manual/en/zend.cloud.queueservice.html.

Conclusão

Abordamos aqui os 3 tipos de componentes disponibilizados pelo Zend_Cloud (Storage Service, Document Service e Queue Service). A grande vantagem o Zend_Cloud é que sua estrutura interna faz a abstração das APIs específicas para cada plataforma de computação em nuvem. Portanto caso precise migrar de uma plataforma para outra, será necessário apenas alguns ajustes. Um exemplo, migrar do Amazon para o Microsoft Azure os exemplos deste artigo pode ser feito com poucos ajustes. Amazon e Windows Azure disponibilizam diversos outros serviços de computação em nuvem além desses. Aconselho visitar as referências abaixo para aprender mais.

Referências

http://framework.zend.com/manual/en/zend.cloud.html
http://simplecloud.org/
http://aws.amazon.com/s3/
http://aws.amazon.com/simpledb/
http://aws.amazon.com/sqs/
http://www.microsoft.com/windowsazure/
http://aws.amazon.com/php/

Ler Post Completo | Make a Comment ( 2 so far )

PHP Caching com Zend_Cache

Posted on outubro 12, 2011. Filed under: PHP, Tuning, Zend Framework |

O Zend_Cache é um componete distribuído junto com o Zend Framework. Pode ser usado tanto como um módulo standalone ou junto com o framework. Muito flexível, permite que você decida o que quer fazer cache (frontend) e onde armazenar (backend). Ao configurar uma instância do Zend_Cache você deve informar dois grupos de opções. Um para o frontend e outro para o banckend. Existem vários frontends e backends disponíveis por padrão no Zend Framework. Todos frontends extendem a classe Zend_Cache_Core que provê funcionalidades genéricas de cache.

Tipos de frontends disponíveis

Além da possibilidade de usar o frontend Core que provê cache de dados de forma básica, o Zend_Cache permite vários outros tipos de cache de dados.

  • Class – Permite realizar o cache de objetos e de chamadas para métodos estáticos.
  • File – Realiza o cache de arquivos que são carregados para dentro do PHP.
  • Function – Realiza o cache do retorno de uma função.
  • Output – Utiliza o Output Buffering do PHP. Ideal para fazer cache parcial de uma página. Realizará o cache de tudo que estiver entre os métodos start() e end().
  • Page – Semelhante ao frontend de Output. Porém com o Page o cache é realizado com páginas completas somente.
  • Capture – Usando juntamente com o backend Static é utilizado para gerar páginas estáticas à partir de páginas dinâmicas. Portanto, as requisições subsequentes não precisam passar pelo PHP ou Zend Framework.

Tipos de backends disponíveis

  • File – Armazena os registros do cache em arquivos.
  • APC – Armazena os registros de cache em memória compartilhada pelo APC (Alternative PHP Cache).
  • Zend Server/ZendPlataform – Armazena os registro de cache usando a funcionalidade de Cache do Zend Server.
  • XCache – Armazena os registros de cache em memória compartilhada pelo XCacahe.
  • Sqllite – Armazena os registros de cache em um banco de dados SQLite.
  • Memcached/Libmemcached – Armazena os registros de cache em servidor memcached.
  • TwoLevels – Permite especificar dois outros backends para armazenar os registros de cache.
  • Static – Usando juntamente com o frontend Capture é utilizado para gerar páginas estáticas à partir de páginas dinâmicas. Portanto, as requisições subsequentes não precisam passar pelo PHP ou Zend Framework.

Exemplos

Abaixo vamos demonstrar um exemplo simples da utilização do Zend_Cache. O exemplo utiliza o frontend Core que faz cache de dados simples. Estamos utilizando o backend File para armazenar os dados. Não recomendo à utilização do backend File pois ele é mais lento do que outros backends, principalmente aqueles que utilizam memória compartilhada. Estou utilizando neste exemplo pois para você que simplesmente quer testar os exemplos não necessita de instalar programas adicionais além do php e Zend_Cache. O importante salientar é que independente do backend que você escolha, a sintaxe de utilização do Zend_Cache é totalmente transparente.

O exemplo abaixo faz o cache de um array de dados. Os dados são informações sobre usuários do sistema. Para instânciar o cache, informamos qual o frontend e qual o backend desejamos. Passamos também um array de opções para frontend e backend. Nas opções do frontend informamos que os dados devem ser serialziados antes de serem inseridos no cache, através da opção automatic_serialization. Isto evita o nosso trabalho de fazer um serialize dos dados antes de colocar no cache. Nas opções de backend informamos qual o diretório o Cache utilizará para armazenar os dados. Esta opção é obrigatória pois estamos utilizando o tipo File como backend. No caso, o diretório será /phpcache.

<?php
require_once("Zend/Cache.php");

// opcoes para frontend
$frontendOptions = array (
        'automatic_serialization' => true
);

// opcoes para backend
$backendOptions = array (
        'cache_dir' => '/phpcache'
);

// instanciar o cache
$cache = Zend_Cache::factory(
        'Core',
        'File',
        $frontendOptions,
        $backendOptions);

// utilizando o cache
$usuarios = $cache->load('usuarios');
if(!$usuarios) {
        // inserir dados no cache
        $usuarios = array(
                array('id' => 1, 'nome' => 'Manuel', 'email' => 'manuel@xxxxyy.com.br', 'telefone' => '011-1111-1111'),
        array('id' => 2, 'nome' => 'Pereira', 'email' => 'pereira@xxxxyy.com.br', 'telefone' => '011-2222-2222'),
    );
        $cache->save($usuarios, 'usuarios', array('usuario', 'admin'));
}

// dados do usuáo
echo "<pre>";
var_dump($usuarios);
echo "</pre>";

Retorno do exemplo acima:

Neste exemplo, gostaria de chamar à atenção para a função save do Zend Cache:

$cache->save($usuarios, 'usuarios', array('usuario', 'admin'));

Além de utilizarmos um identificador único para referênciar os dados no cache, ‘usuarios’, também utilizamos dois tags, ‘usuario’ e ‘admin’. Podemos portanto agrupar dados de cache através das tags. Dessa forma, podemos excluir, por exemplo, todos os dados no cache que tem associado a tag ‘admin’. Facilita a vida não ?

Limpando o Cache

Deletando todos dados no cache que possuem à tag ‘admin’ associado:

$cache->clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array('admin'));

Deletando dados do cache especificando o identificador:

$cache->remove('usuarios');

Removendo todos dados do cache de uma única vez:

$cache->clean(Zend_Cache::CLEANING_MODE_ALL);

Fazendo Cache de classes

O Frontend Class do Zend_Cache permite o cache de objetos e de métodos estáticos. No exemplo abaixo estamos fazendo o cache de um objeto da classe Usuario. Para que funcione de acordo com o esperado, definimos a opção cached_entity no bloco de opções do frontend. Dessa forma, o Zend_Cache irá fazer o cache da saída de todos métodos públicos referente ao objeto dessa classe.

<?php

require_once("Zend/Cache.php");

/*
 * Classe Usuario para exemplificar o cache de classes do Zend_Cache
 */
class Usuario {
        private $nome1 = "Jose";
        private $nome2 = "Pedro";

        public function getNome($tipo) {
                if($tipo == 1) {
                        return $this->nome1;
                } else {
                        return $this->nome2;
                }
        }
}

// opcoes para frontend
$frontendOptions = array (
        'cached_entity' => new Usuario(),
);

// opcoes para backend
$backendOptions = array (
        'cache_dir' => '/phpcache'
);

$cache = Zend_Cache::factory(
        'Class',
        'File',
        $frontendOptions,
        $backendOptions
);

echo $cache->getNome(1) . PHP_EOL;
echo $cache->getNome(2) . PHP_EOL;

Resultado do exemplo acima:

Perceba que estamos chamando o método getNome() através da instância do Zend_Cache e não da instância da classe Usuario. A instância do Zend_Cache funciona como um proxy para a classe Usuario. Na primeira vez que chamarmos o método getNome(1), o cache irá chamar o método original. Nas chamadas subsequentes, o resultado virá do cache. O interessante à observar aqui é que o Zend_Cache reconhece os parâmetros passados para os métodos. Portanto getNome(1) será armazenado separadamente de getNome(2) dentro do cache. Inteligente não ?

Conclusão

Realmente me surpreendi com as funcionalidades disponíveis pelo Zend_Cache. É um sistema de cache extremamente flexível, fácil de configurar e muito poderoso. Para se aprofundar mais a documentação oficial do Zend Framework é a melhor opção. Lá você encontrará exemplos de utilização com todos tipos de frontend e backend.

http://framework.zend.com/manual/en/zend.cache.html

Ler Post Completo | Make a Comment ( 2 so far )

Liked it here?
Why not try sites on the blogroll...

%d blogueiros gostam disto: