Personal tools

Skip to content. | Skip to navigation

Sections

Blog

You are here: Home Blog Érico Andrei

Érico Andrei

Posts do blog publicados pelo Cleber

Showing blog entries tagged as: Desenvolvimento

VMODs: O lego do Varnish 3

Posted by Cleber J Santos at 22/08/2011 00:10
VMODs: O lego do Varnish 3

VMODs, ou simplesmente Varnish Modules é, segundo da documentação de modificações, um dos grandes sucessos obtidos na versão 3: "VMODs on the other hand, was an instant success, because they make it much easier for people to extend Varnish with new functionality".

E realmente, é o mesmo que tenho achado, como bem sabemos desde o Varnish 2.1 podemos usar C inline para criar e estender funcionalidades que por padrão o Varnish não trás, e com a chegada dos módulos essa brincadeira tona-se ainda melhor, por tudo que podemos fazer na VCL.

Sabermos ainda que existem coisas que não temos como fazer na VCL, por exemplo: Procurar um número de IP em um arquivo de banco de dados. Usando código C inline até temos como resolver este problema, já que o Varnish nos provê isso, e lá você pode fazer tudo, mas não é uma forma conveniente ou mesmo legível para resolver tais problemas. Eis o lugar onde VMODs entram em cena.

 

O que é a VMOD?

Trata-se de uma biblioteca compartilhada com algumas funções C que pode ser chamado a partir do código VCL.

A interface entre o VMOD o compilador VCL ("VCC") e o tempo de execução VCL ("VRT") é definido em um arquivo de nome vmod.vcc que um script python de nome "vmod.py" que faz todo o trabalho duro

Executando o vmod.py no arquivo vmod.vcc, será produzido dois arquivos, que são: "vcc_if.c" e "vcc_if.h", no qual devemos usar para construir o nosso arquivo de biblioteca compartilhada.

o vcc_if.c até pode ser esquecido em nosso VMOD, mas o vcc_if.h é importante, ele contém os protótipos para as funções que desejamos exportar para a VCL.

Nota: Uma informação importante, você ainda pode dizer ao Varnish em tempo de execução para qual diretório ele deve olhar para buscar os VMODs. 
vmod_dir
Default: ${VARNISH:DIR}/lib/varnish/vmods


Na prática.

Agora que já temos base do que é um VMOD e como ele funciona, vamos aos exemplos :) , estou usando alguns que encontrei na internet então vamos lá:
 
  • 1º Exemplo.
Autor: Martin Blix Grydeland
Descrição: O módulo implementa o "Olá Mundo!", sendo bem pequeno e simples para entender.
Nota: Após instalar o módulo (como instalar em README) basta executar o seguinte trecho de código em sua VCL.
import example;

sub vcl_deliver {
	# Vamos definit o  resp.http.hello para "Hello, World"
	set resp.http.hello = example.hello("World");
}

 

  • 2º Exemplo

Módulo: https://github.com/leed25d/geoip-vmod
Autor: David Newhall
Descrição: Provê a capacidade de retornar a localização geográfica de um endereço IP.
Nota: Após instalar o módulo (como instalar em README) basta executar o seguinte trecho de código em sua VCL.

import geoip;

sub vcl_recv {
   # Definimos um cabeçalho de solicitação X-GeoIP
   # para o geo do solicitante (ou desconhecido).
   set req.http.X-Forwarded-For = client.ip;
   set req.http.X-GeoIP = geoip.country(req.http.X-Forwarded-For)
}

  • 3º Exemplo
Módulo: https://github.com/varnish/libvmod-curl
Autor: Tollef Fog Heen
Descrião: Este vmod é um dos que mais gosto, ele provê o curls para o Varnish, então podemos usar o varnish como um cliente HTTP e buscar cabeçalhos e corpo nos backends.
Nota: Após instalar o módulo (como instalar em README) basta executar o seguinte trecho de código em sua VCL.
 
import curl;

sub vcl_recv {
    curl.fetch("http://example.com/test");
    if (curl.header("X-Foo") == "bar") {
        …
    }
    curl.free();
}

Estes são alguns dos exemplos que podemos seguir para criar nosso próprio VMOD, nota-se que precisamos saber C para isso, algumas idéias de módulos seria usar C + libxml para fazer parse de arquivos XMLs diretamente no Varnish e já manter em cache, ainda com analise de cabeçalho e etc.. Ou Usar o PIL para gerar imagens ou qualquer outra coisa que sua imaginação desejar, você agora tem o poder do C e do Varnish nas suas mãos.
 

Um pouco mais antes de terminar.

