quarta-feira, 10 de julho de 2013

JBoss - Erro 503 no Apache

   Aqui vai uma super dica para os amantes de JBoss combinado com Jk ou ModCluster.

   Durante a semana me deparei com o seguinte cenário, quando o Apache recebia mais de 500 acessos simultâneos o log do modjk retornava o seguinte erro:
___________________________________________
[Wed Jul 10 16:42:39 2013][22054:139731589330912] [error] ajp_connect_to_endpoint::jk_ajp_common.c (1035): (test-102) cping/cpong after connecting to the backend server failed (errno=24)
[Wed Jul 10 16:42:39 2013][22054:139731589330912] [error] ajp_send_request::jk_ajp_common.c (1630): (test-102) connecting to backend failed. Tomcat is probably not started or is listening on the wrong port (errno=24)
[Wed Jul 10 16:42:39 2013][22054:139731589330912] [error] ajp_service::jk_ajp_common.c (2626): (test-102) connecting to tomcat failed.
[Wed Jul 10 16:42:39 2013][22054:139731589330912] [error] service::jk_lb_worker.c (1485): All tomcat instances failed, no more workers left
________________________________________________

   O reflexo disto no Apache era o retorno de um erro 503 conforme abaixo:
__________________________________________
10.0.0.1 - - [10/Jul/2013:16:41:16 -0300] "POST /teste/salsa.json?blabla=1 HTTP/1.1" 503 437 "-" "Dalvik/1.6.0 (Linux; U; Android 4.0.3; GT-P3100 Build/IML74K)"
__________________________________________

   Quando o número de requisições reduzia os erros paravam e o ambiente era normalizado.

   Após ler em diversos fóruns mencionando que o erro era ocasionado por um Firewall bloqueando a conexão do AJP entre JBoss e Apache(o que não se aplicava no cenário corrente, pois estavam no mesmo servidor), realizei os seguintes ajustes no modjk e no JBossWeb:

Apache:

- Aumentei o connection_pool dos workers.

JBoss:

- Aumentei o MaxThreads das instâncias;
- Aumentei o ConnectionTimeout das instâncias.

   Com isso os erros 503 sumiram ao receber mais de 500 requisições simultâneas, e a comunicação AJP entre JBoss e Apache foi normalizada acabando com o erro 'cping/cpong' que na verdade quando é gerado manda o worker do URI para status ERR.



terça-feira, 4 de junho de 2013

PostgreSQL - Aumentando um LVM em RAID na AWS

   Hoje tive a experiência de aumentar um LVM com RAID0 na AWS, a situação foi que um PostgreSQL warm-standby parou de funcionar em função de não ter mais espaço no PGDATA para consumir WALs, então o pg_standby caiu. 

   Detalhes da situação:

1 - Instância apenas com uma tablespace;
2 - Sistema de arquivos em XFS; 
3 - 3 discos dedicados para o PGDATA em RAID0.

   Não vou dar grandes explicações, vamos ao procedimento:

1 - Adição do novo disco e vinculação a instância na Amazon;

2 - Adição do novo disco no array do RAID(mdadm --detail /dev/md0 ; mdadm --grow /dev/md0 --raid-devices=3 --add /dev/xvdi);

   Observe que no parâmetro '--raid-devices' você tem que preencher o número de discos/partições que seu RAID será composto. Em caso de dúvida rode um 'cat /proc/mdstat'.

IMPORTANTE: Considere neste passo o nível de RAID, pois alguns tipos de RAID não podem crescer sem que o novo disco fique em spare, então se este caso é o seu minha sugestão é criar um novo array de RAID e depois  vincular ao LVM, claro que para isso você precisará de mais discos. 

3 - Desativar o LVM(umount /var/lib/pgsql/data/ ; swapoff -a ; lvchange -an  /dev/vg_dados/lv_swap ; lvchange -an  /dev/vg_dados/lv_pgdata);

  Aqui desativei o LV do swap também, pois no mesmo LVM está a swap do sistema operacional, talvez isso não se aplica ao seu caso. 

