IPv6, C-Blocks e como isso afeta o SEO

IPv6
IPv6

Você provavelmente já ouviu falar sobre IPv6, mas ainda pode permanecer um um pouco confuso sobre os detalhes do que é, como funciona e o que ele significa para o futuro da Internet. Este artigo lhe dará uma rápida introdução ao IPv6, e discutirá as implicações sobre SEO que podem resultar em roll-out de IPv6 (mais especificamente sobre o conceito de C-Blocks).

Breve introdução a endereços IP(v4) e C-Blocks

Você já deve estar familiarizado com endereços IP; eles são geralmente escritos no seguinte formato:

ip-1

Esse formato de endereço IP é o formato comum em uso mundialmente em todos os lugares, e é chamado de IPv4. Há quatro bytes em um endereço IP escrito dessa forma, com cada byte separado por um ponto (o que significa 32 bits no total, para os geeks). Todos os domínios e subdomínios são resolvidos com pelo menos um desses endereços IP (um mesmo domínio pode ter vários IPs, mas vamos ignorar isso por enquanto).

Agora, o conceito principal de SEO originado da ideia de C-Blocks (isso não deve ser confundido com a classe C de IPs; uma coisa diferente e que as pessoas muitas vezes confundem com C-Blocks), que é um conceito que tem girado em torno do SEO por uma década ou mais. De forma simples, a ideia é que, se os primeiros 3 bytes do endereço IP são idênticos, então devemos considerar que os dois endereços IP abaixo estão na mesma C-Block:

ip-2

Então, por que isso é interessante para nós? Por que isso é importante para SEO? A lógica que aprendemos em um passado não tão distante é que se você tiver dois IPs que estão na mesma C-Block, os sites pertencentes a esses IPs provavelmente estarão relacionados e, portanto, as ligações entre esses lugares (em média) não devem contar muito em termos de PageRank. Minha opinião pessoal é que hoje existem muitos outros meios disponíveis no mecanismo do Google para fazer essas conexões, e por isso a questão do C-Block é bem menos importante do que já foi um dia.

Assim, como podemos ver (surpresa!), os dois endereços IP acima são realmente relacionados:

ip-3

Com certeza esses dois IPs são de duas empresas na família da Disney. Faz algum sentido que os laços entre esses dois domínios existam, mas isso não deve indicar um padrão como no caso de links de sites similarmente grandes, mas independentes.

Apresentando o IPv6

Então, há um problema com os endereços IP no formato acima (IPv4); há “apenas” 4 bilhões deles, e nós temos essencialmente esgotado o fornecimento desse tipo de IP. Temos tantos dispositivos conectados atualmente, que os criadores do IPv4 nunca imaginaram, na época, que a vastidão da Internet seria tão grande dali a 30 anos. Por sorte, eles viram o problema logo no início e começaram a trabalhar em um sucessor, o IPv6 (o IPv5 acabou sendo utilizado para outro protocolo inédito).

Formato de endereço IPv6:

Os endereços IPv6 são muito mais longos do que os endereços IPv4, e o formato se parece com isto:

ip-4

As coisas ficaram sérias! Há agora 8 blocos em vez de 4, e em vez de cada bloco possuir 1 byte (antes representados como um número 0-255), cada bloco é representado por quatro caracteres hexadecimais. Há 128 bits em um endereço IPv6, ou seja, em vez de um mísero 4000000000 como IPv4, o IPv6 tem cerca de 340.000.000.000.000.000.000.000.000.000.000.000.000 endereços.

Nos próximos anos, vamos adentrar em um mundo no qual centenas de dispositivos em nossas casas serão capazes de possuir rede e precisarão de um endereço IP, o que o IPv6 vai ajudar a acontecer. No entanto, também surgindo os sites que começam a usar endereços IPv6 cada vez mais comumente e, daqui a alguns anos, vamos começar a ver sites que possuem apenas um endereço IPv6.

Notação CIDR

Antes de irmos adiante, é importante introduzir um conceito valioso para a compreensão de endereços IP, que é chamado notação CIDR.

O protocolo IPv6 utiliza exclusivamente a notação CIDR (por exemplo /24), então a comunidade de SEO precisa entender esse conceito. É muito simples, mas normalmente muito mal explicado.

Como dissemos, os endereços IP no formato IPv4 têm 32 bits de comprimento, por isso podemos olhar para o endereço IP abaixo como binário:

ip-5

Coloquialmente, a notação CIDR poderia ser descrita como um modelo para descrever um grupo de endereços IP intimamente relacionados, de uma maneira semelhante à forma como um C-Block funciona. Ele é representado por um número após a barra ligado a um endereço de IP parcial (por exemplo, 199.181.132/24), que indica que o número dos bits iniciais (dígitos binários) são idênticos. O CIDR é tão flexível que poderia ser usado para descrever um C-Block como /24, porque os primeiros 24 bits (3 grupos de 8 bits) do endereço são os mesmos:

 

ip-6

Dois endereços IP no mesmo C-Block. Os primeiros 24 bits (3 blocos de 8 bits) são idênticos. Isso pode ser representado, nesse caso, por 199.181.132 / 24.

Agora, a notação CIDR é mais refinada e mais precisa do que o conceito de C-Block. No exemplo acima, os dois endereços IP não estão apenas no mesmo C-Block, eles estão ainda mais estreitamente relacionados no que diz respeito aos 6 bits no último bloco, que também são idênticos. Na notação CIDR, poderíamos dizer que esses dois endereços IP estão no bloco de 199.181.132/30, para indicar que os 30 principais bits são idênticos.

Observe que, com o CIDR, quanto menor o número após a barra, mais endereços IP caberão em um bloco (porque estamos dizendo que menos bits principais devem ser idênticos).

IPv6 & C-Blocks?

A notação CIDR/24 não é exatamente um nome atraente, e assim criou-se o nome “C-Block” para tornar isso mais fácil de falar, mas não se estende tão facilmente para o IPv6. Então, a pergunta é: podemos generalizar algo semelhante?

O C-Block, do ponto de vista do Google e da perspectiva do SEO, serve apenas para identificar se os links são originários da mesma rede ISP. Assim, obviamente, esse deve ser o foco. Então, meu melhor palpite seria focar em como esses IPs são alocados pelos ISPs (provedores normalmente obtêm grandes blocos contínuos de endereços IP que podem ser usados nos sites de seus clientes).

Em IPv4, um ISP possuiria determinadas faixas de C-Blocks e, se você pudesse ver vários links provenientes do mesmo C-Block, isso implicaria que os sites foram hospedados juntos e que haveria uma chance muito maior de que eles estivessem de alguma forma relacionados.

ip-7

Ilustração de um “ISP Block” (/32); a parte azul do endereço é estável e indica o ISP. A parte vermelha pode mudar e representa os endereços daquele ISP.

Com o IPv6, acredito que os ISPs serão dados de /32 blocos (os principais blocos de 32 bits serão os mesmos, deixando 96 bits para criar endereços para seus clientes), que, em seguida, vão atribuir seus usuários em blocos de /64 (perguntei a algumas pessoas, e essa tende a ser a tendência para o futuro, mas li que isso pode às vezes ser composto por blocos de /48 bits). Observe que os ISPs têm agora uma ordem de magnitude muito maior, contendo muito mais endereços IP (cada) do que toda a Internet tinha antes!

Isso também significa que cada usuário final vai usar mais endereços IP em seus dispositivos ou em sua própria rede do que o total de endereços IP na versão IPv4. Bem-vindo à Internet das Coisas!

Esses ISPs podem estar servindo os usuários domésticos de modo que cada usuário poderá receber um bloco de endereços IPv6 (para os técnicos: IPv6 acabará com a necessidade de uso do NAT em sua maior parte – já que todos os dispositivos de um usuário terão um IP “real”). Em outro cenário, o ISP será útil para os servidores, para os quais será atribuído um bloco /64; esse é o caso que nos interessa.

ip-8

Ilustração de um “Block Cliente” (/64); a parte azul indica um cliente em particular. A parte vermelha pode mudar e representa endereços pertencentes a esse cliente.

O equivalente a um C-Block em IPv6 seria um bloco /32 porque é isso que um ISP geralmente atribui aos clientes (o que lhes permite então liberar mais de 4 bilhões de blocos /64 bits para seus usuários).

Além disso, no IPv6, a alocação mínima é de /32 blocos, porque um único bloco de /32 não pode ser executado em vários ISPs, sendo assim, não há como dois IPs na mesma faixa de /32 blocos pertencerem a dois ISPs diferentes. Se queremos saber se os sites estão realmente relacionados a dois locais aleatórios, saber que eles estão no mesmo ISP (que é o que o C-Blocks faz) é o nosso objetivo.

Além disso, caso um ISP tenha blocos de /64, terá à disposição 4 bilhões de endereços para distribuir, e essa quantidade é muito escassa para identificar associações entre os sites em blocos diferentes.

No entanto, existe um contra-argumento aqui. Note que um único servidor com um bloco de IPs /64 significa que cada site deve ter um endereço IPv6 diferente (mesmo que compartilhe um endereço IPv4).

Uma observação geek: de fato, o cabeçalho “host” do http aceita um endereço IPv6 para distinguir qual site hospedado em um servidor é o site que você deseja.

