Devido a este problema decidi escrever um artigo mostrando como podemos utilizar a linguagem de scripts do Weblogic Server, Weblogic Scripting Tool(WLST), para fazer monitoramento de servidores. Um ponto importante nestes script é que ele permite inclusive que este monitoramente seja feito de forma independente do Admin Server, pois neste caso, o script mostra conexão direta com servidores gerenciados de um domínio. Para escrevê-lo estou utilizando WLST que por sua vez utiliza linguagem Jython e é padrão para configuração do Oracle Weblogic.
O script:
O script demonstrado aqui é bem simples e o que ele faz basicamente é:
1) Carregar informações de um arquivo de propriedades.
2) Tenta conectar com cada um dos servidores da lista de servidores configurada no arquivo de propriedades.
3) Verifica status do servidor e caso o servidor estiver com um número maior que o definido de threads com delay na resposta gera um thread dump do servidor para posterior análise.
Abaixo segue o código do script comentado e logo em seguida um exemplo de arquivo de propriedades que pode ser utilizado como template.
from java.util import Properties from java.io import FileInputStream from java.io import File #============DEFINICAO DE FUNCOES============ #funcao que carrega dados de arquivo de propriedades def carregaArquivoPropriedades(nomeArquivo) : print 'carregando propriedades do arquivo: ' + nomeArquivo #arquivo de propriedades a ser carregado localizacaoArquivoPropriedadesConfiguracao = nomeArquivo myProps = Properties() #carrega arquivo de propriedades myProps.load(FileInputStream(File(localizacaoArquivoPropriedadesConfiguracao))) return myProps #funcao que retorna lista de todos os servidores configurados para este domínio. def getServidoresDominio(): print 'executando funcao getServidoresDominio'] domainConfig() servidores = cmo.getServers() return servidores #funcao que pega lista de servidores como parametro e verifica o status de cada um deles. def mostraStatusServidores(servidores): print '=======================STATUS dos servidores do domínio===============' domainRuntime() for servidor in servidores: try: cd('/ServerRuntimes/' + servidor.getName()) #ls() print servidor.getName() + ': ' + get('State') except WLSTException,e: servidoresNaoAcessiveis.append(servidor) servidoresAlerta = [] #testa novamente servidores que não estava acessíveis para ter certeza for servidor in servidoresNaoAcessiveis : try: cd('/ServerRuntimes/' + servidor.getName()) #ls() print servidor.getName() + ': ' + get('State') except WLSTException,e: servidoresAlerta.append(servidor) if len(servidoresAlerta) > 0 : print 'ALERTA == ALERTA == ALERTA == ALERTA == ALERTA == ALERTA ==' print 'Os seguintes servidores estão inacessíveis para monitoração, favor checar!' for servidor in servidoresAlerta : print servidor.getName() #faz checagem de memória nos servidores do domínio especificado. def listaConfiguracoesMemoriaServidoresDomino(): servidoresComBaixoHeapMemoria = [] for servidor in servidores: try: cd("domainRuntime:/ServerRuntimes/" + servidor.getName() + "/JVMRuntime/" +servidor.getName()) heapSizeMax = cmo.getHeapSizeMax()/1048576 heapMemoriaLivre = cmo.getHeapFreeCurrent()/1048576 heapMemoriaLivrePercentagem = cmo.getHeapFreePercent() #adiciona na lista de servidores com pouca memoria se servidor tiver menos de 2% de memória livre if heapMemoriaLivrePercentagem < 2 : servidoresComBaixoHeapMemoria.append(servidor) #memoriaMB = memoria/1048576 #transforma os bytes em MB para mostrar print '\n=================================================================' print "O servidor " + servidor.getName() + " esta com :" print 'Memoria total alocada(MB): ' + str(heapSizeMax) print 'Memoria total disponivel(MB): ' + str(heapMemoriaLivre) print 'Memoria livre(%): ' + str(heapMemoriaLivrePercentagem) except WLSTException,e: print 'AVISO: O servidor ' + servidor.getName() + ' nao esta acessivel atraves do admin server' #faz novo teste de heap de memória e caso continuem com pouca memória disponível, mostra ALERTA para observação do servidor. for servidor in servidoresComBaixoHeapMemoria : try: cd("domainRuntime:/ServerRuntimes/" + servidor.getName() + "/JVMRuntime/" +servidor.getName()) except WLSTException,e: print 'AVISO: O servidor ' + servidor.getName() + ' nao esta acessivel atraves do admin server' heapMemoriaLivrePercentagem = cmo.getHeapFreePercent() #adiciona na lista de servidores com pouca memoria se servidor tiver menos de 2% de memória livre if heapMemoriaLivrePercentagem < 2 : print 'ALERTA == ALERTA == ALERTA == ALERTA == ALE RTA == ALERTA ==' print 'O servidor ' + servidor.getName() + ' está com heap de memória < que 2% e deve ser observado!' #faz checagem de threads dos servidores do domínio def checaThreadsServidoresDominio() : servidoresComThreadsProblematicas = [] for servidor in servidores : try: cd("domainRuntime:/ServerRuntimes/" + servidor.getName() + "/ServerChannelRuntimes/DefaultSecure[https]") numeroConexoes = cmo.getConnectionsCount() print '===============================================' print 'Dados do servidor ' + servidor.getName() + ': ' print 'Conexoes https: ' + str(numeroConexoes) cd('domainRuntime:/ServerRuntimes/' + servidor.getName() + '/ExecuteQueueRuntimes/weblogic.socket.Muxer') fila = cmo.getPendingRequestCurrentCount() print 'Requisicoes de usuarios pendentes: ' + str(fila) cd('domainRuntime:/ServerRuntimes/' + servidor.getName() + '/ThreadPoolRuntime/ThreadPoolRuntime') hoggingThread = cmo.getHoggingThreadCount() print 'Quantidade de threads com status hogging: ' + str(hoggingThread) print '===============================================\n' except WLSTException,e: print 'Erro servidor não acessivel para ServerRuntimes ==>> ' + servidor.getName() #faz health check nos pools de conexao do ambiente. def checaPoolsConexoes() : domainConfig() #recupera lista de pools de conexões configuradas no domínio. connectionPools = cmo.getJDBCSystemResources() for pool in connectionPools : print pool.getName() cd('domainConfig:/JDBCSystemResources/' +pool.getName()+ '/JDBCResource/' +pool.getName()+ '/JDBCConnectionPoolParams/' + pool.getName()) print '===============================================' print 'Dados do pool: ' + pool.getName() capacidadeInicialPool = cmo.getInitialCapacity() capacidadeMaximaPool = cmo.getMaxCapacity() print 'Capacidade maxima do pool: ' + str(capacidadeMaximaPool) cd('domainConfig:/JDBCSystemResources/' + pool.getName()) targetServers = cmo.getTargets() print 'targets do pool' for targetServer in targetServers : print targetServer.getName() #=================FIM DEFINICAO DE FUNCOES====================== propriedades = carregaArquivoPropriedades('config.properties') username = propriedades.get('username') password = propriedades.get('password') url = propriedades.get('url') connect(username, password, url) #lista para armazenar servidores não acessíveis através do admin server. servidoresNaoAcessiveis = [] servidores = getServidoresDominio() mostraStatusServidores(servidores) listaConfiguracoesMemoriaServidoresDomino() checaThreadsServidoresDominio() checaPoolsConexoes() disconnect() exit()
E o arquivo de propriedades de exemplo:
#este arquivo de propriedades é utilizado para configurar os #servidores em um ambiente. Todas as chaves devem ter o formato #do nome utilizando sempre _ (underscore) pois é o que define a #busca dos nomes dos elementos e separa durante a configuarção #no script criaInstancias.py USUARIO_ADMIN=user SENHA_ADMIN=pwd PORTA_HTTPS_SERVIDORES=443 #parametro que configura com que quantidade de threads com delay o thread dump deve ser tirado para o servidor. PARAMETRO_THREAD_DUMP=10 #Dados dos servidores a serem monitorados pelo script SERVIDOR_1=server1 IP_SERVIDOR_1=xxxxxx SERVIDOR_2=server2 IP_SERVIDOR_2=xxxxxxx SERVIDOR_3=server3 IP_SERVIDOR_3=xxxxxx SERVIDOR_4=server4 IP_SERVIDOR_4=xxxxxx # .... you may add as many servers as you want here...
Para este script ficar realmente funcional eu programaria para que ele ficasse conectado com os servidores por um período definido em ciclos e que verificasse o status de cada um de tempos em tempos(3 em 3min por exemplo). E caso o servidor apresentasse algum problema considerável dispararia uma rotina que seria responsável por tirar thread dumps com intervalo de cerca de 20s entre um e outro por um período de 2 min. Os thread dumps retirados seriam de extrema utilidade para definir qual o real problema com o ambiente.
[]s