terça-feira, 10 de novembro de 2015

Weblogic - Configurando ORDS para uso do APEX


      Bueno, em minhas atividades atuais com Weblogic precisei migrar o uso do APEX de um OHS para o Weblogic.

______________________________________________________________
APEX: https://apex.oracle.com/en/
OHS: https://docs.oracle.com/cd/E28280_01/web.1111/e10144/intro_ohs.htm#HSADM101
Weblogic: http://www.oracle.com/br/products/middleware/cloud-app-foundation/weblogic/overview/index.html
______________________________________________________________


     Para tal, é necessário usar o ORDS, que pode ser executado em standalone, Glassfish ou Weblogic, para a postagem corrente falaremos de seu uso no Weblogic.

Pré-requisitos
______________________________________________________________
- WLS instalado
- JDK instalado e JAVA_HOME configurado
______________________________________________________________

Premissas
______________________________________________________________
- HTTPS não será abordado;
- Instalação do APEX na database Oracle não será abordada;
- Comandos de configuração do WLST não serão foco do post.
______________________________________________________________


     Primeiramente baixe o ORDS no site da Oracle:
______________________________________________________________
http://www.oracle.com/technetwork/developer-tools/rest-data-services/downloads/index.html
______________________________________________________________

     Após o download extraia o pacote e visualizará um pacote 'ords.war', é esse pacote que utilizarás no Weblogic.

     Antes de nos preocuparmos com este WAR precisaremos criar um novo war com o conteúdo estático de imagens para o APEX, eles podem ser localizados no OHS, possívelmente em '/apex/images'.

    Faça a cópia de todo o conteúdo dessa pasta, pois precisaremos compactá-las em um WAR e implantar no Weblogic, utilize para tal o seguinte comando:
______________________________________________________________
java -jar ords.war static \images
______________________________________________________________

    Esse comando gerará o arquivo 'i.war', o qual tu farás a implantação no Weblogic com custom security roles(Custom Roles: Use roles that are defined in the Administration Console; use policies that are defined in the deployment descriptor).

    Bem, já temos as imagens, nos falta configurar no ORDS a database que tem o APEX instalado(a instalação do APEX na database Oracle não é o objetivo desta postagem), bem como criar um cluster no Weblogic que serão os alvos da aplicação do ORDS.

    Realize a criação de um cluster, pode ser via WLST ou Admin-Server do DAS, e garanta que exista ao menos um managed-server neste cluster, pode ser localizado no nodemanager do mesmo servidor que possui o DAS, sem problemas.

    Feito isto vamos configurar o ORDS, então para tal utilize o comando abaixo:

______________________________________________________________
java -jar ords.war install simple
______________________________________________________________

   Aqui precisará das seguintes informações:

Host da database onde o APEX foi instalado;
Porta da database onde o APEX foi instalado;
Usuário e senha de um usuário com grant de sysdba para instalação do usuário do ORDS;
Usuário e senha do usuário do APEX_PUBLIC_USER e demais usuários relacionados ao APEX;
Especificar um caminho de configuração dos parâmetros de configuração do ORDS, aqui é ideal utilizar uma pasta dentro do $MIDDLEWARE_HOME;

   Caso ocorra um erro de sintaxe na instalação do ORDS, usando um WinRAR ou extrair o 'ords.war' e edite o arquivo 'ords_create_rest_users.sql' e altere deixando como abaixo:
______________________________________________________________
create user ORDS_PUBLIC_USER identified by $minhasenha account unlock default tablespace ^PUB_DATATBS temporary tablespace ^PUB_TEMPTBS;
______________________________________________________________

     Onde $minhasenha é a senha que definiu na instalação.

     Feito isto, execute a desinstalação do ORDS e execute a instalação novamente.
______________________________________________________________
java -jar ords.war uninstall
java -jar ords.war install simple
______________________________________________________________

     Bueno, estamos pendente apenas com o deploy(implantação) pendente no WLS. Execute deixando como target(alvo) o cluster que criaste. Utilize também custom rules para security no processo de deploy. E se fez tudo corretamente o APEX estará disponível no endereço abaixo:

______________________________________________________________
http://localhost:9003/ords 

Onde localhost é o IP do(s) managedserver(s) que configuraste no cluster, e 9003 é a porta que o managedserver escuta. 
______________________________________________________________

   

quarta-feira, 26 de agosto de 2015