Dessa forma, um único servidor, com vários sites, terá um IP separado para cada um desses sites (também é possível que o servidor possua vários blocos IPv6 atribuídos, um para cada cliente diferente – e eu acho particularmente que essa é realmente a intenção e espero que se torne realidade).

Então, se estou acessando uma rede de sites que estão interligados uns com os outros, então é bem provável que, se tenho somente um único servidor de hospedagem, todos esses sites estão no mesmo bloco /64 de endereços IPv6. Isso deve ser um sinal muito forte de que os sites estão interligados. No entanto, estou bastante certo de que aqueles ISPs que tentam manipular isso vão tentar evitar esse cenário e acabarão tentando criar outro bloco de endereços para cada site. Mas se eles estão hospedados com o mesmo ISP, então ainda estarão no mesmo bloco /32, pelo menos.

Recomendações de uma rede IPv6

Para redes IPv6 mais bem sucedidas, sugiro:

  • Os sites que estão no mesmo bloco/32, que antes seria equivalente ao mesmo C-Block, permanecem onde estão.
  • Sites no mesmo bloco /64, quer estejam no mesmo servidor ou pertençam a um mesmo cliente, ainda estão relacionados no mesmo nível C-Block.

 

Estes sites precisam de nomes mais acessíveis e mais fáceis, como:

  • “ISP Block” para blocos /32.
  • “Block Cliente” para blocos /64.

 

Então, seríamos capazes de dizer que:

  • Em endereços IP da categoria IPv6 presentes no mesmo ISP, os blocos assemelham-se à relação de IPs na mesma C-Block em IPv4.
  • Em endereços IP da categoria IPv6 no mesmo bloco de usuários, provavelmente muito semelhante, pertencem à mesma pessoa ou organização.

 

Lições aprendidas
Como mencionei, não estou convencido de que C-Blocks em IPv4 sejam tão importantes do ponto de vista do Google como já foram um dia, uma vez que o Google utilizava esse recuso para identificar e vincular sites. Embora ainda seja útil como um substituto para o SEO, que não têm todos os recursos de um Google, não é algo que deva orientar a sua tomada de decisão. Se você estiver executando sites legítimos, não deverá se preocupar em hospedá-los no mesmo C-Block, já que o site poderá ser manipulado pelo Google (que vai trabalhar com os dados dos IPs, seja no formato em que estiverem, de qualquer maneira).

Com o IPv6, acho que os “Customer Blocks” podem ser um recurso de SEO muito importante, pois é uma relação ainda mais próxima com o que era o antigo C-Block, e isso é algo que o Google provavelmente irá usar. Ainda vai levar um tempo até que o IPv6 torne-se predominante suficiente para que tudo isso seja de fato importante, portanto, neste momento, é apenas algo a ter em seu radar para ficar por dentro quando o Google começar a aumentar a importância do IPv6 no SEO ao longo dos próximos dois anos.

—–

Artigo de Tom Anthony, publicado originalmente no iMasters.

Tunning de solução Java Web

solução
Imagem ilustrativa

Segue abaixo um relato resumido de uma das minhas consultorias para uma empresa que tinha uma solução web feita em Java que estava apresentando travamento e tempo de resposta ruim. O objetivo com esse artigo é apresentar os problemas encontrados na solução e as medidas adotadas de otimização, de forma com que outros profissionais possam aprender com os fatos e ou reutilizar as estratégias encontradas.

1. Otimização de acesso ao SGDB

Fizemos uma triagem da quantidade de acessos que o sistema faz ao sgdb quando um usuário acessa os principais processos. O resultado foi 117 round-trips. Após estudos e otimizações, reduzimos para 41 nos mesmos processos. Foi uma redução de 65%! Dado que o número de acessos diário dessa solução é de +- 7 mil – isso que dizer que reduzimos por dia (117 – 41 = 76 * 7.000) 532 mil acesso ao sgdb. Essa otimização, além de aumentar o tempo de resposta, reduziu drasticamente o número de conexões do DataSource e a quantidade de parse de framework ORM, o que resultou em menos gastos com HEAP.

2. Otimização de auditoria

O sistema usa uma tabela de logg que registra toda a auditoria de seus processos no qual tem uma coluna auto incrementável manual com uma chave composta, que por sua vez resulta em algumas consequências negativas:

Para evitar inconsistências de concorrência nos MAXID + 1 para inserir registro, o sistema sincroniza a concorrência em todos os processos, deixando a execução da solução em modo “MONO” usuários.
Para cada novo registro de logg, o sistema é obrigado a fazer + 1 acesso ao sgdb para pegar o próximo MAXID + 1 a ser gravado.
Após estudos e otimizações, resolvemos ambos os problemas criando um nova tabela de logg contendo a mesma estrutura, só que utilizando o conceito de UUID como chave primária. O resultado foi que para cada novo registro de auditoria não é mais necessário acessar o sgdb para buscar o próximo MAXID + 1, uma vez que o UUID é gerado pela própria solução. Usando a mesma média de acesso diário já indicada acima, reduzimos + 7 mil acessos ao sgdb por dia. A partir dessa medida, foi possível retirar todas as sincronizações das operações de auditoria, fazendo com que eles pudessem ser executados de forma agora 100% concorrentes.

3. Auditoria assíncrona

O sistema faz registros de loggs com características somente de acesso, não sendo processos idempotentes. Do ponto de vista arquitetural, não faz sentido o usuário final esperar estes registros de loggs acontecer enquanto navega na solução. Com isso,  foi elaborada uma nova arquitetura de logg assíncrona específica para estes processos, no qual o sistema faz uso de threads separadas que vão registrando os loggs, sem fazer o usuário pagar o tempo de espera na resposta da sua requisição HTTP.

4. Índices de acesso

Depois de averiguações, foi constatado que as tabelas do sistema estão sem nenhum índice, fazendo com que o sgdb busque os registros originários das consultas do sistema (WHERE) 100% sequencial. Com base em todas as consultas existentes, foi criado uma API de índices que promova melhor performance nas consultas das tabelas, conforme descrito no livro oficial do provedor do sgdb. Foram criados exatamente 63 índices.

5. Evitando bloqueios pessimistas

O sistema faz acesso constante a um banco de dados de uma outra solução legada da década de 90, que por sua vez, utiliza-se do conceito de bloqueio pessimista para assegurar a consistência nas concorrências de seus processos. Em virtude disso, esse sistema sofre intensivo bloqueio, não conseguindo acessar as tabelas dessa outra solução e ocasionando diversas paradas diárias sentidas constantemente pelos usuários finais. Para contornar isso, aplicamos o nível de isolamento das consultas do sistema para READ_UNCOMMITED que faz leituras das tabela independente dos bloqueios existentes. Os únicos lugares que tivemos que manter o nível READ_COMMITED é nas operações de processos de negócios. Como hoje o sistema é praticamente 70% de consultas e 30% de operações de negócios transacionais, o usuário final com essa nova otimização não ficará mais  impedido de acessar e consultar informações quando existir bloqueios pessimistas. Isso reduzirá drasticamente a maioria das reclamações.

6. Otimização de filtro NO-CACHE

Depois de averiguações, foi constatado que a solução faz uso de um filtro servlet para decorar recursos web como “no-cache” HTTP. Nesse controle, encontramos o uso de operação de substring() e contains() da classejava.lang.String. Para otimizar, foi utilizado o recurso de expressão regular, juntamente com a classe java.lang.Match que funciona bem mais rápido na procura de padrões de texto. Com base na mesma média de acesso diário já indicada acima e que em cada requisição HTTP o filtro é executado +- 6 vezes, essa otimização deixou a tempo de resposta bem melhor.

7. Mensurando as otimizações

Para podermos quantificar as melhorias das otimizações, foi feita uma amostra de teste usando nas seguintes configurações SEVIDOR LINUX, JAVA7, TOMCAT 6 com 1GB HEAD, ferramenta de testes JMETER e usando um sgdb remoto de homologação, executando os principais cenários de processos utilizados pelos usuários. Segue um resumo das estatísticas do resultado:

Versão do sistema atual, rodamos os testes usando a versão atual da sistema:

  • 1 usuário demorou 6 segundos para executar todo o script de testes.
  • 500 usuários simultâneos demoraram 6:10 minutos para executar todo o script de testes.

 

Versão do sistema otimizada, rodamos o mesmos testes e usando uma versão com todas a otimizações:

  • 1 usuário demorou 4 segundos para executar todo o script de testes –33% MAIS RÁPIDO!
  • 500 usuários simultâneos demoraram 2 :38 minutos para executar todo o script de testes – 66% MAIS RÁPIDO!

 

Depois de dois meses de muito trabalho, conclui-se que o resultado final foi positivo e muito expressivo. Vale destacar aqui que as otimizações só foram possíveis de serem aplicadas uma vez que a solução estava devidamente arquiteturada em camadas, seguindo corretamente a filosofia do DDD, e porque utilizada gerenciamento de transações automáticas via AOP com o framework Spring Transaction. Caso contrário, ficaríamos impedidos de fazer qualquer tipo de alterações, levando a empresa contratante ao caminho tortuoso da reescrita total da solução.

