terça-feira, 6 de dezembro de 2016

Java - Gerando threaddump e heapdump em um esgotamento de memória heap da JVM



   Quando forem provisionar algum ambiente de middleware, ou até mesmo para ambiente que apresenta esgotamento de memória heap, apliquem essa configuração abaixo na JVM para que ao ocorrer outofmemory na heap um threaddump e heapdump serão gerados: 


-XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -verbose:gc -XX:+PrintGCDetails -Xloggc:/tmp/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=12 -XX:GCLogFileSize=100M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/jvmheap-`date +%Y%m%d%H%M%S`.hprof -XX:OnOutOfMemoryError="$JAVA_HOME/bin/jstack -F pid > /tmp/jvmthread-`date +%Y%m%d%H%M%S`.dmp"


IMPORTANTE: 

1 - O usuário que executará a JVM deve ser root(não faça isso), ou um usuário que não tenha determinadas limitações, exemplos de ajustes no limits.conf e su do pam.d: 

jboss soft nofile 131072
jboss hard nofile 131072
jboss soft nproc 131072
jboss hard nproc 131072
jboss soft core unlimited
jboss hard core unlimited
jboss soft memlock 50000000
jboss hard memlock 50000000

session    required   pam_limits.so

2 - O usuário de execução deve ter permissão de escrita nas pastas em que o heap e thread dump serão gerados; 

3 - A variável $JAVA_HOME deve existir ou ser instanciada antes da chamada da JAVA_OPTS.

quarta-feira, 9 de novembro de 2016

Tomcat | TomEE - Utilizando APR em API e WS para aumentar performance


Quando provisionamos infraestrutura para uma API ou WebServices de integração sabemos que performance é um dos, senão o principal, fator a ser considerado, pois estamos trabalhando com um alto fluxo de requisições. A degradação de performance para este tipo de aplicação significa ao longo de um período sua indisponibilidade, pois ao não atender a carga eficientemente acumulam-se mais requisições de origem criando uma retenção que gerará aumento do tempo de resposta.

Quando um WebService, ou API, é desenvolvido em Java temos algumas alternativas para fazer sua exposição web. Criá-lo autocontido em um JAR com Jetty, publicar em um servidor de aplicação são algumas das diversas opções disponíveis. Neste texto, consideramos que a publicação foi feita em um Tomcat ou TomEE, ou até mesmo em um servidor de aplicação que utiliza o Tomcat como contêiner Web, exemplo JBoss, que tem até a versão 6 o JBoss Web.

A Apache Foundation disponibiliza para o Tomcat como biblioteca de suporte a alta performance, escalabilidade e integração o Apache Portable Runtime,  suporte que só estará ativo quando três componentes forem identificados na inicialização da JVM do Tomcat:

1 - APR - Apache Portable Runtime;
2 - JNI wrappers para o APR -> (libtcnative);
3 - OpenSSL.

Mas qual o ganho real com isso?

HTTP
Ganho de 11% em requisições HTTP quando utilizado
o APR ao invés do connector BIO (padrão) e somente
7% a menos que um Apache 2.x.  

HTTPS
Ganho de mais de 100% em requisições HTTPS quando
se substitui o connector padrão do Tomcat pelo APR,
performando inclusive melhor a um WebServer Apache 2.x.


Fique ligado: ter tais componentes instalados no sistema operacional nem sempre indica que o APR está sendo carregado corretamente no Tomcat. No CentOS ou RHEL (RedHat Enterprise Linux) 6 ou 7, por exemplo, o APR instalado não é identificado pela libtcnative, o que por consequência inviabiliza o uso do APR no Tomcat.

Forma de identificar que o Tomcat não está utilizando o APR é avaliar o log do Catalina quando em
severidade INFO ou menor:

org.apache.catalina.core.AprLifecycleListener.lifecycleEvent The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
Algumas abordagens mais atuais de arquitetura reduzem o impacto de baixa performance escalando horizontalmente a infraestrutura, ainda assim, quanto menor a capacidade de processamento, maior a quantidade de servidores que precisará escalar para ter vazão.  

