Durante o processo de desenvolvimento, foi encontrado um bug. O motivo do bug foi que a transação da primavera enviou mensagens de produção depois da fila de mensagens, resultando em dados incorretos obtidos quando a fila de mensagens consome mensagens. Este artigo apresenta o surgimento de problemas e o processo de resolução passo a passo.
1. Problema que surge:
Restauração do cenário: um método na interface, primeiro modifique o status do pedido e depois produz mensagens da fila de mensagens. O consumidor da fila de mensagens obtém o status da ordem de detecção de mensagens e descobre que o status do pedido não foi alterado.
Código:
@Service (OrderApi) Classe public OrderApiImpl implementa OrderApi {@Resource MQService MQService; @OrderDao OrderDao; public void push (string OrderId) {// Atualize o status do pedido, o status anterior era 1 updateStatus (OrderId, 3); // gerar a mensagem MQService.produce (OrderId); } public viod updatestatus (string orderId, status inteiro) {orderdao.updatestatus (OrderId, status); }}O motivo do problema: todos os métodos do OrderApi têm transações e o tipo de transação propagation_required; portanto, a operação do método push nos dados será enviada após o envio de todo o código push. Antes da transação ser enviada, a mensagem da fila de mensagens foi gerada; portanto, o status do pedido consumido na consulta da fila de mensagens do banco de dados pode ser 1. Para tornar o bug mais óbvio, você pode adicioná -lo no final do método push:
tente {thread.sleep (10000);} catch (interruptedException e) {// TODO BLOCO DE CAPAGEM AUTOMENTADO E.PrintStackTrace ();}Dessa forma, você descobrirá que o status do pedido não deve ter sido modificado quando a mensagem de consumo for consumida.
2. Solução para o problema:
Solução: Ao atualizar os dados, crie uma coisa nova para garantir que, após a execução do código de atualização, a transação que atualiza o banco de dados foi comprometida. (Verifique se a operação do banco de dados foi enviada antes da geração da mensagem)
De acordo com o esquema acima, a primeira coisa que penso é modificar diretamente o tipo de transação do método Updatestatus; Alterei o tipo de transação desse método para propagação_requires_new (crie uma nova transação, se a transação existir atualmente, suspenda a transação atual).
Mas há duas coisas inadequadas para fazer:
1. A modificação forçada do tipo de transação UpdateStaus pode afetar outros processos.
2. Não está funcionando, nenhuma nova transação foi criada no método UpdateStaus.
Explicação sobre o segundo ponto: a primavera adiciona transações através do BeannameautoProxyCreator, que adiciona apenas transações aos objetos de feijão. Agora, chamar métodos dentro da classe não acionará a criação de coisas novas.
Então, depois de tentar o exposto, criei uma nova classe:
@Service ("OrderextApi") Public class OrderextApiImpl {@Resource OrderApi OrderApi; public void updateStatusNewPropagation (String OrderId) {OrderApi.UpDatestatus (OrderId); }}e adicione a transação propagação_requires_new para updatestatusnewpropagation método
Esta classe é apenas para criar uma nova transação para o método UpdateStaus em OrderApi.
OK, até agora o bug foi resolvido.
No entanto, ainda existem problemas no código: a operação do banco de dados foi enviada e, se houver uma exceção na mensagem de produção, ele ainda está errado para a lógica de negócios. Portanto, é necessário detectar se a geração de mensagens está concluída.
O código no OrderApi final é o seguinte:
@Service (OrderApi) Classe public OrderApiImpl implementa OrderApi {@Resource MQService MQService; @Resource OrderDao OrderDao; @Resource OrderextApiImpl ordeRextApi; public void push (string orderId) {// Atualize o status do pedido, o status anterior era 1 ordeRextApi.UpDatestatusNewPropagation (OrderId, 3); // Gerate Message --produce detectará se ocorre uma exceção. Quando 1 é devolvido, isso significa que a mensagem de produção é bem -sucedida. Resposta resposta = mqservice.produce (OrderId); if (Response.getCode ()! = 1) {log.info ("Exceção da mensagem de produção da fila de mensagens:" + Response.GeterRormSg ()) // Exceção da mensagem de produção, redefina o status e aguarde a próxima reexecução ordeRextApi.UpDatSatusNewPropagation (OrderId, 1); }} public viod updatestatus (string orderId, status inteiro) {orderdao.updatestatus (orderId, status); }}O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.