Para os interessados nesse tipo de assunto, veja minha regrinha de bolo de otimização que qualquer um pode reusar como ponto inicial para esse tipo de atividade.

Até a próxima!

—–

Artigo de Fernando Franzini, originalmente publicado no iMasters.

Formulário de contato com Laravel

Laravel
Laravel

Olá, pessoal! Hoje vou falar sobre como montar, de forma fácil, um formulário de contato em seu site usando o Laravel 4.1.

Em meu site, precisei colocar um formulário de contato para que as pessoas que acessam o site possam entrar em contato, seja para solicitar os serviços, ou para dar opinião, criticar… Enfim, ter uma forma de entrarem em contato comigo.

A princípio, tentei fazer o envio usando SMTP autenticado. Localmente, funcionou perfeitamente, mas quando enviei para meu servidor remoto, não funcionou (o Server bloqueou o envio por segurança. Ainda estou resolvendo isso). Mas no servidor remoto, consegui fazer o envio usando como tipo de envio a função mail() do PHP.

Para começar, criei duas rotas, uma para o método GET e outra para o método POST:

1Route::get('contato', array('as' => 'contato', 'uses' =>'HomeController@contato'));
2Route::post('contato', 'HomeController@postContato');

Agora, vamos criar a view responsável pelo formulário:

1/app/views/pages/contato.blade.php
2{{ Form::open(array('action' => 'HomeController@contato', 'role' => 'form')) }}
3{{ Form::label('nome', 'Nome', array('class'=>'control-label')) }}
4 {{ Form::text('nome', null, array('placeholder'=>'Seu nome...', 'class'=>'form-control')) }}
5{{ Form::label('email', 'E-mail', array('class'=>'control-label')) }}
6 {{ Form::text('email', null, array('placeholder'=>'Seu e-mail...', 'class'=>'form-control')) }}
7{{ Form::submit('Enviar Mensagem', array('class' => 'btn btn-default')) }}{{ Form::close() }}

As classes de formatação que estou usando no exemplo são padrão do Twitter bootstrap, que uso com frequência pela facilidade de uso.

Em meu controller HomeController, criei dois métodos, um para carregar a view e outro para o método POST, para enviar o e-mail.

1public function contato() {
2 return View::make('pages.contato');
3}
4public function postContato() {
5$rules = array( 'nome' => 'required', 'email' => 'required|email', 'texto' => 'required' );
6$validation = Validator::make(Input::all(), $rules);
7$data = array();
8 $data['nome'] = Input::get("nome");
9 $data['email'] = Input::get("email");
10 $data['texto'] = Input::get("texto");
11if($validation->passes()) {
12 Mail::send('emails.contato', $data, function($message) {
13 $message->from(Input::get('email'), Input::get('nome'));
14 $message->to('contato@billjr.com.br') ->subject('Contato Bill Jr.');
15 });
16return Redirect::to('contato') ->with('message', 'Mensagem enviada com sucesso!');
17 }
18return Redirect::to('contato')
19 ->withInput()
20 ->withErrors($validation)
21 ->with('message', 'Erro! Preencha todos os campos corretamente.');
22}

Explicarei agora o que fiz no método postContato():

  • Criei a variável $regras para validar meu formulário;
  • Criei a variável $validation validando meu formulário com o Validator::make(), e usando o Input::all() para trazer todos campos postados pelo formulário;
  • Usando a condição if, verifico se a validação “passou” (if($validation->passes()));
  • Na variável $data, criei um array vazio, depois atribuí o valor de cada campo postado pelo formulário, para facilitar;
  • A seguir, uso o método de envio de email padrão do Laravel, com Mail::send(), e passando os parâmetos from, to e subject.
  • Em $message->from, informo email e nome do contato
  • Em $message->to, informo meu email de contato
  • Em $message->subject, o assunto do meu email de contato

 

Dentro da validação (if($validation->passes)), uso o return Redirect::to() para redirecionar para a página de contato, caso o e-mail tenha sido enviado com sucesso, com uma mensagem de “Sucesso!”.

Após fechar o bloco de código da validação, coloco uma validação com a mensagem de erro, caso o e-mail não tenha sido enviado com sucesso. A mensagem de sucesso exibo dentro do meu arquivo de layout padrão do site, desta forma:

1@if(Session::has('message'))
2 {{ Session::get('message') }}
3@endif

Bom, galera, é isso! Desta forma você pode ter facilmente um formulário de contato em seu site, ou adaptar o script para suas necessidades.

Caso queiram saber mais sobre como enviar e-mails com Laravel, acessem a documentação oficial em: e-mail com Laravel

Até o próximo artigo!

—–

Artigo de Oberaldo Büll Junior, publicado originalmente no iMasters.

WHATWG a HTML5 são apenas uma versão do HTML?

html
HTML

É comum eu me deparar com dúvidas sobre a HTML5, não só em fóruns e listas de discussão, mas também em conversas com meus amigos desenvolvedores em eventos, que muitas vezes têm sua explicação relacionada com a filosofia de desenvolvimento da linguagem.

É um assunto interessante e curioso que vale uma reflexão, por isso escrevi esse artigo.

A filosofia de desenvolvimento de especificações do W3C prevê que uma especificação passe por uma série de estágios não necessariamente finais, pois pode haver volta a um estágio anterior, até que a especificação atinja o status de Recomendação do W3C, do qual não haverá mais volta, pois este é o estágio final e definitivo. O processo inicia-se novamente para uma próxima versão da especificação.

A WHATWG adota a filosofia de desenvolvimento da especificação sem o objetivo de alcançar uma versão final. O processo é contínuo e sempre direcionado para a tecnologia sem a necessidade de rotular cada estágio com um número, pois há somente um estágio, o atual.

Essa diferença de abordagem gerou confusão no processo de desenvolvimento da HTML, pois hoje temos um documento que descreve o desenvolvimento da especificação para a HTML5 e outro para a HTML5.1 no site do W3C e um documento que descreve o desenvolvimento da especificação para a HTML no site do WHATWG.

Para melhor entender o acabamos de dizer, leia a seguir, em tradução livre, duas afirmações retiradas do documento para as especificações HTML do WHATWG.