Agora que já estamos mais acostumados e empolgados em poder criar VMODs para trabalhar com o Vanrish, veja alguns exemplos do que podemos fazer com o que já existe. 
 
Nota. Lembre-se que é necessário importar o módulo std ou qualquer outro que iremos utilizar, uma única vez e usar em toda a VCL.
 
  • Adicionando o std.collect(), coletamos vários cabeçalhos HTTP para um único cabeçalho.
import std;

sub vcl_recv {
   std.collect(req.http.foo);
}

sub vcl_fetch {
   std.collect(beresp.http.bar);
}
  • Retornando uma URL em caixa alta ou uma string.
sub vcl_deliver {
        set resp.http.foo = std.toupper(req.url);
}
ou
set beresp.http.x-scream = std.toupper("yes!");
  • Retorna o contrário do toupper, ou seja, strings todas em caixa baixa.
set beresp.http.x-nice = std.tolower("VerY");

Ainda temos random, log, set_up_tos, syslog, fileread, duration e integer, no qual adoraria escrever sobre, mas fica a dica para quem desejar conhecer, o VMOD é realmente uma verdadeira caixa de legos, e o mais legal é que você ainda pode criar novas peças e encaixar nas já existentes. Espero que tenha sido u bom post para você entender e começar a montar a sua VMOD, e espero que post aqui sobre a experiência.

Até a próxima.


Leia também:

| Comentários

Plone 4, velocidade e Chameleon tudo em comum.

Posted by Cleber J Santos at 14/07/2011 14:30
Plone 4, velocidade e Chameleon tudo em comum.

Num post anterior escrito pelo amigo simplificador @Tamosauskas (Plone mais rápido com Chameleon), foi mencionado a preocupação e empenho que a comunidade Plone tem tido quando o assunto é desempenho. Pois bem, neste post pretendo reforçar este aspecto, lembrando que essa é umas das preocupações da comunidade, tenho também como maior delas a segurança é claro.

Como dito no post do @Tamosauskas, a cada nova versão do Plone percebemos um ganho de desempenho, desde a versão 2.5 até a mais atual em desenvolvimento 4.1rc3 (Atual até a data que estou escrevendo este post), e claro, ganho de novas funcionalidades mudanças significativas para  criação de novos produtos e tipos e a mudança da skin padrão.

O que exatamente é o tal do Chameleon?

No site oficial a melhor definição é "Chameleon is an open-source template engine written in Python.
", de fato, trata-se de um modelo de templates escrito em Python, ele foi escrito para gerar documentos de marcação HTML ou XML para aplicações Web.

Ele usa a linguagem do Page Template, só que sua implementação é bem mais rápida e independente, no qual trás um conjunto de novos recursos e podemos usar em qualquer aplicação escrita em Python (2.5 e superior, incluindo 3.x e PyPy), algumas de suas características são:
 
  • Rápido - Os templates são compilados para byte-code.
  • Extensível - É fácil de estender uma linguagem ou criar sua própria.
  • Testado - Testes automatizados que protege contra regressões.
 
Para o Python 2.7 e superior não existem dependências de bibliotecas, já nas versões 2.5 e 2.6 a ordereddict e unittest2 são pacotes definidos como dependências, mas para se ter uma idéia de como Chameleon é independente, seu sistema de tradução é plugável e baseado em gettext. 
 
Não há um suporte embutido para o pacote zope.i18n. Mas se o pacote for instalado, ele será usado por padrão. O pacote translationstring[3] oferece algumas das mesmas classes de utilidades auxiliares, sem a interface do Zope.
 

Usando Chameleon no seu buildout.

Adicione as linhas em seu buildout:
eggs = ... five.pt>=2.1
zcml = ... five.pt
Estes testes foram efetuados nas versões 4.0.7 e 4.1rc3 do Plone, para um teste simples crie um Page template e coloque o seguinte conteúdo:
 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
      xmlns:tal="http://xml.zope.org/namespaces/tal"
      xmlns:metal="http://xml.zope.org/namespaces/metal"
      xmlns:i18n="http://xml.zope.org/namespaces/i18n"
      lang="en"
      metal:use-macro="context/main_template/macros/master"
      i18n:domain="plone">
 <body>
  <metal:main fill-slot="main" tal:define="name string:world">
   Hello ${name}!
  </metal:main>
 </body>
</html>
 
