Entrega da mensagem JMS antes que a transação seja cometida
-
19-09-2019 - |
Pergunta
Eu tenho um cenário muito simples envolvendo um base de dados e a Jms em um servidor de aplicativos (Glassfish). O cenário é morto simples:
1. an EJB inserts a row in the database and sends a message.
2. when the message is delivered with an MDB, the row is read and updated.
O problema é que às vezes o a mensagem é entregue antes que a inserção seja cometida no banco de dados. Isso é realmente compreensível se considerarmos o protocolo de confirmação de 2 fases:
1. prepare JMS
2. prepare database
3. commit JMS
4. ( tiny little gap where message can be delivered before insert has been committed)
5. commit database
Eu discuti esse problema com outros, mas a resposta sempre foi: "Estranho, deve funcionar fora da caixa".
Minhas perguntas são então:
- Como poderia funcionar fora da caixa?
- Meu cenário parece bastante simples, por que não há mais pessoas com problemas semelhantes?
- Estou fazendo algo errado? Existe uma maneira de resolver esse problema corretamente?
Aqui estão um pouco mais de detalhes sobre minha compreensão do problema:
Esse problema de tempo existe apenas se o participante for tratado nesta ordem. Se o 2PC tratar os participantes na ordem inversa (primeiro banco de dados, depois o corretor de mensagens), isso deve ficar bem. O problema estava acontecendo aleatoriamente, mas completamente reproduzível.
Não encontrei nenhuma maneira de controlar a ordem dos participantes nas transações distribuídas nas especificações JTA, JCA e JPA, nem na documentação do Glassfish. Poderíamos assumir que eles serão alistados na transação distribuída de acordo com a ordem quando forem usados, mas com um ORM como JPA, é difícil saber quando os dados são liberados e quando a conexão do banco de dados é realmente usada. Qualquer ideia?
Solução
Você está experimentando a condição clássica de corrida XA 2-PC. Isso acontece em ambientes de produção.
Há 3 coisas chegando à minha mente.
- Última otimização do agente, onde o JDBC é o recurso não-XA. (Perca a semântica da recuperação)
- Tenha JMS Time-T-DeLike. (Deliberadamente perder tempo real)
- Construa as tentativas no código JDBC. (Menos efeito na funcionalidade)
O WebLogic tem essa otimização de LLR evita esse problema e oferece todas as garantias do XA.