4 - Aguardar até que o novo disco seja sincronizado com os demais(watch -n1 "mdadm --detail /dev/md0);

    Com este comando você verá o percentual de execução do sincronismo do novo disco do RAID, quando todos estiverem sincronizados vá para o passo 8. 

    Mentira, é o 5. 

5 - Após fazer um resize do LVM(pvresize /dev/md0 ; vgextend vg_dados /dev/md0 ; lvextend -L+120G /dev/vg_dados/lv_pgdata ; lvchange -ay /dev/vg_dados/lv_pgdata ; lvchange -ay /dev/vg_dados/lv_swap ; swapon -a);

   Aqui estou fazendo um resize no PV e LV, no parâmetro '-L' utilize o tamanho do seu novo HD do RAID. 

6 - Aumentar o XFS(xfs_growfs /dev/mapper/vg_dados-lv_pgdata);

   Como meu sistema de arquivos é XFS utilizei o comando acima. 

7 - Reparar o XFS(xfs_repair -v /dev/mapper/vg_dados-lv_pgdata ; mount -a);

   Quando tentei iniciar o PostgreSQL sem executar o passo atual, o pg_ctl retornou que não conseguia gravar o 'postmaster.pid' em função da estrutura não estar limpa, então procurando na Internet descobri que era coisa do sistema de arquivos, o comando corrente resolveu o problema. 

8 - Aguardar o PostgreSQL consumir os WALs(tail -f /var/log/pgsql.log); 

   Chegou a hora de subir o PGSQL, se tudo deu certo é só alegria. Que foi o meu caso, tomara que seja o seu leitor. 

quinta-feira, 9 de maio de 2013

JBoss - RHQ/JON deployment em Domain mode EAP6 ou JBoss7.x

IMPORTANTE: Domain mode não suporte Bundles!!!

Deployment de novas aplicações

PASSO 1

Acesse o link do JON/RHQ no seu navegador e preencha os campos com as credenciais.

PASSO 2


Acesse o 'Inventory', selecione o item 'Servers' do inventário e clique no recurso 'EAP Domain Controller'.


PASSO 3


Após clique com o botão direito no item do 'Domain Controller' e com o botão esquerdo em 'DomainDeployment'.

PASSO 4


Informe a versão da aplicação que está realizando o deploy, faça o upload da mesma:




PASSO 5


Avance a tela e clique em 'Finish'. Aguarde até que a aplicação que realizaste deploy esteja disponível no item 'DomainDeployment', isto pode levar alguns minutos.



PASSO 6

Agora você precisa designar ao grupo de servidores a aplicação, então clique com o botão direito do mouse sobre a aplicação que criaste, selecione 'Operations' e após clique em 'Assing to Server-group'.



Selecione o Server-grop do seu ambiente, marque o 'Yes' como Enabled, no Schedule marque 'Now' e após clique em 'Schedule'. 

* Imagens extraídas da documentação oficial da RedHat. 

sexta-feira, 22 de fevereiro de 2013

PostgreSQL - Replicando PostgreSQL em 15 passos com Gabriel Prestes


Migração banco de dados:


1 - Criar estrutura de archives na instância de origem:
[root@sebaorig /]# mkdir -p data/archive_log
[root@sebaorig /]# chown -R postgres. data/archive_log/


2 - Ativando archive na instância de origem:
[root@sebaorig /]# grep archive /var/lib/pgsql/data/postgresql.conf
archive_mode = on # allows archiving to be done
archive_command = 'rsync -arv %p /data/archive_log/%f' # command to use to archive a logfile segment
archive_timeout = 0 # force a logfile segment switch after this
[root@sebaorig /]# service postgresql restart
Stopping postgresql service: [ OK ]
Starting postgresql service: [ OK ]


3 - Testando a gravação de archives:
[root@sebaorig /]# psql -U postgres
psql (8.4.5)
Type "help" for help.


postgres=# SELECT pg_switch_xlog();
pg_switch_xlog
----------------
61F/AF92C180
(1 row)


postgres=# \q


[root@sebaorig /]# ls -la /data/archive_log/
total 16412
drwxr-xr-x 2 postgres postgres 4096 Oct 18 20:24 .
drwxr-xr-x 3 root root 4096 Oct 18 20:20 ..
-rw------- 1 postgres postgres 16777216 Oct 18 20:24 000000010000061F000000AF


4 - Colocando a instância de origem para backup:
[root@sebaorig /]# psql -U postgres
psql (8.4.5)
Type "help" for help.


postgres=# SELECT pg_start_backup('Cordeiro de Deus perdoai os pecados do mundo');
pg_start_backup
-----------------
61F/B0000020
(1 row)
postgres=# \q


5 - Replicando a instância para o servidor de destino:
[root@sebaorig pgsql]# rsync -avog --delete-after data/ -e ssh root@sebadest:/var/lib/pgsql/data


6 - Criando estrutura de archives no servidor de destino:
[root@sebadest pgsql]# mkdir -p /data/archive_log
[root@sebadest pgsql]# chown -R postgres. /data/archive_log

7 - Parando o backup na instância de origem:
[root@sebaorig archive_log]# psql -U postgres
psql (8.4.5)
Type "help" for help.


postgres=# SELECT pg_stop_backup();
pg_stop_backup
----------------
61F/B0000088
(1 row)


postgres=# \q


8 - Replicando archives para o servidor de destino:
[root@sebaorig pgsql]# rsync -avog --delete-after /data/archive_log/* -e ssh root@sebadest:/data/archive_log


9 - Limpando a instância de destino:
[root@sebadest data]# rm postmaster.pid


10 - Criando recovery.conf na instância de destino e limpando pg_xlog:
[root@sebadest data]# vim recovery.conf


Insira o seguinte conteúdo:


# -------------------------------
# PostgreSQL recovery config file
# -------------------------------
#
# Edit this file to provide the parameters that PostgreSQL
# needs to perform an archive recovery of a database.
#
# If "recovery.conf" is present in the PostgreSQL data directory, it is
# read on postmaster startup. After successful recovery, it is renamed
# to "recovery.done" to ensure that we do not accidentally re-enter
# archive recovery mode.
#
# This file consists of lines of the form:
#
# name = 'value'
#
# (The quotes around the value are NOT optional, but the "=" is.)
#
# Comments are introduced with '#'.
#
# The complete list of option names and allowed values can be found
# in the PostgreSQL documentation. The commented-out settings shown below
# are example values.
#
#---------------------------------------------------------------------------
# REQUIRED PARAMETERS
#---------------------------------------------------------------------------
#
# restore_command
#
# specifies the shell command that is executed to copy log files
# back from archival storage. The command string may contain %f,
# which is replaced by the name of the desired log file, and %p,
# which is replaced by the absolute path to copy the log file to.
#
# It is important that the command return nonzero exit status on failure.
# The command *will* be asked for log files that are not present in the
# archive; it must return nonzero when so asked.
#
# NOTE that the basename of %p will be different from %f; do not
# expect them to be interchangeable.
#
restore_command = 'cp /data/archive_log/%f %p'
#
#
#---------------------------------------------------------------------------
# OPTIONAL PARAMETERS
#---------------------------------------------------------------------------
#
# recovery_end_command
#
# specifies an optional shell command to execute at completion of recovery.
# This can be useful for cleaning up after the restore_command.
#
#recovery_end_command = ''
#
#
# By default, recovery will rollforward to the end of the WAL log.
# If you want to stop rollforward before that point, you
# must set a recovery target.
#
# You may set a recovery target either by transactionId, or
# by timestamp. Recovery may either include or exclude the
# transaction(s) with the recovery target value (ie, stop either
# just after or just before the given target, respectively).
#
#recovery_target_time = '2004-07-14 22:39:00 EST'
#
#recovery_target_xid = '1100842'
#
#recovery_target_inclusive = 'true' # 'true' or 'false'
#
#
# If you want to recover into a timeline other than the "main line" shown in
# pg_control, specify the timeline number here, or write 'latest' to get
# the latest branch for which there's a history file.
#
#recovery_target_timeline = '33' # number or 'latest'
#
#
#---------------------------------------------------------------------------


[root@sebadest data]# rm -f pg_xlog/*
[root@sebadest data]# rm -f pg_xlog/archive_status*

11 - Inicie a instância no servidor de destino:
[root@sebadest data]# /etc/init.d/postgresql start
Starting postgresql service: [ OK ]

12 - Retire a instância de destino e origem do archive mode:
[root@sebadest data]# grep archive postgresql.conf
archive_mode = off # allows archiving to be done
#archive_command = 'rsync -arv %p /data/archive_log/%f' # command to use to archive a logfile segment
#archive_timeout = 0 # force a logfile segment switch after this


[root@sebadest data]# service postgresql restart
Stopping postgresql service: [ OK ]
Starting postgresql service: [ OK ]

13 - Teste os ajustes do item 12:
[root@sebaorig pgsql]# psql -U postgres
psql (8.4.5)
Type "help" for help.


postgres=# SELECT pg_start_backup('Cordeiro de Deus perdoai os pecados do mundo');
ERRO: arquivamento do WAL não está ativo
HINT: archive_mode deve ser habilitado ao iniciar o servidor.


14 - Valide a instância replicada no servidor de destino:
[root@sebadest data]# psql -U postgres
psql (8.4.13)
Type "help" for help.


postgres=# \l
List of databases
Name | Owner | Encoding | Collation | Ctype | Access privileges
----------------------+----------+----------+-------------+-------------+-----------------------
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres
: postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres
: postgres=CTc/postgres
(3 rows)


15 - Seja feliz, mas verifique no log da instância qual o ponto de consistência atingido do banco.  

segunda-feira, 18 de fevereiro de 2013

JBoss EAP 6 - Primeiros contatos



   Depois de trabalhar bastante com JBoss EAP 5.x por um tempo considerável, tive uma oportunidade impar de começar os trabalhos com o EAP 6, e melhor, migrar uma aplicação que vinha do 5.x, ou seja, utilizava frameworks antigos com relação ao do contêiner do 6.

   As principais mudanças que observei são:

1 - Possibilidade de gerenciamento de configurações do profile por domínio;
2 - Implementação do conceito de módulos, o que reduz o uso de memória da JVM;
3 - Alteração da interface de gerenciamento(console) e JBossCLI;
4 - Simplificação dos XMLs;
5 - HornetQ para mensageiria.

   Sei que existem mais alterações, entretanto para a ação de migração da aplicação em JSF que precisava foram os pontos mais observados.

   O que vale a pena citar do caminho da migração:

   Não utilizei bibliotecas do contêiner internas na aplicação, dupliquei a versão das mesmas no contêiner no diretório 'modules' e apenas na referência do 'jboss-deployment-structure.xml' excluí a versão 'main' e utilizei a do slot criado.     Bibliotecas de uso comum das aplicações que foram desenvolvidas pelo cliente coloquei como módulo também, para isso foi necessário alterar sua visibilidade.

   Todas as alterações relevantes foram executadas no XML 'domain', facilitando e muito o gerenciamento.

   Por boa prática utilizei o CLI para adicionar bibliotecas e DataSources, que agora são carregados como módulos também.

   Quanto a configuração do ModCluster, nenhuma novidade aparente, mas pude observar um melhor funcionamento do JGroups para comunicação entre os nodos do cluster. Outro item que deve ser levado em conta na configuração do cluster é o Infinispan, que gerencia o cache das aplicações.

   O bom deste primeiro contato "a quente" com o 6 foi ter que mexer bastante mesmo nele para fazer tudo funcionar 100%, e isso me agregou muito.     O que pude levar em resumo foi que a administração do JBoss melhorou muito, com a atualização dos frameworks muitos problemas foram solucionados.

    Nota 10 para o novo Enterprise.