terça-feira, 23 de março de 2010

Performance de aplicações WEB

Olá pessoal,

Tenho encontrado constantemente sites com problemas sérios de performance. Algumas das vezes temos problemas estruturais sérios, mas algumas vezes os problemas podem ser simples de resolver e pequenos ajustes representam grande melhoria na experiência do usuário.

Quando dizemos performance de aplicações, logo os desenvolvedores pensam em grandes mudanças estruturas como cluster, melhorias na JVM, máquinas novas, cache de banco de dados e outras. Isto também são melhoras importantes, mas quando se trata de aplicações web, a percepção da performance pelo usuário, pode ser melhorada por otimizações mais simples como mudanças no front-end da aplicação.

Podemos encontrar as melhores práticas sobre performance de aplicações web em http://developer.yahoo.com/performance/rules.html. Entre as dicas descritas no documento acima temos:

* Fazer menos requisições HTTP

* Adicionar um cabeçalho “Expires” na resposta HTTP

* Utilizar Gzip para compactar os componentes da página

* Colocar os Stylesheets no topo da página

* Colocar os Scripts no fim da página

* Evitar CSS Expressions

* Colocar os códigos JavaScript e CSS em arquivos externos

* Reduzir DNS Lookups

* Compactar os códigos JavaScript

* Remover Scripts duplicados

* Evitar Redirects

* Configurar as ETags

* Make Ajax Cacheable

Uma ferramenta que auxilia bastante é um addon do mozilla que chama YSlow que é um addon desenvolvido pela Yahoo. Este addon analisa com base nas melhores práticas documentadas no artigo acima quais regras estão sendo usadas.

Uma dica que me ajudou bastante em algumas aplicações que trabalhei foi a de habilitar a compressão de páginas. Existem páginas que são grandes, o que faz com que o acesso seja lento em conexões de rede ruins.

Esta compressão de página basicamente troca o requisito banda por CPU. Os passos realizados para a compressão são os seguintes:

1 – O browser do cliente faz uma requisição e envia para o servidor no cabeçalho que o browser aceita arquivos comprimidos.

2 – O servidor verifica que o browser que fez a requisição aceita arquivos comprimidos.

3 – O servidor comprime a página e envia para o cliente.

4 – O cliente descompacta a página recebida e exibe para o usuário.

Podemos utilizar para a compressão de página o apache com o módulo mod_deflate. Para explicações mais detalhadas sobre como funciona o mod_deflate verifiquem a documentação em http://httpd.apache.org/docs/2.0/mod/mod_deflate.html.

É isto ai pessoal. Espero que vocês sigam as orientações, para o bem de suas aplicações e de seus usuários.

terça-feira, 2 de fevereiro de 2010

Cache de páginas com o framework EhCache

Olá pessoal,

Há bastante tempo não escrevo nada. Resolvi falar agora sobre melhorias de performance que ajudam bastante a aplicação. Em sites, constantemente temos páginas que acessam várias consultas pesadas além de regras de negócio. Estas páginas quando muito acessadas causam freqüentemente problemas de desempenho na aplicação e páginas lentas.

Um dado importante para se tomar a decisão de utilizar ou não cache em páginas é a relação entre corretude e performance. Imagine o seguinte caso: Você tem uma página que possui as últimas notícias da sua empresa. Se uma nova notícia nova acaba de sair, qual o impacto da notícia demorar um pouco a mais para entrar no ar? O ganho de performance vale a pena o atraso na notícia. Se sim é interessante utilizar neste caso o cache para esta página.

Quando temos cenários parecidos com este podemos verificar se é possível realizar cache de páginas. O Ehcache que é um framework java possui além do cache de objetos e cache para acesso a dados com JPA, possui também cache de páginas. Este cache às vezes é mais interessante, porque uma mesma página pode possuir várias consultas e regras de negócio, o que faz com que o cache de página geralmente gere mais ganho de performance do que o cache de acesso a dados.