Dependendo do tipo de negócio que é aplicado, uma API ou WebService não ser utilizado por questão de ineficiência de tempo de resposta é fadar a aplicação ao fracasso.

Referências:









Publicação também disponível em: http://ilegra.com/beyonddata/

quarta-feira, 26 de outubro de 2016

Java - Snapshot JVM

O conteúdo do script é muito útil para quem sabe o que fazer com ele e como analisar as saídas. 

Cuidado ao utilizá-lo livremente em função do heapdump que é gerado a cada execução então precisam avaliar espaço em disco e impacto antes disto. 

Ele serve para coletar diversas informações sem que seja necessário algo mais que o JDK instalado no servidor alvo que vão avaliar. 

   Exemplo de saída: 

$ ./snapshot-jvm.sh
PID JVM -> 18854
Date execution -> Wed Oct 26 15:47:27 BRST 2016

Take thread dump...
Take memory snapshot...
Attaching to process ID 18854, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.79-b02
Attaching to process ID 18854, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.79-b02
finding class loader instances ..done.
computing per loader stat ..done.
please wait.. computing liveness..............liveness analysis may be inaccurate ...
Take memory dump...
Dumping heap to /opt/resources/temp/heapdump-18854-15-2016-10-26.hprof ...
File exists
Snapshot resources in use
Check threads in use...
Finish.

Repositório para download : https://github.com/helkmut/snapshot-jvm


Em resumo, após sua execução poderá avaliar threads ativas nos connectors, thread dump, heap dump e suas estatísticas, assim como estatísticas do uso dos recursos do servidor. Com essa informação conseguimos identificar uma contenção de recursos seguramente. 

Espero ter ajudado de alguma forma, ao menos poupando o trabalho de fazer um script igual.

terça-feira, 23 de agosto de 2016

FlywayDB - Automação e versionamento de dados


Paradigmas caem dia após dia na tecnologia da informação. Tal dinâmica é conhecida por desenvolvedores atentos as mudanças de metodologia de desenvolvimento de software, linguagens e ao próprio modelo e ciclo de implantação de suas aplicações.

Essa dinâmica gerada pela demanda de inovação em razão do empreendedorismo de diferenciação, com a necessidade de entregar mais e melhor em menor tempo a menor custo revolucionou camadas de frontend, backend, integrações e interações com objetos que tornaram-se cache e responsabilidade de CDNs (Content Delivery Network). Mas pouco falava-se na camada de dados.

Um exemplo prático do método utilizado em grandes organizações para o gerenciamento da estrutura de dados geralmente segue o seguinte modelo: O desenvolvedor cria seus SQLs necessários para atender uma demanda de negócio(ou correção de erro) com scripts de install e rollback e em algumas circunstâncias “perfumados” com um gerenciador de publicação de estrutura de dados: O qual recebe o script, ordena, valida sintaxe ou algo neste sentido.
Em conjunto com processos delineados de gestão de mudanças, entra em cena o nosso amado DBA(administrador de banco de dados), o qual tem o papel de avaliar o conteúdo e seu impacto na performance, também a integridade da base de dados, e quando passar nestes quesitos aplicar tais scripts, ocasionalmente em horário comercial quando temos um nível de amadurecimento alto, ou em função da criticidade e risco nas madrugadas frias de sábado para domingo.

Enquanto isto, do lado do código da aplicação o desenvolvedor com sua veia inovadora utiliza-se de novas soluções e metodologias para que a atualização de sua aplicação seja feita da maneira mais ágil possível, resguardado por seus testes de performance, funcionalidade, cobertura de código e outros que lhe permitem a realização cada vez mais eficaz de entrega e integração.

Pois bem, mas chegada a hora do desenvolvedor atualizar informações na base e toda inovação fica fadada a execução de um processo lento e dependente, passível de erros e falhas humanas durante um rollback ou install.

Finalizada a apresentação de fluxos e cenários que ainda existem, e são comuns em organizações, vamos ao que o FlywayDB, uma das soluções disponíveis de versionamento de estrutura de dados, pode fazer e como ele pode fazer.



flywaydb.png

