Ajuda com agendamento

Boa noite.

Bom, a princípio minha dúvida pode parecer ser esclarecida com uma resposta simples: Timer.

Pois bem, explicarei o problema e o cenário que me levantou dúvidas quanto a essa estratégia.

Seguinte, quando acontece um determinado tipo de evento no meu sistema preciso gerar um alerta na aplicação em tempo real a cada, digamos, meia hora. Caso ocorra um outro evento essa geração de alerta deve ser abortada.
Pensei da seguinte maneira, quando acontecer esse evento eu lanço um timer que a cada meia hora registra essa ação desejada. Quando ocorrer outro evento que cuminaria na finalização desse evento simplesmente cancelo o timer. Até aí tudo bem.

O problema é que esse tipo de evento é lançado para cada usuário do sistema múltiplas vezes por dia (estamos falando na ordem de centenas de usuários, quiçá milhares).
Daí eu cairia num problema grave de agendar um timer pra cada um, onde em um teste de estresse que fiz hoje não se mostrou nada bem (no caso de TimerService persistente deu pau com 100 Timers, não-persistente chegou a algo próximo de 4200 até ter um OutOfMemory).

Uma solução encontrada seria criar um único timer em polling para verificar esse evento sempre (em um tempo menor de agendamento, pra aumentar a precisão), mas isso não me parece muito inteligente…

Espero ter conseguido explicar a minha situação e o por quê da minha dúvida.

A claro, os recursos disponíveis consistem em JBoss 4.2.3 e JDK 1.5 (não me perguntem por que) e quem sabe mais algum framework (tipo quartz).

Qual seria uma aproximação de algo que vocês escolheriam como solução candidata?!

Obrigado!

Como assim?

Injeto um javax.ejb.TimerService e pelo método getTimers() obtenho os timers existentes, podendo controla-los caso esses não tenham sido executados.

Esses eventos são gerados de acordo com comportamentos do próprio sistema e provenientes de vários atores como o usuário ou mesmo outros sistemas.

O que são executores de eventos em Stand by?

Na verdade esses alertas são gerados a cada determinada fração de tempo (no exemplo meia hora) sendo iniciado quando ocorrer um evento provenientes daquelas situações descritas e finalizadas quando eventos de outra natureza serem disparados.

Não sei se entendi muito bem, mas existe a necessidade de se rodar 30 min depois?

Por que se não, vc poderia colocar essa lista de eventos em uma queue única e colocar múltiplos “Processadores de Evento” para executar o que precisa ser feito.

[quote=deniswsrosa]Não sei se entendi muito bem, mas existe a necessidade de se rodar 30 min depois?

Por que se não, vc poderia colocar essa lista de eventos em uma queue única e colocar múltiplos “Processadores de Evento” para executar o que precisa ser feito.[/quote]

Existe sim.
É que, além de registrar esse evento (a cada 30 minutos) precisa gerar um aviso pro operador.

Humm… e vc não pode fazer da forma que eu falei acima gerar o aviso ao operador com uma data de “validade”!? por exemplo, o evento acaba se ser gerado, vc o processa e gera a mensagem para o operador, porém grava a mensagem com uma data de inicio de validade, ou seja, a mensagem só vai ser válida daqui meio hora.

Simplesmente quando você efetuar a busca das mensagens que o operador deve receber, você pode passar o horário atual do servidor. funciona? quais seriam os possíveis problemas para você? entendi certo o seu fluxo?

Você tentou usar um java.util.concurrent.ScheduledThreadPoolExecutor fora do container?

Então, vamos la.
Vou tentar descrever melhor a situação:

Supondo que aconteça um evento A o sistema deve iniciar uma contagem que a cada 30 minutos avise a um outro sistema (de outra consultoria do cliente).
Caso ocorra um evento B essa contagem deve ser cancelada.

É muito importante que esse outro sistema receba sempre o aviso corretamente a cada trinta minutos (salvo uma pequena margem de segurança).

Detalhe, esses eventos são para cada usuário, que fica na casa de algumas centenas simultâneas, lembrando que o evento A de um usuário é somente dele e caso algum outro usuário gere um evento B esse deve cancelar apenas o seu contador.

Entenderam o problema?

Eu fiz uns testes com TimerService, funcionou da forma como queria, mas com poucas centenas não funcionou direito. Desativei a persistência do TimerService e consegui até quatro mil e pouco simultâneos, até dar pau, mas não senti confiança na estratégia.

To pensando numa solução com uma Queue conforme você havia sugerido e alguns “processadores” em paralelo rodando em polling… não gosto da idéia de polling, mas não vai ter mto jeito rsrsrs…

Alguma outra sugestão? Complementação?

Não curto muito a idéia, além de não ser tão eficiente contra o problema descrito quando lancei muitos TimerServices é altamente não recomendado lançar threads de dentro de um conteiner JEE.

Enfim, no final das contas serei obrigado a usar um polling…
Não queria usar essa estratégia, queria algo mais… inteligente rsrs
Mas vou aproveitar a idéia da Queue e simular uma espécie de cache, transparente ao polling, pra evitar chamadas excessivas ao banco (ainda mais pq depende de um serviço disponibilizado pelo sistema da outra consultoria).

Mais sugestões?
Obrigado galera!

[quote=Tchello]

Não curto muito a idéia, além de não ser tão eficiente contra o problema descrito quando lancei muitos TimerServices é altamente não recomendado lançar threads de dentro de um conteiner JEE.[/quote]

Primeiro: é eficiente em termos de memória. Teste antes de afirmar. Eu testei com 100mil eventos agendados e não fez cócegas na minha máquina de 2gb de RAM.
Segundo: eu sugeri que você criasse um serviço fora do container.

[quote=esmiralha][quote=Tchello]

Não curto muito a idéia, além de não ser tão eficiente contra o problema descrito quando lancei muitos TimerServices é altamente não recomendado lançar threads de dentro de um conteiner JEE.[/quote]

Primeiro: é eficiente em termos de memória. Teste antes de afirmar. Eu testei com 100mil eventos agendados e não fez cócegas na minha máquina de 2gb de RAM.
Segundo: eu sugeri que você criasse um serviço fora do container.[/quote]

Desculpe-me caso meu post tenha soado rude, não foi a minha intenção.
Deixe-me explicar um pouco melhor o cenário de ambiente, não tenho a opção de usar algo fora do conteiner, devo me ater ao que o servidor de aplicações suporta e soluções híbridas acabariam saindo do escopo.

Outra coisa, os recursos do ambiente são limitados, embora sejam máquinas bem parrudas em produção será difícil justificar um uso excessivo dessas threads e mais difícil ainda do cliente aceitar, ele já é conhecido por ser bem linha dura nesse quesito =/

De qualquer maneira, agradeço as sugestões e novamente peço desculpas pela rispidez do meu comentário.

Como voce vai controlar os eventos disparados?

Esses eventos gerados pelo sistema, como controla? Ex. Os eventos que devem disparar alertas estão configurados no código?

Resumindo o que eu entendi:

Atores “geram” eventos que disparam alertas dentro da aplicação (JBoss);
Cada alerta, deve ser mantido até o momento de ser executado;

  • Problema: Muitos atores, muitos eventos, consequentemente, muitos alertas sobrecarregando o AppServer.

    Imagino que manter um único Timer e reduzindo o tempo de agendamento ainda poderá te trazer problemas, porque poderiam haver picos de eventos que poderiam sobrecarregar o server.

Será que o Timer não pode ser substituido por uma requisição em tempo real? Ex. Ao invés de ter um executor de eventos agendados, teria um executor de eventos em Stand By ?