Como você pode usar efetivamente serviços da Web em um ambiente corporativo, se não pode usar transações?

14

O local em que estou trabalhando está tentando estabelecer algumas regras básicas, e o debate que estamos tendo agora é sobre bibliotecas locais versus serviços web para reutilização de código. Os serviços da Web parecem ser a escolha popular na maioria das empresas, e é para isso que a maioria dos desenvolvedores aqui está se inclinando.

Eu simplesmente não consigo ver como você pode usar efetivamente os serviços da Web para qualquer trabalho sério. Como executar com segurança várias chamadas de serviço se não posso usar uma transação?

Digamos que eu tenha um trabalho cron que agarre clientes do nosso banco de dados que atendam a uma determinada condição da qual precisam ser notificados. Eles recebem um fax, um email e um ticket é criado para rastrear o problema internamente. São três chamadas de serviço diferentes que aconteceriam para cada cliente em um loop for.

Se ocorrer um erro em qualquer lugar, é possível que, por exemplo, um fax e email sejam enviados ao cliente, mas um ticket não seja criado. Ou pior, esse trabalho cron pode conter um bug que faz com que falhe sempre no mesmo ponto e envia por e-mail repetidamente o mesmo cliente. Se as bibliotecas fossem todas locais, tudo poderia ser envolvido em uma transação e nada disso aconteceria. Mas estamos usando serviços da web neste exemplo.

Observe que os métodos de email e fax realmente inserem os dados nas tabelas de filas suportadas pelo banco de dados, que por sua vez são tratadas por um processo de tarefa cron separado. Portanto, as chamadas para os métodos de serviço "enviar email" e "enviar fax" podem ser canceladas sem efeito colateral, se necessário.

Uma opção é colocar todo esse pedaço de código no serviço da Web, para que o próprio serviço chame os métodos de criação de email, fax e ticket em uma transação. Mas então estamos criando um método de serviço da Web apenas para o uso de uma transação; não há razão válida para precisarmos chamar esse método de qualquer lugar, exceto esse script cron.

Como você geralmente lidaria com esse método?

ryeguy
fonte
Para fornecer uma resposta completa, preciso de mais informações. Há muitas coisas a considerar ao mudar para uma arquitetura baseada em serviço. Por exemplo, você tem um ambiente heterogêneo (diferentes idiomas e plataformas) ou homogêneo (único idioma e plataforma). Você possui um sistema de barramento de serviço? Se não, você planeja implementar um? Como você planeja acessar seus serviços (Intranet de local único, WAN de vários locais, cliente distribuído atingindo uma API de serviço público). Há várias variáveis ​​que afetam uma solução "ótima".
Michael Brown
@ MikeBrown: Os serviços seriam todos escritos em um idioma, mas consumidos por várias plataformas. Nenhuma idéia sobre a implementação de um EBS, nem começamos qualquer tipo de serviço, portanto tudo é possível. Os serviços seriam principalmente consumidos internamente em nossa rede local, mas haveria alguns que precisariam ser voltados ao público para aplicativos móveis.
ryeguy
"Se as bibliotecas fossem todas locais, tudo poderia ser envolvido em uma transação e nada disso aconteceria". Falso. O erro pode ocorrer após o envio do email, mas antes da atualização final do banco de dados. Uma transação não impede retroativamente o email ou o fax.
31512 S.Lott
@ S.Lott: Sim, porque as chamadas de serviço de e-mail e fax estão apenas inserindo-as em uma fila, que é entregue por um processo diferente. Se a transação que descrevi acima aconteceu, a inserção da fila seria abortada.
ryeguy
1
@ryeguy: Atualize a pergunta. Por favor, não adicione comentários à pergunta. Esta é uma parte importante da sua arquitetura. Divulgue-o na pergunta.
31512 S.Lott

Respostas:

5

O que você está descrevendo é de fato uma transação distribuída implementando confirmação de duas fases . Algumas plataformas de mensagens corporativas incluem gerenciadores de transações para oferecer suporte a esse tipo de coisa, mas produtos concretos dependem da plataforma / idioma. Não tenho experiência concreta com essas ferramentas, mas espero que esses indicadores ajudem.