MySQL - Backup full e incremental com innobackupex



     Em um dos últimos projetos em que atuei precisei configurar uma rotina de backup no MySQL. Com isto veio a necessidade do uso do 'innobackupex', pois o mesmo me possibilitaria gerar backups completos e incrementais, sejam eles compactados ou não, sem downtime da instância de 1TB.

      Depois de ler diversos materiais relacionados a execução de backup remoto ou local, cheguei aos comandos abaixo, bem como as conclusões que seguem: 

  1. O backup incremental não foi de fato efetivo, pois a redução de armazenamento foi de 50% por backup com relação ao backup completo;
  2. A compactação durante a execução mostrou-se eficaz no sentido de espaço em disco, entretanto péssima para o tempo de execução do backup, pois o uso do 'gzip' fez com que a opção de multi-thread parasse e a compressão ficasse em um só core do processador;
  3. O comando de extração xbstream, quando utilizada a compressão de stream não funcionou, precisando do outro lado no servidor de destino utilizar ele diretório por diretório;
  4. Tar sem compressão foi a solução mais aderente. 

    Comandos utilizados:

Backup FULL:

     innobackupex --stream=tar /tmp | cat - > /disk2/backup-dir/full-base-backup/backup.tar

Aplicando os binlogs em caso de restore(para abrir a instância):

cd /data/mysql ; tar xvfi /mnt/backup.tar ; innobackupex --apply-log /data/mysql

Script de backup:

#!/bin/bash
#     Full backup mysql percona
# Developped by:
#     Gabriel Prestes - helkmut@gmail.com
# Last update:
#     2015-08-21
#
## DEFAULT SETTINGS ###########################################
BACKUP_DESTINATION='/disk2/backup-dir/full-base-backup'
HOST_NAME="teste.athore.org"
DAYS=3

source /etc/profile

## STOP EDITING HERE ###########################################