Note que não precisei colocar tal:content para imprimir o texto da variável name, abaixo mais 2 exemplos:
 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
      xmlns:tal="http://xml.zope.org/namespaces/tal"
      xmlns:metal="http://xml.zope.org/namespaces/metal"
      xmlns:i18n="http://xml.zope.org/namespaces/i18n"
      lang="en"
      metal:use-macro="context/main_template/macros/master"
      i18n:domain="plone">

 <body>
  <metal:main fill-slot="main">
   <div tal:replace="python:'here==context:'+str(here==context)" />
   <div tal:replace="python:'here==container:'+str(here==container)" />
   <div tal:replace="string:root:${root/getPhysicalPath}" />
   <div tal:replace="string:nothing:${nothing}" />
   <div tal:define="cgi python:modules['cgi']"
        tal:replace="python: dir(cgi)" />
  </metal:main>
 </body>
</html>
 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
      xmlns:tal="http://xml.zope.org/namespaces/tal"
      xmlns:metal="http://xml.zope.org/namespaces/metal"
      xmlns:i18n="http://xml.zope.org/namespaces/i18n"
      lang="en"
      metal:use-macro="context/main_template/macros/master"
      i18n:domain="plone">

 <body>
  <metal:main fill-slot="main">
    <table border="1">
      <tr tal:repeat="row python:['apple', 'banana', 'pineapple']">
        <td tal:repeat="col python:['juice', 'muffin', 'pie']">
           ${row/capitalize} ${col}
        </td>
      </tr>
    </table>
  </metal:main>
 </body>
</html>
Para realizar outros testes e aproveitar bem o Chameleon, leia a documentação[1] e sugiro a leitura dos códigos dos produtos Chameleon e five.pt.
 

| Comentários

Buildout, para o que der e vier Parte 2

Posted by Cleber J Santos at 28/06/2011 18:03
Em um post anterior mostrei que podemos utilizar o buildout para instalar praticamente qualquer aplicação que desejarmos, seja ela compilada ou não.
      Como no caso do WordPress, no qual se trata apenas de um pacote compactado e que exige a alteração de seus arquivos de configuração, e também a compilação do aplicativo spawn-fcgi, vale lembrar que caso desejado poderia até compilar o próprio PHP.
 
Neste post pretendo dar continuidade na instalação do ambiente, mostrando como compilamos o servidor Nginx para servir as páginas em PHP, ou em nosso caso, servir o WP, também iremos instalar o Supervisord (Sistema cliente/servidor que permite monitorar e controlar número de processos em sistemas operacionais UNIX-like.)

O buildout.
[buildout]
parts =
    ...
    supervisor
    nginx-build
    nginxctl
    default-server-config

...


[nginx-build]
recipe = zc.recipe.cmmi
url = http://nginx.org/download/nginx-1.0.4.tar.gz
extra_options =
    --with-http_gzip_static_module
    --with-http_stub_status_module
    --with-http_dav_module
    --with-http_ssl_module
    --with-http_flv_module
    --http-client-body-temp-path=${buildout:directory}/tmp
    --http-proxy-temp-path=${buildout:directory}/tmp/proxy
    --http-fastcgi-temp-path=${buildout:directory}/tmp/fastcgi
    --with-md5-asm --with-md5=/usr/include
    --with-sha1-asm
    --with-sha1=/usr/include
    --with-http_realip_module

[nginxctl]
recipe = gocept.nginx
nginx = nginx
configuration =
    daemon off;
    worker_processes 1;

    events {
        worker_connections  1024;
    }

    http {
        include            ${nginx:location}/conf/mime.types;
        default_type       application/octet-stream;
        sendfile           on;
        keepalive_timeout  65;

        include ${buildout:directory}/etc/nginx.conf;
    }


[default-server-config]
recipe = collective.recipe.template
input = ${buildout:directory}/etc/nginx.conf.in
output = ${buildout:directory}/etc/nginx.conf


[supervisor]
recipe = collective.recipe.supervisor
logfile = ${buildout:directory}/var/log/supervisord.log
logfile-backups = 10
loglevel = info
pidfile = ${buildout:directory}/var/supervisord.pid
plugins = superlance
user = admin
password = secret
port = 9001
programs =
	10 fcgi  ${buildout:directory}/parts/fcgi/bin/spawn-fcgi [ -a 127.0.0.1 -p 53217 -P ${buildout:directory}/tmp/fastcgi-php.pid -- /usr/bin/php-cgi] true
	20 nginx ${buildout:directory}/parts/nginxctl/sbin/nginx [ -c ${buildout:directory}/parts/nginxctl/nginxctl.conf] true
Pois bem, adicionamos mais 4 seções, e antes mesmo de continuar, vamos aos detalhes. No post anterior criamos uma pasta com o nome de tmp, agora note que na seção [nginx-build], indicamos alguns diretórios a serem usados pelo Nginx, que são: proxy e fastcgi.