O FlywayDB (https://flywaydb.org) em comparação com o Liquibase (http://www.liquibase.org/) parece-me mais flexível e simples em sua implantação cujo cenário descrito acima nesta publicação seja o vigente. Dai a opção de uso desta solução, mas vale fazer uma comparação das duas.

Em que versionar as alterações de estruturas de dados e dados pode beneficiar? Primeiramente em mapear alterações, ou seja, saber o que e quando causou impacto, também acompanhar o ciclo de evolução da base de dados. Veja um exemplo da tabela de ‘migrations’ do FlywayDB:

schema.png
Com essa informação é possível saber do que se trata a migration, qual versão a base está e quais foram bem sucedidas das ‘migrations’ e quando.

Abordaremos então os métodos de integração com o seu projeto Maven e repositório de versionamento GIT.

No exemplo utilizado para integrar a um projeto Maven os scripts SQL precisarão estar situados no diretório, ou alterar no pom.xml o location: $projeto/src/main/resources/db/migration de seu repositório GIT. Precisarás incluir também as dependências de plugins e jdbcs, tais como:

JDBC
   
          mysql
          mysql-connector-java
          5.1.21
  

Plugin FlywayDB
   
        com.googlecode.flyway
        flyway-core
        1.7
  

   
       
          com.googlecode.flyway
          flyway-maven-plugin
          1.7
         
            $user
            $passwd
            com.mysql.jdbc.Driver
            $string_de_conexão
  
                    src/main/resources/db/migration
                    org.flywaydb.sample.migration
               
         
       
  

Não esqueça que precisará de um primeiro scripts de install na database alvo, um exemplo abaixo:

V0001__Install.sql

CREATE TABLE t (c CHAR(20) CHARACTER SET utf8 COLLATE utf8_bin);

Após para futuras migrations utilize: ‘V0002__Migration.sql’.

Estrutura de POM e aplicação de teste disponível em:


Exemplo de saída de um Job de criação de artefato do CI (Continuous Integration) Jenkins de um projeto Maven usando FlywayDB:

Started by user anonymous
Building in workspace /var/lib/jenkins/jobs/BUILD-treina-auto_avanc/workspace

Deleting project workspace... done

Cloning the remote Git repository
Cloning repository https://github.com/helkmut/treina-auto_avanc
>git init /var/lib/jenkins/jobs/BUILD-treina-auto_avanc/workspace # timeout=10
Fetching upstream changes from https://github.com/helkmut/treina-auto_avanc
>git --version # timeout=10
using .gitcredentials to set credentials
>git config --local credential.helper store --file=/tmp/git1715435271723825466.credentials # timeout=10
>git -c core.askpass=true fetch --tags --progress https://github.com/helkmut/treina-auto_avanc+refs/heads/*:refs/remotes/origin/*
>git config --local --remove-section credential # timeout=10
>git config remote.origin.url https://github.com/helkmut/treina-auto_avanc# timeout=10
>git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10
>git config remote.origin.url https://github.com/helkmut/treina-auto_avanc# timeout=10
Fetching upstream changes from https://github.com/helkmut/treina-auto_avanc
using .gitcredentials to set credentials
>git config --local credential.helper store --file=/tmp/git1240117904577578786.credentials # timeout=10
>git -c core.askpass=true fetch --tags --progress https://github.com/helkmut/treina-auto_avanc
>git config --local --remove-section credential # timeout=10
>git rev-parse refs/remotes/origin/master^{commit} # timeout=10
>git rev-parse refs/remotes/origin/origin/master^{commit} # timeout=10
Checking out Revision e5d07b7b9898c931fef6397d060e911e3535828c (refs/remotes/origin/master)
>git config core.sparsecheckout # timeout=10
>git checkout -f e5d07b7b9898c931fef6397d060e911e3535828c
>git rev-list e5d07b7b9898c931fef6397d060e911e3535828c # timeout=10
[workspace] $ /bin/sh -xe /tmp/hudson7642003292037004876.sh
+ git checkout
Parsing POMs
[app] $ /var/lib/jenkins/tools/hudson.model.JDK/Java8/bin/java -cp /var/lib/jenkins/plugins/maven-plugin/WEB-INF/lib/maven31-agent-1.5.jar:/var/lib/jenkins/tools/hudson.tasks.Maven_MavenInstallation/3.2.2/boot/plexus-classworlds-2.5.1.jar:/var/lib/jenkins/tools/hudson.tasks.Maven_MavenInstallation/3.2.2/conf/logging jenkins.maven3.agent.Maven31Main /var/lib/jenkins/tools/hudson.tasks.Maven_MavenInstallation/3.2.2 /var/cache/jenkins/war/WEB-INF/lib/remoting-2.51.jar /var/lib/jenkins/plugins/maven-plugin/WEB-INF/lib/maven31-interceptor-1.5.jar /var/lib/jenkins/plugins/maven-plugin/WEB-INF/lib/maven3-interceptor-commons-1.5.jar 41028
<===[JENKINS REMOTING CAPACITY]===>channel started
Executing Maven:  -B -f /var/lib/jenkins/jobs/BUILD-treina-auto_avanc/workspace/app/pom.xml -PDev compile flyway:status
[INFO] Scanning for projects...
[INFO]                                                                    
[INFO] ------------------------------------------------------------------------
[INFO] Building app 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ app ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ app ---
[INFO] No sources to compile
[INFO]
[INFO] --- flyway-maven-plugin:1.7:status (default-cli) @ app ---
[INFO] +-------------+------------------------+---------------------+---------+
[INFO] | Version | Description         | Installed on     | State   |
[INFO] +-------------+------------------------+---------------------+---------+
[INFO] | 0001     | Install             | 2015-06-15 17:22:49 | SUCCESS |
[INFO] +-------------+------------------------+---------------------+---------+
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.933 s
[INFO] Finished at: 2015-06-15T18:59:09+00:00
[INFO] Final Memory: 11M/31M
[INFO] ------------------------------------------------------------------------
[JENKINS] Archiving /var/lib/jenkins/jobs/BUILD-treina-auto_avanc/workspace/app/pom.xml to com.mycompany.app/app/1/app-1.pom
[workspace] $ /bin/sh -xe /tmp/hudson4990860526944688595.sh
channel stopped
+ tar cvf app.tar app README.md
app/
app/src/
app/src/main/
app/src/main/resources/
app/src/main/resources/db/
app/src/main/resources/db/migration/
app/src/main/resources/db/migration/V0001__Install.sql
app/index.html
app/MySqlDataGrid.aspx.resx
app/pom.xml
app/target/
app/target/classes/
app/target/classes/db/
app/target/classes/db/migration/
app/target/classes/db/migration/V0001__Install.sql
app/1web.config
app/MySqlDataGrid.aspx
app/1.html
app/MySqlDataGrid.aspx.cs
README.md
Triggering projects: DEV-treina-auto_avanc
Archiving artifacts
Finished: SUCCESS
 
Com relação às melhores práticas de vinculação com o CI (Continuous Integration) Jenkins em seu projeto, pipelines e demais plugins deixaremos para uma próxima publicação, pois seria aqui uma abordagem superficial. O importante é que essa publicação abra seus olhos para facilitar interações com a base de dados e a aplicação, proporcionando um ciclo ágil em ambas as camadas.  

Referências:



Autores:

*Gabriel Prestes é formando em Gestão da Tecnologia da Informação, arquiteto de middleware da ilegra com experiência de mais de 5 anos em suítes de middleware Oracle e RedHat. É um entusiasta de carros antigos.

DevOps Engineer com ampla experiência como agile coach e arquiteto de infraestrutura em clouds publicas e privadas. *Cesar Mesquita possui mais de 13 anos atuando na operação de infraestruturas de TI. Entusiasta da cultura DEVOPS,  contribuindo com diversas empresas a disseminar práticas ágeis entre os times de desenvolvimento e infraestrutura .
Trabalha atualmente na Ilegra como arquiteto de soluções em cloud. Fã incondicional de The Walking Dead, Breaking Bad e Band of Brothers.

Contato: https://br.linkedin.com/in/cmesquita00


Publicação também disponível em: http://ilegra.com/beyonddata/