function remove() {
        log_this "Removing older than ${DAYS_TO_KEEP}"
find ${BACKUP_DESTINATION}/* -type f -name "${HOST_NAME}*" -mtime +${DAYS_TO_KEEP} | xargs ls -lha find ${BACKUP_DESTINATION}/* -type f -name "${HOST_NAME}*" -mtime +${DAYS_TO_KEEP} | xargs rm -fv

}

function log() {
        echo $(date "+[ %d-%m-%Y %H:%M:%S ]:") "${1}"
}

function start() {

        log "Starting backup job..."

        innobackupex --stream=tar /tmp | cat - > ${BACKUP_DESTINATION}/${HOST_NAME}-$(date "+%d-%m-%Y_%H-%M-%S").tar
        flag=$?

        if [ ${flag} -eq 0 ]; then

                echo "0" > /opt/resources/backup/percona-mysql-backup-agent.mon

        else

                echo "1" > /opt/resources/backup/percona-mysql-backup-agent.mon

        fi


        remove

        log "Job fished."
}


start


Crontab:

## Backup full daily Percona - MySQL

00 12   * /opt/resources/backup/percona-mysql-backup-agent.sh > /opt/resources/backup/percona-mysql-backup-agent.out 2>&1








      

quarta-feira, 27 de maio de 2015

Puppet - Exportando site.pp para CouchDB



   Quando estamos no caminho da automação de processos e garantia de estado uma das ferramentas poderosas e nossa aliada é o Puppet. 

   Quanto mais se conhece de Puppet, mais quer integrá-lo ao CouchDB para que o mesmo responda de forma inteligente consultas no formato JSON via Hiera. 

   O que essa publicação de propõe é a facilitar, apoiando-o na migração do site.pp dos seus ambientes, hoje com todas informações de classes, includes e tasks carregadas dos agents no site.pp e que serão exportadas para o CouchDB. 

   Segue abaixo a explicação de uso de um programa que criei para automatizar o processo de exportação. Ele já faz a análise se o agent existe no CouchDB, caso exista o mesmo ignora, do contrário, exporta para a base. 

   Repositório GIT do programa: https://github.com/helkmut/couchdb-populate

   Exemplo de execução: 

[root@Teste-CouchDB rb-couchdb-populate]# ./bin/rb-couchdb-populate.rb
| Starting agent Current Time : 2015-02-04 23:41:22 -0200 |
| Test database connection > configuration |
| Connection PASS |
| Directory /etc/puppet exist |
| Parse file /etc/puppet/environments/prd/manifests/site.pp |
| Import node 1.teste.com.br to CouchDB |
| Import node 2.teste.com.br to CouchDB |
| Import node 3.teste.com.br to CouchDB |
| Import node 4.teste.com.br to CouchDB |
| Import node 5.teste.com.br to CouchDB |
| Import node 6.teste.com.br to CouchDB |
| Import node 7.teste.com.br to CouchDB |
| Import node 8.teste.com.br to CouchDB |
| Import node 9.teste.com.br to CouchDB |
| Import node 10.teste.com.br to CouchDB |
| Import node 11.teste.com.br to CouchDB |
| Import node 12.teste.com.br to CouchDB |
| Import node 13.teste.com.br to CouchDB |
| Import node 14.teste.com.br to CouchDB |
| Import node 15.teste.com.br to CouchDB |
| Import node 16.teste.com.br to CouchDB |
| Import node 17.teste.com.br to CouchDB |
| Import node 18.teste.com.br to CouchDB |
| Import node 19.teste.com.br to CouchDB |
| Import node 20.teste.com.br to CouchDB |
| Parse file /etc/puppet/environments/dev/manifests/site.pp |
| Node 21.teste.com.br already exists in CouchDB |
| Import node 22.teste.com.br to CouchDB |
| Import node 23.teste.com.br to CouchDB |
| Import node 24.teste.com.br to CouchDB |
| Node 25.teste.com.br already exists in CouchDB |
| Node 26.teste.com.br already exists in CouchDB |
| Import node 27.teste.com.br to CouchDB |
| Node vagrant-teste.local already exists in CouchDB |
| Parse file /etc/puppet/environments/hlg/manifests/site.pp |
| Import node 28.teste.com.br to CouchDB |
| Import node 29.teste.com.br to CouchDB |
| Import node 30.teste.com.br to CouchDB |
| Node 31.teste.com.br already exists in CouchDB |
| Import node 32.teste.com.br to CouchDB |
| Import node 33.teste.com.br to CouchDB |
| Import node 34.teste.com.br to CouchDB |
| OK - Program end with success |

   O que o programa não contempla: 

1 - se o Document existir ele não atualiza os fields;
2 - ainda não está fazendo parse das 'tasks', mas faz de chamadas 'includes' e 'classes'.  

   Sugiro testar em um laboratório com uma Vagrant de CounchDB, hiera e Puppet Master. Naturamente que isto não se aplica a versão Enterprise do Puppet, que já não faz o gerenciamento dos agents por site.pp. 


quinta-feira, 4 de dezembro de 2014

MySQL - SQL thread is not running?



Imagine o seguinte cenário, você tem um MySQL master e um slave configurado com replicação assíncrona. Por alguma razão você descobre através da consulta de status do slave que o SQL thread parou de funcionar, mas o IO thread continua em execução buscando logs do master. 

COMO IDENTIFICAR A CAUSA DO PROBLEMA? 

        - Verifique o log de erro do MySQL, lá constará o código de erro gerado durante o processo de replicação, seja ela por row ou statement, e este código já lhe ajudará a buscar soluções na documentação. 

        - No mesmo log você poderá verificar qual a posição e binlog do master em que ocorreu o erro, isso será muito útil no futuro. 

        Consideraremos aqui neste exemplo que o erro foi causado por um SQL que violou uma CONSTRAINT de PK ou FK.

        O ERRO É DE VIOLAÇÃO E AGORA? 

 1 - Primeiramente utilizando o mysqlbinlog acesse o log binário do master indicado no erro do MySQL do slave e com o -j informe a posição;
2 - Ao identificar o STATEMENT ou ROW que foi executado/alterada você poderá acessar o MySQL master e comparar os dados da tabela alvo com a do slave;
3 - Aqui é certo que você identificará diferenças de integridade entre as tabelas, pois lembre que o slave está atrasado com relação ao master;
4 - Pule uma posição no log do master no slave: 

CHANGE MASTER TO MASTER_LOG_FILE = '$master_log_name' MASTER_LOG_POS = $master_log_pos+1; 

Viu agora o porquê da importância da posição do log lido no master? Onde $master_log_name e $master_log_pos podem ser obtidos ao consultar o status do slave

 5 - Feito isto ative o slave novamente:
     
START SLAVE;

Se nenhum outro erro ocorreu após o slave se atualizar em relação ao master(veja no status do slave) então é hora de verificar como ficaram os dados da tabela que apresentou o erro. COMO? 

        Se seu slave não tem delay setado e o fluxo de alterações e inserções da tabela não é constante podes realizar a validação por MD5SUM. COMO? 
mysql > \P md5sum 
mysql > select * from tabela_alvo; (não faça isso em tabelas gigantes!)
O resultado no master e slave devem ser o mesmo valor de md5. Para normalizar o client basta executar \P. 

Bom, se ainda assim tem diferenças na tabela alvo, considere ajustar os dados dela via dump com a function slave parada, ou ressincronizar o slave. 







quarta-feira, 13 de agosto de 2014

PostgreSQL - Acompanhando SQL via log

Ei você! Sim, você que precisa acompanhar DML/DDL/DCL via log, mas não sabe como, ai vai uma dica para acompanhar o mesmo via log em tempo real(depois que já executou, evidente): 


1 - logado por SSH no banco alvo execute :

watch -n 10 'tail -n 1500 /var/log/pgsql.log | grep -i -A 1 "MEU SQL"'

Em resumo de 10 em 10 segundos você ficará visualizando os SQLs, e caso seja um UPDATE/DELETE que os parâmetros sejam vistos somente na próxima linha será apresentado. 

Requisitos: 

1 - Cluster PGSQL com log configurado para o syslog/rsyslog;
2 - Log ser o pgsql.log no '/var/log';
3 - Ser Linux; 
4 - Log configurado para logar tudo ou pelo menos SQL por duration.