quarta-feira, 31 de julho de 2013

PostgreSQL - Rotina de VACUUM optimizada



   Primeiramente devo agradecer ao Fabrízio Mello(http://fabriziomello.blogspot.com.br/) que trabalhou junto comigo na rotina abaixo.

CENÁRIO: Base 24x7 em uma base de quase 500GB.

PROBLEMA: Optou-se por tornar o auto-vacuum mais agressivo para não impactar no ambiente durante o horário comercial, mas o VACUUM na base inteira ainda que executado no domingo demorava muito, mesmo com alteração dos parâmetros de memória.  

SOLUÇÃO: Em conjunto com o Fabrízio Mello, o qual tem minha indicação incondicional, elaboramos a rotina abaixo através do PgAgent em um job de BATCH:

#!/bin/bash

PGUSER="postgres"
PGPORT="5432"
PGDATABASE="postgres" 
PGHOST="localhost"

export PGUSER PGPORT PGDATABASE PGHOST

START="00:00:00"
END="06:00:00"
LIMIT="20"

SQL="
SELECT 'VACUUM ANALYZE VERBOSE '||quote_ident(schemaname)||'.'||quote_ident(relname)||';'
  FROM pg_stat_user_tables
 WHERE (n_dead_tup+n_live_tup)>0
 ORDER BY (n_dead_tup * 100)/(n_dead_tup+n_live_tup) desc
 LIMIT ${LIMIT};"

echo "Iniciando rotina de vacuum:" > /tmp/vacuum-maintenance-$PGDATABASE-v2.log

psql -Atq -c "$SQL" | while read i
do
 now=$(date +%H%M%S)
 if [[ "$now" == "$START" || "$now" > "$START" &&
   "$now" < "$END" || "$now" == "$END" ]]
 then
  psql -c "$i" >> /tmp/vacuum-maintenance-$PGDATABASE-v2.log 2>&1
 
 fi
done




Em resumo o job realiza VACUUM ANALYZE nas 20(quantidade definida com o parâmetro LIMIT) tabelas que mais tem tupulas mortas. Entretanto a execução ocorre apenas entre o START e o END que for definido no job, caso finalize a tabela 19 e o horário for maior que o definido em END o job é finalizado sem realizar o VACUUM ANALYZE na tabela 20 da query. O resultado podes ver em /tmp/vacuum-maintenance-$PGDATABASE-v2.log onde $PGDATABASE é o nome da base alvo do BATCH.

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.