Então crie estes dois diretórios e vamos seguir em frente, também teremos que criar dentro do diretório etc um arquivo com o nome nginx.conf, este contém as configurações para rodar-mos o WP, abaixo o conteúdo deste arquivo.
 
server {
    listen 80;
    server_name *.meusite.com;
    rewrite ^ http://www.meusite.com$request_uri permanent;
}

server {
        location / {
                root /home/cleber/buildout/wordpress;
                index  index.php index.html index.htm;
                fastcgi_index   index.php;

                # this sends all non-existing file or directory requests to index.php
                if (!-e $request_filename) {
                        rewrite ^(.+)$ /index.php?q=$1 last;
                }

                autoindex on;
        }

        location = /favicon.ico {
                empty_gif;
                log_not_found off;
                access_log off;
        }

        # Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
        location ~ /\. {
                deny all;
                access_log off;
                log_not_found off;
        }

        try_files $uri $uri/ /index.php;

        location ~ \.php$ {
            include        /home/cleber/buildout/parts/nginx-build/conf/fastcgi_params.default;
            fastcgi_pass   127.0.0.1:53217;
            fastcgi_param  SCRIPT_FILENAME  /home/cleber/buildout/wordpress/$fastcgi_script_name;
        }
}
 
 Pronto, rode o buildout, e depois você já poderá desfrutar de sua aplicação, o supervisor irá criar um um script no diretório bin da instância, agora você pode startar as aplicações usando o comando:
./bin/supervisord

Nota. Vale lembrar que a porta 80 só pode ser aberta pelo root ou por um usuário com poder igual, neste caso estamos falando que o comando acima deverá ser rodado por um usuário com poderes de sudo ou root.

Até a próxima!

| Comentários

Buildout, para o que der e vier

Posted by Cleber J Santos at 25/06/2011 12:05
Buildout, para o que der e vier

Começo dizendo que durante algum tempo fui assombrado pelo buildout, desde a minha entrada na Simples até alguns meses depois, eu tremia sempre que eu tinha de rodar um, a primeira coisa que vinha na cabeça era: "Pronto, agora o ambiente vai ser destruído :(".

Trabalhar com alho no pescoço, pé de coelho e até mesmo trevo de 4 folhas não estava em meu escopo de trabalho, e não é muito meu tipo, pois bem, depois de algumas brigas decidi me tornar o melhor amigo do buildout, após alguns copos de café, e saindo juntos, decidimos fazer as pazes. 

Hoje posso garantir, que em qualquer situação onde preciso instalar alguma aplicação que vá ou não rodar com o Plone, penso no meu amigo buildout.

Duas pessoas que me tiraram esse medo e me deram coragem foi o amigo e inesquecível Dorneles, e também o amigo Érico

E agora a novidade é que não vou falar de como instalar Plone usando buildout, isso tudo para poder mostrar todo o poder do buildout, caso não saiba ainda do que estou falando acesso em http://www.buildout.org/docs/tutorial.html.

Buildout

  • É simples de usar e de manter se você fizer configurações simples e legíveis.
  • Trabalha com eggs.
  • Evita conflitos com os pacotes instalados no site_packages.
  • Evita a instalação diretamente no Python do sistema.
  • Instala dependências a partir das definições dos eggs.
  • Podemos instalar por exemplo:
    • Bancos de dados: PostgreSql, Mysql, Oracle e etc...
    • Serviço de autenticação como o LDAP.
    • Aplicações como: Versões diferentes de Python, Varnish,Squid, Supervisor e etc..
    • Frameworks: Django, Web2Py, Zope
    • CMS: Plone, WordPress e etc..
    • Servidores web: Apache, Nginx e etc...
    • E etc...
Vamos manter as coisas simples, então crie um diretório chamado mybuildout, dentro deste diretório crie a seguinte estrutura de pastas:
 
mybuildout
|- tmp
|- etc
|- src

Essa não é uma estrutura requerida pelo buildout, mas gosto de montar assim, garantindo que qualquer arquivo temporário vá ficar em
tmp por exemplo, arquivos de configurações em etc e aplicações em desenvolvimento em src, dois arquivos são requeridos, são eles: bootstrap.py e buildout.cfg.

Podemos não usar o buildout.cfg e montar o ambiente com outros aquivos, mas isso não vem ao caso, vamos a um exemplo do não uso do Plone, e para não dizerem que não gosto de PHP, iremos instalar o WordPress, então vamos lá.

NOTA. A instalação a seguir foi feita no sistema operacioal Linux (Ubuntu) sendo assim, não garanto que funcione no Windows, mas sim, temos como fazer funcionar da mesma forma no Windows e outros sistemas operacionais.