Para definir o cache de páginas é necessário primeiramente baixar os jars do ehcache disponíveis em http://ehcache.org. Entre os jars necessários é necessário baixar o módulo ehcache-web, que possui a Servlet responsável por gerenciar e guardar o cache das páginas.

Depois disto, no classPath (pode ser na pasta src por exemplo) deve ser adicionado o aquivo ehcache.xml com um conteúdo parecido com o abaixo:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<diskStore path="java.io.tmpdir" />
<cache name="SimplePageCachingFilter" maxElementsInMemory="10"
eternal="false" timeToIdleSeconds="600"
timeToLiveSeconds="600" overflowToDisk="true" />

<defaultCache maxElementsInMemory="10" eternal="false"
overflowToDisk="false" timeToIdleSeconds="120"
timeToLiveSeconds="120" diskPersistent="false"
diskExpiryThreadIntervalSeconds="120" />
</ehcache>


Para o arquivo acima é necessário verificar o tempo de expiração do cache que é definido pela propriedade timeToLiveSeconds que representa o número de segundos do cache da página apresentada.

Depois, no arquivo web.xml devemos adicionar o filtro de cache para as páginas necessárias, assim como mostrado abaixo:

<!-- Filtros para cache de páginas adicionado para páginas -->
<filter>
<filter-name>SimplePageCachingFilter</filter-name>
<filter-class>
net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>SimplePageCachingFilter</filter-name>
<url-pattern>/index.jsf</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>SimplePageCachingFilter</filter-name>
<url-pattern>/noticias.jsf</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>SimplePageCachingFilter</filter-name>
<url-pattern>/rss.jsf</url-pattern>
</filter-mapping>


A melhoria de performance é bastante significante. Além do cache de páginas comum é possivel também compactar as páginas, adicionar cabeçalhos, entre outros. Para mais informações visitem http://ehcache.org/documentation/web_caching.html.

É isto aí pessoal. Qualquer problema avisem...

quarta-feira, 9 de setembro de 2009

Resultado da enquete sobre certificações Sun

Olá pessoal,

Chegamos ao resultado de mais uma enquete. Desta vez sobre certificações Sun. Segue abaixo o resultado:

resultado enquete

Pelas respostas dos visitantes do site vimos que a grande maioria (57%) ja possuem a certificação de Programador (SCJP). Logo atrás em segundo lugar, com 38% das respostas estão os visitantes que responderam que não possuem nenhuma certificação.

Em terceiro lugar com 32% estão os certificados em Desenvolvimento Web (SCWCD). Muito próximo, logo abaixo estão os visitanes com certificação Associate (SCJA) e em Componentes de Negócios (SJBCD) com respectivamente 18% e 16% das respostas.

12% dos visitantes que responderam a enquete possuem a certificação de arquiteto (SCEA) e 7% a de Web Services (SCDJWS). Por último ficaram as certificações de desenvolvedor (SCJD) e de desenvolvedor para aplicações móveis (SCMAD) empatados com aproximadamente 6% das respostas.

Nesta última votação tivemos uma participação ainda mais ativa dos visitantes. Em breve teremos novas enquetes e continuem votando.

É isto aí pessoal.

segunda-feira, 31 de agosto de 2009

Apache Native Library no Tomcat ou Jboss

Olá pessoal,

Trabalhando com melhoria de performance de aplicações a algum tempo verificamos algumas mudanças que podem ser aplicadas no servidor de aplicação e que surtem efeito na aplicação como um todo. Entre estas melhorias uma que é uma opção para aplicações que utilizam servidores como o Tomcat e o JBoss é a utilização do Apache Tomcat Native Library (APR).

O Apache Tomcat Native Library é um JNI (Java Native Interface) que provê grande parte das funcionalidades do Tomcat em código nativo ao invés de utilizar Bytecode Java. Isto na prática significa maior velocidade da aplicação, uma melhor escalabilidade e melhor integração com os serviços nativos da máquina. Por default o Tomcat não vem com o APR já compilado e aplicado a distribuição, pois isto tornaria o servidor dependente de plataforma, mas sua utilização é bastante recomendável em ambientes de produção.