Péter Török
fonte
3

É interessante que, ao participar desta sessão de perguntas e respostas, há um tópico semelhante sobre serviços que oferecem suporte a várias plataformas na lista de discussão DDD / CQRS da qual estou participando. Posso reiterar alguns dos meus conselhos aqui.

Uma opção para suportar transações em um ambiente heterogêneo é usar um mecanismo de transporte que ofereça suporte a transações e seja suportado em todas as plataformas a partir das quais será usado. O Protocolo avançado de fila de mensagens (AMQP) oferece suporte a transações e existe uma API nativa para quase todos os idiomas mais usados ​​atualmente. RabbitMQ é um servidor que implementa o AMQP e foi avaliado na indústria como uma solução robusta.

A alavancagem de um sistema baseado no RabbitMQ coloca você no caminho de ter um ESB completo, caso precise crescer nele. Você publica mensagens em um canal e assina uma fila. Onde isso fica realmente poderoso é que entre o canal e a fila, você pode executar muitas coisas interessantes. Um canal pode alimentar várias filas (pub / sub), uma fila pode ser alimentada por vários canais, você pode rotear mensagens para diferentes filas com base no conteúdo, etc. etc.

Eu estava lendo sobre alternativas para transações (que vêm com sobrecarga e transformam uma operação assíncrona em uma operação de bloqueio). O RabbitMQ suporta o que é chamado de confirmação de editor . Basicamente, permite registrar um retorno de chamada para um método publicado para lidar com uma transação com falha. No seu caso, isso pode desfazer as solicitações de email / fax e excluir o ticket.

É claro que a toca do coelho (perdoe o trocadilho) vai ainda mais fundo a partir daí. Você pode usar o Rabbit para fazer orquestrações complexas com serviços da Web internos e externos.

Para os serviços da web voltados para o público, torna-se simples. Seu serviço (seja SOAP, REST ou JSON) apenas publica uma mensagem na fila de serviço apropriada e deixa seu sistema interno lidar com isso a partir daí.

Também há funcionalidade para criar uma mensagem de solicitação / resposta para os cenários em que você espera que as informações retornem rapidamente.

Michael Brown
fonte
2

As palavras-chave que você procura são 'coreografia de serviços da web'.

Confira o artigo da Wikipedia sobre isso.

Dibbeke
fonte
Às vezes chamado de "orquestração" também.
31512 S.Lott
1

A maneira como lidei com isso em um aplicativo de serviços que escrevi foi criar um wrapper para lidar com as transações necessárias. No meu caso, a solicitação do usuário, feita por site, aplicativo de desktop ou serviço do Windows, teve que consultar um serviço da web e, com base no resultado e nas opções do usuário, precisou atualizar um banco de dados local e, opcionalmente, um remoto através de um serviço da web. Em seguida, foi necessário gerar um relatório para ser retornado imediatamente, enviado por e-mail e / ou fax. Eu tinha controle sobre o banco de dados local, geração de e-mail e relatório, mas nenhum sobre os serviços web ou o servidor de fax.

A criação de um wrapper permitiu um melhor controle de transações e manipulação de erros. Também permitiu uma melhor segurança, controlando o acesso aos serviços de rede internos de fontes externas. Em geral, vejo a necessidade de transações e gerenciamento do serviço como um motivo válido para criar um wrapper apropriado para uma única solução, desde que o código seja reutilizado corretamente (sem codificação cut-n-paste).

jfrankcarr
fonte
1

Eu simplesmente não consigo ver como você pode usar efetivamente os serviços da Web para qualquer trabalho sério. Como executar com segurança várias chamadas de serviço se não posso usar uma transação?

Você não pode.

A pergunta que você deve fazer é: como implementar transações com a estrutura de serviço da web X? No momento, você está assumindo que é impossível.

Mike Baranczak
fonte