Também estou partindo do ponto que já temos php instalado no sistema, não quero ter que ficar compilando no buildut o PHP, ainda que dê claro ;)

Comento o buildout logo abaixo.

Instalando o WordPress usando Python, ironia?

[buildout]
parts =
    fcgi
    wp

[wpconf]
wpversion = latest.tar.gz
mydb_name = wp 
mydb_user = wp
mydb_pass = wpnginx
mydb_charset = utf8
mydb_host = localhost

[downloads]
wp_url = http://wordpress.org/${wpconf:wpversion} 
fcgi_url = http://www.lighttpd.net/download/spawn-fcgi-1.6.3.tar.gz

[ports]
fastcgi = 53217

[fcgi]
recipe = zc.recipe.cmmi
url = ${downloads:fcgi_url}
configure-options = 
    --prefix=${buildout:directory}/parts/fcgi

[wp]
recipe = plone.recipe.command
command =
    chmod 600 .installed.cfg
    if [ ! -f ${buildout:directory}/${wpconf:wpversion} ]; then wget ${downloads:wp_url}; fi
    tar xzf ${wpconf:wpversion} 
    cp ${buildout:directory}/wordpress/wp-config-sample.php ${buildout:directory}/wordpress/wp-config.php
    ln -dfs ${buildout:directory}/wordpress ${buildout:directory}/var/www/wordpress
    sed -i "s/define('DB_NAME', 'database_name_here')/define('DB_NAME', '${wpconf:mydb_name}')/" ${buildout:directory}/wordpress/wp-config.php
    sed -i "s/define('DB_USER', 'username_here')/define('DB_USER', '${wpconf:mydb_user}')/" ${buildout:directory}/wordpress/wp-config.php
    sed -i "s/define('DB_PASSWORD', 'password_here')/define('DB_PASSWORD', '${wpconf:mydb_pass}')/" ${buildout:directory}/wordpress/wp-config.php
    sed -i "s/define('DB_HOST', 'localhost')/define('DB_HOST', '${wpconf:mydb_host}')/" ${buildout:directory}/wordpress/wp-config.php
    sed -i "s/define('DB_CHARSET', 'utf8')/define('DB_CHARSET', '${wpconf:mydb_charset}')/" ${buildout:directory}/wordpress/wp-config.php
    chmod +x ${buildout:directory}/bin/spawn-fcgi
update-command = ${wp:command

Criei duas seções que servirá para instalar o WordPress e um script de inicialização do php-cgi, este script também vem quando instalamos o servidor lighttpd, que é uma forma de manter o php vivo enquanto podemos dar um restart ou reload no servidor lighttpd, mas isso não vem ao caso.

Também criamos  3 outras seções que são:

wpconf - > Colocamos aqui as configurações do nosso WP, como dados da base de dados [usuário, senha etc ] e a versão que desejamos instalar do WP.
downloads -> Urls das aplicações, WP e fcgi.
ports -> Configuração da porta no qual o fcgi irá rodar

Note que na seção [wp], usei alguns comandos para fazer a mágica acontecer, quero baixar e descompactar o tar.gz, lembrando que em casos de arquivos zip, será necessário alterar a linha.  Após descompactar copiamos o arquivo wp-config-sample.php para wp-config.php, este será o que o Wp irá ler.

E por fim, setamos os dados de acesso ao bando de dados neste arquivo de configuração.

Rode o bootstrap e o buildout: python bootstrap.py && ./bin/buildout -Nvvv -t 30

Ao final teremos o o Wp instalado e pronto pra usar, é claro que faltam detalhes como instalar o servidor Apache ou Nginx, ou um de sua preferência.

Para subir o fcgi você pode executar: 

./parts/fcgi/bin/spawn-fcgi -a 127.0.0.1 -p 53217 -P ./tmp/fastcgi-php.pid -- /usr/bin/php-cgi

A configuração acima, usei com o servidor Nginx, também compilado com buildout, por este motivo adicionei o fcgi, abaixo sugestões de eggs que ajudam nas instalações.

Sugestões.

| Comentários

O sabor de diversas versões Python para Linux e OSX usando o collective.buildout.python

Posted by Cleber J Santos at 24/10/2010 20:50

Aproveitando a onda dos Buildouts, agora você pode instalar versões do interpretador Python (2.4, 2.5, 2.6, 2.7 e 3.1) no sistema *UNIX ou OSX, e assim melhor trabalhar com seus projetos de Buildout sem medo de ser feliz.

O sabor de diversas versões Python para Linux e OSX usando o collective.buildout.python | Comentários

Read More…

Document Actions
Spinner