O termo “HTML5″ é um buzzword para designar as modernas tecnologias para web, muitas das quais (não todas) são desenvolvidas pelo WHATWG. Este documento é dedicado a uma destas tecnologias; outros estão disponíveis e estão relacionados no índice das especificações do WHATWG (http://kwz.me/wm).

Fica claro que para o WHATWG a HTML5 é muito mais que uma versão da HTML. É um conjunto de tecnologias, tais como, DOM, Fullscreen, Web Sockets, WebGL, Storage etc. Ao contrário do que considera o W3C com sua filosofia de especificação versionada e finalizada para a HTML.

Embora nós já tenhamos pedido para eles pararem com essa prática, o W3C continua publicando algumas partes da nossa especificação como uma especificação separada. Existem inúmeras diferenças entre estas especificações e as especificações do W3C; umas pequenas, outras significativas. Infelizmente não há, em lugar algum, um documento listando as diferenças, assim não há como saber quais diferenças são propositais e quais não são.

Sobre esta citação, deixo por conta do leitor concluir o que fica claro, mas aponto um exemplo das diferenças citadas: para o W3C o elemento hgroup não existe e obviamente não consta da sua especificação ao passo que para o WHATWG, aquele elemento consta da especificação em toda sua glória.

Hoje (agosto/2014), a especificação para a HTML5 encontra-se na fase de Candidata a Recomendação e as funcionalidades da linguagem devem ser estudadas baseando-se naquele documento hospedado no site do W3C.

Já existe um Rascunho do Editor do W3C que possivelmente será elevado ao status de Rascunho de Trabalho para as especificações da HTML5.1 – possivelmente a próxima versão da HTML. O documento encontra-se hospedado no site do W3C.

O WHATWG continua desenvolvendo a HTML, mas como dito anteriormente, para aquele Grupo de Trabalho não existe mais uma versão. A especificação encontra-se hospedada no site do WHATWG.

Será que um dia vão fazer as pazes? O que você pensa a respeito? Comente!

Importando múltiplos arquivos texto

multiplos arquivos
Imagem ilustrativa

Faz alguns meses que publiquei aqui nesta coluna um artigo descrevendo alguns problemas comuns com arquivos texto. Separadores de colunas, identificadores de linhas, caracteres “proibidos” etc. Desta vez eu apresento uma solução simples para importação de múltiplos arquivos texto no SQL Server. De quebra, eu uso também um truque muito interessante apresentado por Grzegorz Oledzki para conversão de texto no formato ‘DD-MM-YYYY’ em datas reconhecidas pelo SGBD.

Alternativas de importação

Existem vários comandos e ferramentas que auxiliam na importação de dados. Alguns são simples e práticos, outros mais complexos e robustos. Basta pensar que, em última análise, um comando BULK INSERT, uma operação de DATA FLOW do SSIS e o utilitário BCP fazem a mesma coisa: importam dados.

Eu sou fã da simplicidade do comando BULK INSERT, apesar dele ter limitações importantes. Talvez a mais séria destas limitações seja não suportar arquivos CSV, que são muito comuns quando se trata de importação de dados.

Por outro lado, o comando BULK INSERT oferece uma série de benefícios interessantes. Alguns deles são:

  1. Reforça a validação de tipos de dados;
  2. Valida restrições do modelo (como chaves estrangeiras);
  3. Permite configurar delimitadores de colunas e marcadores de final de linha;
  4. Permite definir a página de códigos, para trabalhar com caracteres diferentes do ASCII;
  5. Controla o fluxo de importação, comitando transações a cada N registros importados;
  6. Permite desabilitar gatilhos que seriam disparados em consequência da inserção dos novos registros;
  7. Permite definição de layouts de importação, essencial nos casos em que o arquivo importado tem número diferente de colunas em relação à tabela de destino;
  8. Permite definir as linhas inicial e final do arquivo de dados, desprezando eventuais cabeçalhos ou rodapés no arquivo importado;
  9. Controla o tipo de “lock” sobre a tabela;
  10. Possibilita cargas de dados em paralelo, aumentando dramaticamente a velocidade do processo;
  11. Dispensa log da operação de carga de dados e, portanto, não tem impacto sobre o “transaction log” da base;
  12. Especifica um arquivo de output para registrar erros da importação.

 

Estudo de caso

Considere que você recebeu uma solicitação especial de um diretor da sua empresa. Ele lhe passou um conjunto de 50 arquivos texto e pediu para importá-los num banco de dados para fazer algumas análises.

Ele fez questão de passar detalhes do seu pedido: todos os arquivos tem o mesmo layout, exatamente a mesma sequência de campos. Usam o mesmo separador de colunas (caractere de tabulação “\t”) e o mesmo identificador de final do registro (caractere de retorno de linha “\n”). Os 50 arquivos recebem nomes sequenciais, que vão de “Arquivo01.txt” a “Arquivo50.txt”.

A primeira linha dos arquivos é sempre um cabeçalho informando o nome dos campos. Porém os cabeçalhos apresentam rótulos diferentes em cada arquivo. E a quantidade de linhas de dados varia de arquivo para arquivo.

As tabelas usadas

O leitor mais atento já percebeu a descrição acima traz detalhes importantes misturados com informações irrelevantes para a sua tarefa. Mas a vida real é assim mesmo. Mesmo quando lida com um usuário com bastante conhecimento técnico, é comum que aconteçam alguns deslizes e ele suponha que alguns detalhes tenham muito mais importância do que de fato tem.

O primeiro detalhe irrelevante é sobre a variação da quantidade de registros entre os arquivos. Isso não nos afeta, até porque as ferramentas de carga de dados já estão preparadas para isso (importação roda até encontrar o marcador de final de arquivo).

O segundo é sobre os cabeçalhos variáveis. O que interessa no processo importação é o número de linhas que serão desprezadas no início de cada arquivo e a sequência das colunas. Se elas são descritas de forma diferente é irrelevante. Como eu disse, estas linhas de cabeçalho são desprezadas.

Não há nenhuma informação sobre campos que devam ser desprezados. Então eu assumo que devo importar todas as colunas do arquivo. Também não há comentário sobre existência de alguma chave nestes dados. Mas como serão feitas análises, é fundamental que seja criado um índice clusterizado nesta tabela.

Tenha em mente que o SQL Server nunca oferecerá boas performances em consultas se não existir um índice clusterizado na tabela. Isso é tão importante que o SQL Server cria automaticamente um índice clusterizado assim que se define a chave primária da tabela.

Portanto a tabela de destino deverá ter uma chave primária. Para isso, eu adiciono um campo IDENTITY nesta tabela. Veja Listagem 1:

Listagem 1: tabela de destino


1CREATE TABLE dbo.tbDestino(
2    DestinoID       int identity(1,1) NOT NULL,
3    TipoPessoa      char(2) NOT NULL,
4    NomeCompleto    varchar(200) NOT NULL,
5    Titulo          varchar(8) NULL,
6    Prenome         varchar(50) NOT NULL,
7    NomeDoMeio      varchar(50) NULL,
8    Sobrenome       varchar(50) NOT NULL,
9    Sufixo          varchar(50) NULL,
10    EmailPromo      int NOT NULL,
11    DataAtualizacao datetime NOT NULL,
12 CONSTRAINT PK_Destino PRIMARY KEY CLUSTERED (DestinoID)
13) ON PRIMARY
14GO

Importante notar que agora temos uma tabela com um campo a mais do que os arquivos. É o campo [DestinoID], chave primária da tabela.

Neste ponto, temos que escolher entre dois caminhos. A primeira opção é criar um arquivo de formatação, especificando o mapeamento dos campos entre os arquivos de origem e a tabela de destino. A segunda é criar uma tabela de carga de dados, normalmente chamada de tabela de staging. Esta tabela teria o mesmo número de campos da fonte de dados e a mesma sequência de campos. Todos os campos da tabela de staging usam o tipo VARCHAR, evitando conversões durante o processo de importação.

Como eu disse, meu objetivo é criar um processo de carga de múltiplos arquivos que seja o mais simples possível e menos suscetível a falha. Por conta disso eu escolho usar a tabela de staging. O script de criação desta tabela é apresentado na Listagem 2.

Listagem 2: tabela de staging


1CREATE SCHEMA staging
2GO
3
4CREATE TABLE staging.tbDestino(
5    TipoPessoa      varchar(2)   NULL,
6    NomeCompleto    varchar(200) NULL,
7    Titulo          varchar(8)   NULL,
8    Prenome         varchar(50)  NULL,
9    NomeDoMeio      varchar(50)  NULL,
10    Sobrenome       varchar(50)  NULL,
11    Sufixo          varchar(50)  NULL,
12    EmailPromo      varchar(50)  NULL,
13    DataAtualizacao varchar(50)  NULL
14) ON PRIMARY
15GO

O script de carga de dados

Agora é necessário tratar do comando BULK INSERT. Um detalhe que sempre causa confusão é que ao usarmos esse comando, devemos especificar um caminho de arquivo conforme ele é especificado no servidor onde roda a instância SQL.

No caso atual, os arquivos estão gravados no diretório ‘C:\TEMP’ do servidor. A  Listagem 3 mostra o comando necessário.

Listagem 3: comando BULK INSERT


1BULK INSERT staging.tbDestino
2FROM 'C:\Temp\Arquivo01.txt'
3WITH (
4    FIELDTERMINATOR ='\t',
5    ROWTERMINATOR = '\n',
6    FIRSTROW = 12
7)
8GO

Temos 50 arquivos para importar e naturalmente seria possível executar esta tarefa repetindo esta instrução para cada um dos arquivos. Porém, o legal de fazer scripts genéricos é que eles podem ser reutilizados numa gama muito grande de situações. “Reusabilidade” é algo muito importante e você deve estar atento a isso quando cria seus scripts.

Este script de importação de múltiplos arquivos é fácil de criar, mas ainda assim pode ser reaproveitado para qualquer importação de arquivos que tenham nomes sequenciais. Basta criar as variáveis adequadas. No caso, eu uso os seguintes parâmetros:

  • Nome do arquivo (@vchArquivo)
  • Extensão do arquivo (@vchArquivoExtensao)
  • Diretório de origem (@vchDiretorioOrigem)
  • Nome completo da tabela de destino (@vchTabelaDestino)
  • Quantidade de arquivos a importar (@intQTDArquivos)
  • Número de linhas de cabeçalho (@intLinhasCabecalho)
  • Separador de colunas (@vchColuna)
  • Identificador de linha (@vchLinha)

 

A instrução inteira precisa ser montada e guardada numa outra variável que então será executada com a instrução EXEC(). A Listagem 4 mostra este script parametrizado de carga de dados.

Listagem 4: script de carga

 

1declare @vchArquivo as varchar(50)
2declare @vchArquivoExtensao as varchar(50)
3declare @vchDiretorioOrigem as varchar(4000)
4declare @vchTabelaDestino as varchar(200)
5declare @intQTDArquivos as integer
6declare @intLinhasCabecalho as integer
7declare @vchColuna as varchar(2)
8declare @vchLinha as varchar(2)
9
10--insercao dos valores iniciais
11set @vchArquivo = 'Arquivo'
12set @vchArquivoExtensao = '.txt'
13set @vchDiretorioOrigem = 'C:\TEMP\'
14set @vchTabelaDestino = 'staging.tbDestino'
15set @intQTDArquivos = 50
16set @intLinhasCabecalho = 1
17set @vchColuna = '\t'
18set @vchLinha = '\n'
19
20-- declaracao de variaveis de controle
21declare @intContador as integer
22declare @vchSQL as varchar(500)
23declare @vchLinhaInicial as varchar(5)
24
25set @intContador = 1
26set @vchLinhaInicial = convert(varchar(5), (@intLinhasCabecalho + 1 ))
27
28
29--limpa tabela de destino
30set @vchSQL = 'truncate table ' + @vchTabelaDestino
31exec(@vchSQL)
32
33while @intContador <= @intQTDArquivos
34    begin
35
36    --define caminho completo para o arquivo de importação
37    set @vchSQL = @vchDiretorioOrigem + @vchArquivo
38        + convert(varchar(3), @intContador) + @vchArquivoExtensao
39
40    --define a instrucao completa do BULK INSERT   
41    set @vchSQL =  'BULK INSERT ' + @vchTabelaDestino
42        + ' FROM ''' + @vchSQL
43        + ''' WITH (FIELDTERMINATOR =''' + @vchColuna
44        + ''', ROWTERMINATOR = ''' + @vchLinha
45        + ''', FIRSTROW = ' + @vchLinhaInicial + ')'
46
47    -- importa o arquivo
48    exec(@vchSQL)
49
50    --identifica o novo arquivo
51    set @intContador += 1
52    end

O script de conversão de tipos de dados

O passo final é a conversão dos dados para os tipos de dados adequados. Eu costumo tratar esta tarefa em separado da carga de dados, porque é praticamente impossível generalizar qualquer tipo de tratamento. A conversão depende essencialmente do layout do arquivo de dados e, portanto, não há como generalizá-la sem restringir o layout considerado.

Neste estudo, o layout envolve campos VARCHAR na maioria dos casos. Existem apenas três exceções:

  • Campo TipoPessoa, usando CHAR(2)
  • Campo EmailPromo, que tem valores tipo INTEGER
  • Campo DataAtualizacao, com tipo DATE (entenda-se mm/dd/yy)

 

Na tabela de staging todos os campos usam VARCHAR. Mas as conversões de VARCHAR para CHAR ou para INTEGER são automáticas. É preciso tratar apenas da conversão das datas. Elas estão registradas no formato “dd.mm.yyyy”.

Observe que a conversão seria automática se o formato da coluna data fosse “mm/dd/yyyy”.  Mas no nosso caso é necessário haver um tratamento. É aqui que entra um truque que eu encontrei tempos atrás num fórum. É uma sugestão de Grzegorz Oledzki (veja Referências) e é um recurso que eu mantenho na minha “caixa de ferramentas”.

Convertemos as datas usando a função CONVERT(),  especificando o novo tipo de dados como DATE e o parâmetro de formatação 103, que representa o formato “dd/mm/yyyy”.

A Listagem 5 mostra a declaração INSERT com a conversão necessária:

Listagem 5: populando a tabela de destino


1insert into dbo.tbDestino (
2     TipoPessoa
3    ,NomeCompleto
4    ,Titulo
5    ,Prenome
6    ,NomeDoMeio
7    ,Sobrenome
8    ,Sufixo
9    ,EmailPromo
10    ,DataAtualizacao   
11        )
12select
13     TipoPessoa
14    ,NomeCompleto
15    ,Titulo
16    ,Prenome
17    ,NomeDoMeio
18    ,Sobrenome
19    ,Sufixo
20    ,EmailPromo
21    ,convert(datetime, DataAtualizacao,103) as DataAtualizacao 
22from staging.tbDestino
23GO

Conclusão

Carga de dados é um tópico muito importante para qualquer sistema novo. Neste aspecto, dispor de um script simples e versátil como aquele apresentado neste artigo pode ser de grande utilidade para desenvolvedores e DBAs.

Em resumo, o processo apresentado aqui envolve cinco etapas:

  1. Criação de uma tabela de staging com a mesma sequência de colunas dos arquivos de dados, usando sempre campos VARCHAR();
  2. Criação de uma tabela de pesquisa que use os tipos de dados adequados para cada coluna e também inclua uma chave primária;
  3. Adaptação (se necessário) dos nomes de arquivos de texto para que sejam sequenciais;
  4. Identificação dos parâmetros do processo de importação;
  5. Definição das transformações necessárias entre a tabela de staging e a de pesquisa.

 

Esta é uma solução bastante versátil e de implementação simples. E espero que lhe seja útil assim como tem sido para mim.

Referências

MICROSOFT. BULK INSERT (Transact-SQL). MSDN. MICROSOFT CORP
OLEDZKI, Grzegorz. How to convert a “dd/mm/yyyy” string to datetime in SQL Server? STACKOVERFLOW. Maio/2010
MICROSOFT. CAST and CONVERT (Transact-SQL). MSDN. MICROSOFT CORP

Device-agnostic: desenvolvimento único, múltiplas plataformas

Design responsivo
Device-agnostic

A palavra “agnóstico”, de origem grega (a gnose, não-conhecimento), tem ligação com questionamentos profundos do ser humano, especialmente religiosos. Um pensamento agnóstico é, essencialmente, cético em relação a crenças: elas existem, mesmo que não seja possível provar. Essa postura de “dúvida permanente”, capaz de revelar respostas e abrir a mente, vem sendo adotada por desenvolvedores web ao projetarem e implementarem produtos e serviços.

A crença, nesse caso, é a de que “plataformas e dispositivos diferentes exigem soluções específicas”. O desenvolvedor e web designer norte-americano Ethan Marcotte foi um dos primeiros a questionar essa premissa, em 2010, ao escrever em seu blog sobre as vantagens do design responsivo. “Não se trata de ‘projetar para celular’, mas também não é ‘projetar para desktop’. Em vez disso, é sobre a adoção de uma abordagem mais flexível para a web, uma abordagem device-agnostic”.

Ao contrário da visão tradicional, centrada em dispositivos, a expressão device-agnostic aponta para um desenvolvimento único, baseado na web, capaz de funcionar em qualquer lugar, mesmo em dispositivos que ainda não foram criados. “A presença da web em múltiplos dispositivos não é novidade. O W3C possui dezenas de grupos de trabalho e interesse, que discutem a evolução na web tanto em dispositivos móveis quanto sua aplicação em automóveis, por exemplo. Os grupos surgem conforme as tecnologias evoluem”, explica o especialista em desenvolvimento web do W3C Brasil, Reinaldo Ferraz.

Para Clécio Bachini, diretor de pesquisa e desenvolvimento da Soyuz Sistemas, vivemos um momento no qual o dispositivo não é mais a estrela, mas sim a experiência que a aplicação proporciona e sua adaptação ao ambiente. “Isso é a principal questão do device-agnostic, porque eu posso dar continuidade ao meu trabalho em qualquer lugar, de acordo com os meus interesses”. Nesse contexto, a interoperabilidade da web é a chave. “É possível pensar em uma aplicação em uma loja de aplicativos que não faz ideia de como ela é feita, e ela pode ser toda baseada em web”, lembra Ferraz.

No smartphone ou na televisão

Bachini acredita que, com o tempo, existirão mais sistemas operacionais baseados em um núcleo Linux, C ou outra linguagem baseada em UNIX, mas com interface totalmente web. “A web é essencial para isso. Ela está se tornando a grande máquina universal. É possível colocar um engine de web em qualquer dispositivo e rodar. A preocupação é que ele renderize e que rode aplicações JavaScript mais rápido. É o que acontece hoje com aplicações no navegador Chrome ou mesmo no Firefox OS”, exemplifica, mencionando o sistema operacional livre mantido pela Mozilla Foundation.

Desenvolvedor evangelista do Firefox OS, David Ruiz complementa: o navegador web é o elemento comum entre a tela de um smartphone e um televisor inteligente, permitindo a interoperabilidade. “Alguns aparelhos da LG utilizam um sistema operacional web, o WebOS. Qualquer aplicativo que você desenvolver para web, empacotar e colocar uma casca para distribuir em uma appstore vai funcionar nela”.

Ruiz aponta alguns pilares para explicar o avanço dessa postura. O principal é a melhoria de performance dos browsers, capazes de interpretar e compilar códigos JavaScript com mais eficiência. “O navegador deixou de ser apenas uma janela para a informação. Agora, quanto mais responsabilidade você jogar para o navegador, melhor”.

Outro aspecto são as práticas de design responsivo. Por meio de media queries, é possível definir dentro do CSS a quantidade de informação a ser exibida, seja qual for a dimensão da tela. “Em vez de simplesmente espremer todo o conteúdo, é preciso encontrar a melhor forma de apresentar o que é mais relevante ou esconder o que não interessa”.

Finalmente, Ruiz destaca a possibilidade de uma abordagem API first, ou seja, disponibilizar uma camada onde as informações são recuperadas por meio de múltiplos suportes. “Assim, as versões para acessar em desktop ou mobile tornam-se novas aplicações, que vão acessar informações estruturadas, armazenadas e acessadas por meio de APIs”, explica Ruiz.

Desenvolvimento web x sistemas nativos

Posturas agnósticas contrastam com crenças fortes. No mercado de apps para dispositivos móveis, os números reforçam o reino absoluto dos sistemas operacionais iOS e Android. Ambos possuem fãs dispostos a defender a programação na linguagem nativa desses aparelhos: facilidade de aprendizagem, tempo de desenvolvimento, aparência, aproveitamento de funcionalidades, performance, monetização etc.

Lançado pela Apple na última WWDC, a linguagem de programação Swift representa a última cartada para cativar seus desenvolvedores. “Esta foi uma aposta proprietária, focada nos produtos da Apple, para criar uma forma muito simples de programar aplicações”, observa David Ruiz, lembrando que um clone do jogo Flappy Bird foi produzido em poucas horas após seu lançamento. “É bastante promissora, mas continua fechada para o seu sistema”, reitera.

“É o papel da Apple manter o seu nicho. Mas eles sabem o que está acontecendo, gradualmente eles já aderem aos padrões web. Quando o mercado começar a se acertar, eles estarão prontos”, aposta Clécio Bachini. Para ele, essa briga entre desenvolvedores nativos e web tende a acabar. “A tendência é que essas interfaces migrem para a web, independentemente da linguagem de programação. Isso não quer dizer que vai ser tudo igual: ainda teremos experiências com estilo iOS e outras Android. O objetivo é fazer com que a aplicação se adapte mais facilmente à experiência que o usuário espera”.

Segundo Ruiz, há ainda uma visão equivocada sobre a performance de aplicações baseadas na web. A principal propaganda negativa veio em 2012, quando o Facebook lançou sua aplicação para iPhone baseada em HTML5: diante das reclamações, Mark Zuckerberg voltou atrás, optou pela linguagem nativa e alegou ter sido “um erro” usar padrões web. “Em resposta, a Sencha Labs produziu uma aplicação web chamada Fastbook”, recorda. Um vídeo comparativo mostrou que o problema não estava no embate entre abordagens, mas na qualidade do código. Você pode assistir ao vídeo “The Making of Fastbook: An HTML5 Love Story”.

Do webmaster ao profissional multidisciplinar

O exemplo do aplicativo Facebook em HTML5 ressalta a importância de desenvolvedores capazes de atender às demandas do mercado. No caso da web, a evolução remete à figura do “webmaster”. Popular em meados dos anos 1990, era o profissional responsável por tudo. Com o tempo, especialistas em arquitetura da informação, usabilidade e design dividiram a tarefa, dando fôlego a quem se dedica ao código-fonte.

Para David Ruiz, o desenvolvimento front end evoluiu rapidamente nos últimos anos. “Uma das razões para isso é o NodeJS, que permite que você execute linhas de comando, códigos e tarefas dentro do seu computador programando em JavaScript”, opina. Ferramentas como Grunt e Gulp, bem como frameworks como o AngularJS, deram maior poder de desenvolvimento a esses profissionais.

Com esses avanços, a trilha para o desenvolvimento multiplataforma por meio da web passa por uma nova divisão de especializações: entre back end e front end. Ruiz entende que essa divisão é clara e necessária. “Quem desenvolve back end se responsabiliza pela arquitetura, pela construção das APIs. Já o front end tem que ter uma preocupação com o desenvolvimento das tecnologias, para conseguir extrair o melhor do hardware que está sendo utilizado”.

Clécio Bachini vê com cautela essa separação absoluta. Ele já viu projetos fracassarem porque o back end não consegue dialogar com o front end. Assim, o profissional de web precisa ser multidisciplinar. “Ele precisa saber algo sobre banco de dados e correlação entre eles, existe uma camada semântica importante. Conhecer ainda um pouco de design, outras linguagens… Um pouco de tudo, mesmo que não execute. Existem pessoas nas duas pontas do seu código, com informação no meio. É fundamental entender as melhores formas de ela ser transmitida”, sugere.

Ainda que pareça difícil fazer qualquer prognóstico em relação ao futuro (afinal, quando poderemos dizer que a “Internet das Coisas” é algo corriqueiro?), está claro que “a web continua muito forte, cada vez mais para todos”, como afirma Reinaldo Ferraz. Desenvolver na web e adotar uma postura agnóstica revela oportunidades, mas ao mesmo tempo exige escolhas. Então, em que você acredita?

***

O W3C possui dezenas de grupos de trabalho e interesse, que discutem a evolução na web tanto em dispositivos móveis quanto sua aplicação em automóveis. Veja alguns:

Você encontra a lista complete dos grupos neste link e os Community e Business Group aqui.

—–

Artigo de André Rosa, publicado originalmente no iMasters.

Três ferramentas de cache para acelerar seu WordPress

wordpress wallstreet
Imagem: Marca WordPress

Acelerar seu site em WordPress certamente traz grandes benefícios. Além de ser uma experiência favorável para o usuário, pode ser um fator determinante para o posicionamento na página de buscas do Google. Por isso, aqui vão algumas dicas de como utilizar plugins de cache para aumentar a velocidade de entrega de conteúdo na sua página!

O que é cache e como ele pode trazer benefícios

Cache é uma cópia de um conteúdo que costuma ser gerado dinamicamente, servindo a requisições subsequentes de maneira mais rápida, evitando o reprocessamento desnecessário de conteúdo.

O objetivo do cache é reduzir o custo de acesso de sites. Existem técnicas que aumentam a performance de um site exercendo regras sobre os navegadores para tipos de arquivos diferentes, como de imagens, que raramente são alterados, podendo ter tempo de cache alto. Esse tipo de cache é armazenado no browser.

Já conteúdo dinâmico tem seu cache armazenado diretamente no servidor web, pois é necessário um controle de alterações mais eficaz.

O cache pode beneficiar o site reduzindo a demanda de recursos em cada acesso único e, em casos de cache client side, também pode reduzir o conteúdo entregue.

O tempo e a quantidade ideal de cache dependem de cada projeto, pois cada conteúdo pode ter um tipo diferente de cache conforme as regras de negócio do site.

Por que plug-ins de cache?

Um plug-in de cache é um fator muito importante em um blog de sucesso. Se você utiliza o WordPress, a cada visita esse CMS irá passar por um processo de montagem da página ligado pela conexão com o banco de dados e montagem do código HTML.

Quando um site recebe um tráfego pesado, uma carga significativa no servidor pode retardar o carregamento das páginas e até mesmo torná-lo indisponível. Se o cache estiver habilitado, apenas o primeiro visitante irá passar por esse processo. Depois, todos os demais internautas irão visitar páginas HTML que já estão prontas, e o processo será muito mais rápido.

Existem diversos plug-ins de cache que aceleram a sua página em WordPress. Neste artigo, vamos falar sobre três ferramentas que quando utilizadas em conjunto podem aumentar ainda mais a velocidade de sites em WP.

OPcode

O OPCode é uma extensão do PHP que foi gerada para aumentar a performance de execução de código ao ser processado no servidor. Após a abertura do plano, que era proprietário, a Zend introduziu-o ao PHP e tem mostrado suporte para o projeto.

Toda vez que um script é executado, a engine do PHP precisa compilar o código fonte em algo que a linguagem de máquina possa entender, resultando em um OPcode. Quando uma nova requisição é realizada, antes de o PHP compilar o código fonte, o software de cache intercepta e verifica se o OPcode do script já existe no cache. Caso não exista, o sistema de cache passa para o PHP Engine gerar o OPcode e o armazena no cache.

Nas requisições subsequentes para o mesmo script, o OPcode será obtido a partir do cache, e não será necessário ser compilado pelo Engine do PHP novamente. Esse processo economiza de forma considerável o processamento de CPU no servidor.

É claro que, se houver mudanças no código fonte em um script que já tenha o OPcode no cache, a mudança será identificada pelo sistema, que irá proceder com a devida atualização.

W3 Total Cache

Este plug-in melhora a experiência do usuário no seu site, aumentando o desempenho do servidor e reduzindo os tempos de download. Com ele, você tem uma infinidade de opções de otimização, como minimização de código fonte e integração com sua rede de distribuição de conteúdo (CDN).

Com o W3 Total Cache instalado, seu blog pode carregar 10 vezes mais rápido e economizar até 80% de largura de banda. O tempo de inatividade é reduzido e a qualidade é drasticamente melhorada.

Importante: Antes de instalar o W3 Total Cache, é necessário que você remova ou desinstale todos os plug-ins de cache que esteja usando (por exemplo, o WP Super Cache). Se você tiver algum plugin de cache correndo, é natural que tenha problemas na ativação.

Varnish

Varnish é um servidor HTTP usado como proxy de cache para conteúdo web. Ele atua de forma transparente, independentemente de linguagens de programação e bancos de dados, pois age diretamente na camada HTTP, utilizando somente cache de conteúdo já gerado.

Basicamente, quando um cliente acessa um site que possui um Varnish, ele acessa o Varnish, que confere se já possui cache do conteúdo acessado. Se tiver, entrega o conteúdo imediatamente. Caso contrário, busca o conteúdo no servidor original (que fará o processamento), armazena-o em cache e entrega o retorno ao usuário inicial.

Após esse armazenamento, o fluxo é repetido em novos acessos, com a vantagem de que o cache fica armazenado na memória RAM do servidor, aumentando a velocidade de entrega de conteúdo.

O Varnish pode aumentar a velocidade de 300 a 1.000 vezes, principalmente de elementos estáticos, e diminuir bastante a utilização de memória, deixando para o Apache somente a execução de conteúdo dinâmico, como scripts PHP e CGI.

A implantação do Varnish não requer mudanças na programação do site. Caso ele rode no mesmo servidor que o Apache, existe a necessidade de ajuste das portas de comunicação e uso de um IP adicional. Também pode ser utilizado para balancear a carga entre dois ou mais servidores web.

As técnicas de cache são usadas para melhorar o desempenho do site, ao preservar recursos do servidor, permitindo que ele possa entregar o conteúdo a mais usuários. Planejar e oferecer acesso rápido aos usuários do seu site é um dos passos essenciais para o sucesso da sua página!

—–

Artigo de Andressa Dorneles, publicado originalmente no iMasters.

A simplicidade e a importância do Round Robin como técnica de balanceamento

banco de dados
Imagem ilustrativa

Na era da Big Data somos obrigados a criar sistemas cada vez mais robustos que saibam lidar com grande variação de demanda. Serviços na internet, por exemplo, possuem uma variação tão grande de uso, que gera dificuldades para controlar os acessos nos momentos de pico. Os sistemas que precisam ter controle de demanda, mas não o fazem, podem ter inúmeros problemas como, por exemplo, gerar um tempo de resposta inaceitável para seus usuários ou até mesmo fazer com que o sistema fique fora do ar.

Para tentar amenizar o problema de variação de demanda, muitas empresas acabam criando sistemas altamente complexos que realizam a monitoração através de métricas, como medições de CPU e memória para distribuir a carga de trabalho. Com estas métricas, serviços podem ser capazes de mudar seu comportamento caso precisem lidar com muitos acessos, repassando trabalho de uma máquina para outra, caso atinja um limite de CPU ou até mesmo recusando novas requisições para evitar a degradação do sistema, para citar alguns casos. Existem ainda sistemas que trabalham com arquiteturas de prioridade, tratando primeiramente dos processos com maior demanda, tentando amenizar o grande número de acessos.

Existem, contudo, desafios para os sistemas listados acima: testar estas medições é uma tarefa complexa e, por isso, muitas vezes acabam sendo testadas apenas com simulações básicas. Além disso, exigirem manutenções delicadas quase que constantemente. Será que realmente é necessário adicionar tanta complexidade para distribuir trabalho em nosso sistema?

A resposta é: nem sempre é preciso. Uma alternativa é utilizar uma técnica chamada de Round Robin. Esta alternativa foi classificada como uma das mais simples e robustas entre as atuais técnicas utilizadas para problemas de distribuição de carga. Em palavras simples, Round Robin é um sistema que consiste em alguns elementos, sendo cada elemento representado por um processo ou até mesmo uma máquina de um cluster, formando uma fila circular.


No exemplo da figura acima, vamos supor que tenhamos um cluster com 4 máquinas. Cada nova requisição recebida em nosso cluster seria atendida por um destes nós. A primeira seria atendida pelo nó 1, a subsequente pelo nó 2, a seguinte pelo nó 3 e daí em diante até voltar ao nó 1 e reiniciar o processo. Com esta técnica é possível distribuir o trabalho de forma equilibrada para cada máquina disponível sem precisar calcular métricas de balanceamento. Existem inúmeras variações do algoritmo de Round Robin, uma delas, por exemplo, é trabalhar com filas circulares dando uma fatia de tempo de CPU para cada processo.

Neste artigo só estamos discutindo sobre a ideia mais simples, que já é bastante eficaz para a construção de API’s que precisam, por exemplo, de distribuição de carga. Esta técnica remove a necessidade de criar sistemas para monitoração dinâmica e são obviamente construídas de forma muito mais rápida e prática das que fazem balanceamento através de medições de recursos. Esta técnica foi criada antes mesmo de existirem computadores e é até hoje utilizada em larga escala por inúmeros sistemas com diferentes propósitos.

—–

Artigo de Breno Riba, publicado originalmente no iMasters.

Como fazer um tunning de aplicações web

Carregando...
Carregando…

A velocidade da aplicação em executar os processos está intimamente ligada com a experiência do usuário final. Na prática, vejo que os responsáveis pela criação de sistemas (gerentes, projetistas e programadores) não têm colocado isso como um fator de preocupação nos ciclos de desenvolvimento. O resultado é o mesmo de sempre, em ambiente de testes, homologação e durante algum tempo inicial de produção, o sistema acaba enganosamente funciona lindo e maravilhoso, mas depois de algum tempo, as reclamações relacionadas com a lentidão começam a aparecer. Diante desse contexto, segue abaixo as principais práticas que eu venho utilizando como sucesso como se fosse uma “receita de bolo” para resolver esse tipo de situação:

Acesso ao banco de dados

Reduzir ao máximo o número de vezes que a solução faz acesso ao banco de dados.

Problema: Muitos programadores têm a mania de ir desenvolvendo classes, componentes e módulos sem antes e/ou durante fazer uma análise organizada de como estas partes do sistema estão fazendo estes acessos. Com isso, vemos como resultado aplicações com baixa performance devido aos vários e desnecessários acessos ao banco “round-trips” que se multiplicam a medida do número de usuários simultaneamente conectados.

Solução: Analisar quantas vezes a aplicação está acessando o banco, o porquê do acesso e assim tentar uma forma de evitar este acesso. Neste momento, muitos profissionais pecam por não conhecerem recursos básicos de banco de dados e de SQL-ANSI, principalmente pelas propagações de frameworks ORM. Qualquer meio é válido, alguns recursos usados para alcançar isso são o uso de VIEWS, JOIN, SUBQUERYS e o Pattern Store Procedure Facade. Todos os programadores têm que possuir um lema em mente: “O acesso remoto é que mais degrada a performance de uma aplicação e o acesso ao banco de dados é um deles, então eu tenho que fazer de tudo para evitar ou minimizar ao máximo.“

Índices adequados

Criar os índices para as todas as tabelas que sofrem consultas na aplicação.

Problema: Muitos programadores não conhece o mínimo dos fundamentos de banco de dados, criando bancos sem nenhum índice de busca para as tabelas que sofrem alto número de SELECT + WHERE CAMPO. A questão problemática é que quando uma tabela sem índice sofre um SELECT +WHERE CAMPO, o registro é buscado, na maioria das vezes, da pior e mais demorada forma possível, que é o “sequencialmente”. A pior notícia é que isso é um problema cumulativo, ou seja, quanto mais registro existente, mais demorada fica a consulta. Já tive experiências de diminuir o tempo de um procedimento de fechamento mensal em 50% do tempo, pelo simples ato de criar os índices nas tabelas usados pelo processo.

Solução: Para cada SELECT que o programa faz, em cada tabela, verifique os campos de busca colocados no WHERE e, assim, crie um índice para cada um deles.

Consultas gigantescas

Sistemas que permitem o usuário consultar e trazer do banco de dados um alto número de registros.

Problema: Algumas situações que costumam ocorrer em sistemas no modelo desktop, ou mais conhecido como “FAT CLIENT”, não se encaixam em aplicativos web. Um destes casos é quando sistemas permitem aos usuários filtrar e trazer do banco de dados consultas com um alto número de registros complemente desnecessário. Em casos em que o modelo era desktop, isso não acarretava problemas devido à própria natureza da solução. Entretanto em sistemas web, onde recursos de execução são compartilhados e o numero de acesso simultâneos é ilimitado, o sistema estará gastando um alto e precioso número relevante de memória.

Explicando de forma prática, eu já peguei sistemas na redondezas onde os programadores estavam replicando a arquitetura que continha uma camada de persistência CRUD. O problema era que o framework replicava um método que sempre retornava todos os registros existente. Isto estava sendo propagado para todo o sistema e seus processos relacionados. Se paramos para analisar, mecanismos de busca são disponibilizados ao usuário para que ele tenha autonomia de buscar registros individuais ou grupos lógicos deles. Qual seria o motivo, ou o que poderia fazer um usuário com 500 linhas de resultados de uma consulta? Que ser humano na face da terra gostaria de visualizar 500 registros em uma olhada? Mesmo que a regra de negócio ainda apoiasse o caso, o usuário final, sendo um humano comum, não teria tamanha visibilidade para isso.

Solução: Os processos do sistema em questão devem ser analisados e devem ser implementadas validações lógicas corretas, que não permitam  executar consultas que retornem uma alto número de registros no banco de dados. Duas práticas neste tópico são bem comuns – o uso sistemático de paginação, e a implementação de filtros inteligentes, baseados em regra do próprio negócio, que não deixassem a ocorrência de grandes intervalos. Como tudo na vida, existem exceções e podemos, sim, encontrar situações em sistemas que teriam a necessidade de consultar grandes volumes de registros, mas isso já está mais que comprovado que é uma porcentagem pequena e restrita do total da automação.

Ordenação de dados

Ordenar dados em memória usando java ao invés de usar ORDER BY.

Problema: Uma funcionalidade muito comum é disponibilizar a ordenação das tabelas apresentadas na aplicação pelas suas próprias colunas. A questão problemática é quando a aplicação efetua mais um acesso ao banco a cada ordenação requisitada. Ou seja, o programador usa o recurso de SELECT ORDER BY para fazer a ordenação.

Solução: Transformar as linhas da tabela em objetos Java e, assim, ordená-los usando recursos do JSE, evitando gasto com tempo, acesso ao banco e recursos de memória. Esta solução pode ser facilmente implementando com a interface Comparable.

Pool de conexões

Use indiscutivelmente a abordagem de pool como paradigma de acesso ao banco de dados.

Problema: Eu realmente não sei o motivo, mas já peguei alguns aplicativos web por aí que abrem e fecham objetos de conexão com o banco de dados a cada requisição. Ou seja, a cada pedido enviado ao container Java, no mínimo duas chamadas remotas são efetuadas, uma para autenticar o usuário/senha e outra para efetuar a comando SQL desejado. Esta opção é uma das piores gafes que um desenvolvedor web pode fazer para deixar o sistema com a pior performance possível, sem falar que o sistema pode “baleiar” o banco quando o número de acesso simultâneos exceder a capacidade de resposta do determinado banco de dados.

Solução: Na web existe uma única solução comprovada que é o uso efetivo da abordagem de Pool de conexões. No momento da disponibilização – deploy da aplicação, o sistema deve abrir um número X de conexões com o banco de dados que será posteriormente usado em toda a aplicação. Esta abordagem mistura o conceito de compartilhamento e concorrência, sendo que pedidos em tempos diferentes reutilização a mesma conexão e pedidos simultâneos usarão diferentes conexões. Este número X deve ser levantando e configurado de forma parametrizada, de acordo com o perfil da aplicação e do modo/quantidades que os usuários estarão gastando conexões durante utilização do sistema.

Cache

Cachear informações que sofrem alto índice de acesso e baixa ocorrência de alteração.

Problema: Sistemas em geral implementam administração de informações na qual poderíamos classificar em dois tipos: dados de manutenção/parâmetrose de processos:

  • Manutenção/Parâmetros – informações que os sistemas têm que guardar, usadas como parte do processo, que não possuem um fim nelas mesmas. Este tipo de formação frequentemente sofre um baixo índice de manutenção e um alto número de acessos. Ou seja, no escopo da aplicação, estes dados raramente são alterados e muitos usados.
  • Processos – informações resultantes de processos com regras de negócio do escopo da aplicação. Estes podem ou não sofrer alterações e podem ou não ser altamente acessados. Tudo depende da natureza do negócio da aplicação.

A situação complicada seria o sistema fazer um acesso ao banco de dados a cada momento que diferentes usuários (concorrentes ou não) necessitassem usar informações de manutenção – que na grande maioria dos casos são iguais. Ou seja, teríamos vários usuários acessando o banco de dados repetidas vezes para pegar as mesmas informações, gastando assim tempo e memória de forma desnecessária.

Solução: Analisar cuidadosamente e cachear as determinadas informações que se encaixam de alguma maneria no perfil de dados de “Manutenção/Parâmetros”. Conceitualmente, é fácil visualizar o mecanismos de cache: o primeiro usuário que necessitar da determinada informação efetuará um acesso ao banco e cacheará os dados em algum lugar na memória, fazendo com que os próximos usuários não precisem gastar tempo e memória repetindo o ciclo. O cache é atualizado quando estes dados forem atualizados de alguma maneira no sistema, bem como o perfil deles já mostrou que seria um caso difícil de acontecer.

Segue um resumo das estratégias gerais:

  • Use cache de global para evitar consultas repetitivas dentro da solução global para dados que não sofram alteração de nível global;
  • Use cache de sessão para evitar consultas repetitivas dentro da mesma sessão para casos no qual dados estes dados não sofram alteração durante a o tempo de duração da sessão;
  • Use cache de thread local para evitar consultas repetitivas dentro da mesma requisição para casos no qual estes dados os sofram alteração durantes as requisições.

A prática do cache, entretanto, não é algo simples ou trivial; demandando tempo e esforço para ser implementado. Eu poderia sugerir implementações prontas como o EhCache, ou serviços de cache disponibilizados pelos frameworks ORM. Veja que a utilização só vale a pena se os dados realmente possuírem um alto índice de acesso. Com esta abordagem, a aplicação consegue reduzir em média até 60% o acesso ao banco de dados.

Ciclo de vida de objetos

Controle efetivo da criação de objetos durante a execução do programa.

Problema: Algo que precisamos sempre lembrar durante a programação é que o operador new aloca fisicamente o objeto da memória, gastando espaço no HEAP da aplicação. A primeira questão problemática é que percebo que os programadores usam o new de forma displicente, sem nem ao menos parar para pensar em que contexto da aplicação está usando. Tudo é motivo para fazer um new! Eu já vi casos em que para reiniciar o estado do objeto, o programador dava um new na referência.

Solução: O programador tem que sair desse comodismo e começar a analisar todos os seus new! Duas perguntas resolvem o problema: por que estou alocando esse objeto? Quantas vezes esse código vai ser executado?

Estas duas perguntas vão consciencializar o programador daquela situação, levando-o no mínimo a tomar uma das duas decisões abaixo:

  • Reutilizar Objetos: ao invés de ficar sempre fazendo new, ele pode aumentar a visibilidade do escopo daquele objeto e assim reusá-lo, restartando seu estado;
  • Reduzir o Escopo: reduzir o escopo dos objetos vai deixá-los disponíveis mais rápido para o coletor de lixo. Se for preciso, use escopos lógicos menores com { }.

Esta solução é uma das mais difíceis a serem implementadas, porque invadem a “cultura” do programador de se autocriticar. Mas quero animá-los dizendo que a batalha da economia de memória e performance se ganha na somatória de detalhes.

Objetos string

Controlar o gasto com os objetos Strings.

Problema: Outra coisa que sempre precisamos lembrar é que os objetos String chamados de “wrappers” são imutáveis, ou seja, uma vez instanciados eles nunca mudam. Qualquer operação com a String gerará uma terceira String. O problema aqui é o uso abusivo, desnecessário e inconsciente das String durante a execução do programa.

Solução: Segue a mesma ideia do tópico 5. O programador deve analisar a questão da necessidade e entender o por quê daquele uso. Duas opções surgem para contornar a situação:

  1. Usar final static para as Strings que se encaixam no contexto de estáticas (SQLs, mensagens). Ou seja, somente será gasto um objeto para todas as execuções do programa;
  2. Usar StringBuffer/StringBuilder para as String que sofrem alterações constantes ou para situações de manipulação de arquivos.

Configurações de memória da JVM

Problema: Mesmo depois de todas as precauções tomadas, a aplicação ainda pode gastar mais memória do valor default previamente configurado na JVM.

Solução: Neste casos, é preciso fazer um estudo, apurando a média de memória gasta pela aplicação, usando alguma ferramenta de profile e, assim, configurar um adequado número razoável de memória.

É isso, pessoal! O artigo fica aberto para sugestões e novas ideias.

—–

Artigo de Fernando Franzini, publicado originalmente no iMasters.

Três elementos da consistência em content marketing: estratégia, storytelling e personas

content marketing
Content marketing

Content marketing não é uma questão de ferramenta. É uma questão de estratégia. Foi esse o recado que procurei transmitir na abertura do Content Marketing Brasil 2014. Vivemos hoje no Brasil algo que era discutido nos Estados Unidos em 2012: será que Facebook funciona mais do que blog? É verdade que vídeo fortalece a marca mais do que Twitter? E-mail ainda funciona? E por aí vai…

A discussão sobre comunicação por múltiplos canais é bem-vinda em nosso mercado, que finalmente começa a abandonar a monocultura do Facebook. Mas é improdutiva, se focarmos apenas nos canais e não nos alicerces da comunicação de uma marca. Especialmente porque a plataforma que funciona bem para uma marca não necessariamente funciona para outra.

Baseado nos conceitos amplamente discutidos nas últimas duas edições do Content Marketing World, nos Estados Unidos, eu apontaria três pilares para um bom plano de content marketing:

1. Estratégia

Nada substitui a estratégia. Você, na condição de gestor de comunicação, precisa tomar decisões que norteiem o conteúdo para a geração de resultados alinhados aos objetivos da sua marca, e não apenas da área de comunicação. Observe a prévia da edição deste ano da pesquisa Benchmarks, Budgets And Trends, realizada anualmente pelo Content Marketing Institute, de Cleveland (EUA). Entre as empresas eficazes na prática de content marketing, apenas 3% abrem mão de uma estratégia. Entre as ineficazes, o percentual é de 44%. E mais: as empresas eficazes acompanham de perto a execução do plano estratégico.

2. Personas

Como você espera fazer conteúdo adequado ao seu público se não souber com precisão seus interesses e necessidades de quem lê, assiste ou ouve o que você produz? Em vez de despejar conteúdo e observar o que funciona melhor, experimente entrevistar alguns de seus leitores, ouvintes, espectadores, seguidores. Você entenderá melhor o que o público espera e, ainda, descobrirá aspectos que os gráficos de Analytics são incapazes de apontar. Depois, crie um personagem que represente esse público. Pronto, você terá uma persona. Aliás, fizemos um vídeo de 1’30” que explica bem esse conceito.

3. Storytelling

O volume de informações despejados na internet é enorme e concorre com todo tipo de publicação: de outras empresas, de outros mercados, da mídia convencional e, principalmente, dos amigos e parentes do seu público. Você precisa, então, ser relevante. Para se destacar, aplique storytelling à missão da sua marca e aos pedaços de conteúdo que publica.

Depois de estabelecer esses alicerces, você terá condições de produzir um conteúdo consistente, que transmita uma mensagem única, capaz de posicionar a marca. Só nessa etapa você deverá pensar nas táticas de distribuição de conteúdo. Isso vai acontecer naturalmente. E, quando acontecer, saiba que as táticas mais populares ― como site e redes sociais ― não são as mais eficazes. Segundo a mesma pesquisa do CMI, em 2014 as que mais geram resultados são: eventos presenciais, eventos online (como webinars) e vídeos.

Estratégia é o nome do jogo. E é exatamente por isso que assessores de imprensa são os profissionais mais aptos a ocupar o mercado de content marketing no Brasil.

—–

Artigo de Cássio Politi, publicado originalmente no iMasters.