Entre as vantagens de sua utilização temos acesso a funcionalidades avançadas de IO (SendFile, Epoll e OpenSSL), funcionalidades do sistema operacional (Geração aleatória de números, status do sistema, etc.) e acesso a processos nativos (Memória compartilhada, NT pipes e Sockets).

Quando o APR não está instalado vemos o seguinte log no servidor de aplicação:
The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path

Para instalá-lo utilize os passos descritos em http://tomcat.apache.org/tomcat-6.0-doc/apr.html ou em http://www.liferay.com/web/guest/community/wiki/-/wiki/Main/Tomcat+Native+Library.

Assim que ele estiver instalado vemos o seguinte trecho no log do Tomcat:
INFO: Loaded APR based Apache Tomcat Native library 1.1.16.

Realizar os testes para verificar o quanto melhorou no desempenho da aplicação é um processo um pouco complicado, pois algumas operações podem ser mais beneficiada que outras. Em algumas referências vimos um ganho de até 10% na performance da aplicação em geral, mas realmente é um teste difícil de ser realizado.

Em um teste bem curto que fiz verificamos as seguintes medições apenas do tempo de startup do servidor sem e com a API nativa tive os seguintes resultados:

Tempos sem lib native:
2125 ms
2155 ms
2113 ms

Tempos com lib native:
1913 ms
1984 ms
1985 ms

Vimos então um ganho que se aproxima de 10% apenas para o startup do servidor.

É isto aí pessoal. Espero que isto ajude quem necessita otimizar a performance das aplicações.

Quaisquer problemas avisem...

quarta-feira, 26 de agosto de 2009

Implementando página de erro com JSF

Algumas pessoas estão tendo dúvidas sobre como implementar uma página de erro com JSF, e resolvi então criar este post para explicar uma maneira de implementar.

Para se realizar o redirecionamento pode se utilizar o ActionListener do JSF. Segue abaixo um exemplo de implementação da classe deste ActionListener:


/**
* Classe responsável por tratar erros inesperados do sistema.
*
* @author Samuel Delfim
*
*/
public class ExceptionHandler extends ActionListenerImpl {

@Override
public void processAction(ActionEvent event) {
// Obtem o contexto JSF
FacesContext context = FacesContext.getCurrentInstance();

try {
// Executa o método da classe Pai
super.processAction(event);

} catch (Exception e) {

// Se ocorrer um erro inesperado, exibe a mensagem abaixo
context.addMessage(null, new FacesMessage(
FacesMessage.SEVERITY_FATAL, e.getMessage(), null));


// Redireciona para a pagina com o mapeamento 'erro'
// no faces-config.
context.getApplication().getNavigationHandler().
handleNavigation(context, null, "erro");
}
}
}


Pode-se, por exemplo, na classe acima realizar tratamentos diferentes para cada tipo de exceção.

Para aplicar o Listener em uma aplicação jsf deve ser colocado o seguinte trecho dentro do arquivo faces-config.xml:


<application>
<!-- Aplicação do Listener -->
<action-listener>com.thinkworks.handler.exception.ExceptionHandler
</action-listener>
<view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
<locale-config>
<default-locale>pt_BR</default-locale>
<supported-locale>pt_BR</supported-locale>
<supported-locale>es_AR</supported-locale>
</locale-config>
<message-bundle>com.bionexo.mensagens.Mensagens</message-bundle>
</application>


O trecho a ser copiado se refere à tag e deve ser aplicado ao view-handler específico. Neste caso, o ViewHandler utilizado é o do projeto facelets que está sendo utilizado no projeto em questão.

Também no arquivo faces-config.xml deve ser realizado o mapeamento da página de erro.
Segue abaixo um exemplo de mapeamento de página de erro:


<navigation-rule>
<navigation-case>
<from-outcome>erro</from-outcome>
<to-view-id>/pages/erro/paginaErro.xhtml</to-view-id>
</navigation-case>
</navigation-rule>


É isto aí pessoal. Espero ter ajudado...