Arquivo mensais:outubro 2012

Synchronous x Asynchronous Services – Parte 2

Livro Service Design Patterns

Olá pessoal,

No post anterior vimos alguns padrões para modelos de processamento síncronos de web services. Vimos também os problemas decorrentes destes padrões, como por exemplo, o acoplamento temporal, que está relacionado à dependência que consumidores de serviços síncronos possuem com relação ao tempo de processamento do serviço, para que a operação seja bem sucedida. Problemas com estouro do tempo de resposta previsto (timeout) podem fazer com que mensagens sejam perdidas, diminuindo a confiabilidade da abordagem. Outros problemas relacionados também são, por exemplo, a dependência com relação à disponibilidade de todos os demais sistemas subjacentes ao serviço (sistemas gerenciadores de banco de dados, rede, servidores de aplicação, sistema de arquivos, etc.). Caso haja qualquer indisponibilidade em tais componentes, consumidores de serviços síncronos são diretamente afetados. Além disso, cargas acima do planejado em serviços que implementam o padrão Request/Response comprometem seu funcionamento e o da infraestrutura que o suporta, uma vez que todas as requisições são processadas assim que recebidas, dado o fato de que o número de requisições a serem processadas em paralelo é, em geral, comandado pelo cliente.

Para endereçar tais questões, no livro Service Design Patterns é sugerido à utilização de padrões assíncronos, e a utilização de message queues seria uma alternativa. Tal mecanismo permite que um cliente envie uma mensagem para uma fila remota em qualquer horário, independentemente do estado operacional do sistema destino. Usualmente, mensagens são salvas em filas locais até que as filas destino estejam disponíveis. Consumidores de mensagens podem proteger recursos dos sistemas remotos pela implementação de mecanismos de “throttling” (afunilamento – controle da taxa de Fluxo do padrão Request/Acknowledgeprocessamento de mensagens), desta forma endereçando requisitos de escalabilidade e disponibilidade de forma mais eficiente do que o padrão síncrono Request/Response visto anteriormente.

Se por um lado a utilização de message queues resolve boa parte dos problemas, por outro, novos problemas podem ser introduzidos. O uso de mensageria, em geral, é aconselhado como uma abordagem interna à corporação, ou seja, não deveria ser exposto diretamente além do firewall corporativo, seja por questões de segurança, seja por acoplar consumidores externos às tecnologias específicas dos sistemas de mensageria.

Para endereçar tais questões, é sugerida então a utilização do padrão de web services Request/Acknowledge, no qual um web service recebe uma requisição, a encaminha para um processo em background (uma thread secundária, por exemplo) e então retorna uma mensagem ao consumidor (acknowledgment) contendo um identificador único para referência futura. Veja como isso funciona no diagrama de sequencia ao lado (direito).

Em diversas situações apenas o recebimento de um “acknowledgment” é suficiente para o consumidor saber que sua requisição foi armazenada para processamento posterior. Porém, em outras situações, um cliente pode precisar de uma resposta, seja, por exemplo, de um processo de longa duração iniciado pela requisição inicial. Imagine um cenário em que uma requisição é enviada contendo uma solicitação de compra. Um retorno (acknowledgment) é enviado para consumidor informando que a solicitação foi recebida e que será processada. Um acknowledgment contendo um ID único serve como um protocolo de recebimento, um recibo. Quando todos os processos de aprovação da compra (sejam automáticos ou manuais) forem finalizados, o que pode demorar horas ou dias, dependendo do processo da organização, o cliente deverá ser informado, para que possa tomar outras ações.

Existem três formas no qual o padrão Request/Acknowledge permite prover respostas assíncronas aos consumidores de serviços. Vejamos a seguir.

Request/Acknowledge/Poll

Fluxo do padrão Request/Acknowledge/PollNeste padrão, uma vez que o cliente possui um acknowledge contendo um identificador único da sua requisição, ele fica constantemente consultando um outro serviço pelo resultado do seu processamento. Veja no diagrama de sequencia ao lado (esquerdo) a ilustração do fluxo deste padrão.

Os problemas decorrentes da utilização deste padrão estão relacionados ao intervalo de tempo em que o cliente efetua consultas pelo resultado final da operação. Se o intervalo de tempo for alto, então poderá haver um atraso entre o tempo em que o resultado final está pronto e o tempo em que ele é obtido. Se for baixo, então uma carga excessiva poderá ser colocada nos servidores envolvidos, além de aumentar trafego de rede.

Request/Acknowledge/Callback e Request/Acknowledge/Relay

No padrão Request/Acknowledge/Callback ao invés do cliente ficar constantemente buscando pelo resultado final da operação, ele é avisado através de um serviço que ele deve prover ou através do encaminhamento para outras partes interessadas. Esta última variação descreve o padrão Request/Acknowledge/Relay. A vantagem de tais abordagens com relação ao Request/Acknowledge/Poll está no tempo em que o cliente receberá a resposta e nos recursos consumidos para tal. Veja no diagrama de sequencia a mais abaixo (à direita) a ilustração do fluxo descrito.

Note que a forma pela qual o processador de requests pode saber para qual serviço ele deve retornar o resultado pode ser tanto através de um endereço provido no request inicial, pelo próprio cliente (veja, por exemplo, WS-Addressing), quanto através de configurações que relacionem o tipo de mensagem / processamento aos destinatários interessados (relay). Quando os destinatários de mensagens de callback são especificados pelo consumidor, cuidados especiais devem ser tomados para que eles não sejam alterados no meio do caminho. Segurança no nível de transFluxo do padrão Request/Acknowledge/Callbackporte ou mesmo WS-Security podem ser usados para mitigar este risco.

Algumas considerações devem ser levadas em conta antes de optar por um dos padrões. Em geral, o padrão Request/Acknowledge/Poll é mais simples de se implementar e de se depurar do que o padrão Request/Acknowledge/Callback. O planejamento de capacity também é diferenciado dentre as abordagens. Se o callback for efetuado sempre para um destinatário apenas, então o número de mensagens de resposta deve ser semelhante ao que se teria no padrão Request/Response. Porém, se o número de destinatários for significante e se houver necessidade de transformar mensagens em formatos específicos para cada destinatário, então, os recursos de infraestrutura necessários devem ser maiores, o que pode implicar em investimentos mais significativos.

O padrão Request/Acknowledge/Callback pode não ser viável em cenários em que o cliente não pode ou não está disposto a prover um serviço para receber retornos, seja pela necessidade de abertura de porta para recebimento de trafego de dados, seja pela falta de recursos para prover infraestrutura necessária. Neste caso, a única alternativa possível para o recebimento de retornos seria o Request/Acknowledge/Poll.

Conclusão

Diante de tantos fatores a serem levados em consideração quando da escolha por um dos padrões mencionados, uma “Trade-off Analysis” pode lhe ser útil para ajudar em sua decisão, dado seu contexto de aplicação.

Neste post ficamos por aqui. Até o próximo!

Synchronous x Asynchronous Services – Parte 1

Olá pessoal,

Livro Service Design Patterns

Neste post gostaria de trazer um assunto bastante recorrente em discussões relacionadas à integração, principalmente quando o meio escolhido para a tal é web service: quando que serviços devem ser síncronos ou assíncronos e quais as vantagens e desvantagens de ambas as abordagens. Além disso, discutiremos também, para o caso de serviços assíncronos, quais os padrões que podemos considerar para retornarmos um determinado resultado para o chamador do serviço, uma vez que o processamento tenha sido concluído. Padrões como Request/Response, Asynchronous Response Handler, Request/Acknowledge/Poll e Request/Acknowledge/Callback serão explicados, bem como o impacto da sua adoção na forma como os serviço são estruturados, o que incorre em esforço de desenvolvimento, timing de atualização e recuperação de informações, além de disponibilidade e escalabilidade do serviço provido. Neste primeira parte (parte 1) focarei em em padrões de serviços síncronos (padrão Request/Response e Asynchronous Response Handler) e no seguinte fecharei a comparação com os padrões de implementação de serviços assíncronos (Request/Acknowledge/Poll e Request/Acknowledge/Callback).

Todas estas questões e diversas outras, como padrões de APIs de serviços, padrões de interação client-service (que discutiremos em parte neste artigo), padrões para gerenciamento de requisição e resposta, padrões para implementação de serviços, padrões de infraestrutura de serviços e padrões de evolução de serviços, todos bastante relevantes e úteis em qualquer discussão que envolva web service como meio de integração, podem ser encontradas no livro Service Design Patterns de Robert Daigneau, que conta com prefácio de nada mais nada menos que Martin Fowler, além de Ian Robinson.

Serviços que implementam o padrão Request/Response

Padrão Request/Response

Um serviço que implementa o padrão Request/Response processa requisições assim que elas são recebidas, retornando resultados em uma mesma conexão de um cliente, de forma síncrona. Uma vez que o cliente submeta uma requisição, usualmente ele não continua com seu processamento até que uma resposta seja retornada. Na utilização deste padrão, frequentemente assume-se que o processamento será concluído em apenas alguns segundos. Dentre os padrões que serão abordados, o padrão Request/Response é mais simples de se implementar, depurar e testar, uma vez que funciona como uma chamada remota de uma operação, com parâmetros de entrada e resposta síncrona. Veja a exemplificação do padrão Request/Response no diagrama de sequencia ao lado.

O padrão Request/Response é indicado para casos em que uma resposta imediata seja necessária, como por exemplo, uma página web que proveja uma funcionalidade para consulta de abertura de vagas, cuja consulta das vagas disponíveis seja provida por um serviço.

Acoplamento temporal (temporal coupling)

A adoção do padrão Request/Response incorre em algumas implicações. Acoplamento temporal é uma delas. O acoplamento temporal remete à dependência do tempo de resposta que um serviço que implementa o padrão Request/Response implica para seu consumidor. No padrão Request/Response é assumido que o serviço sempre poderá processar uma requisição quando esta for recebida e que uma resposta será enviada assim que o processamento for encerrado. A implicação neste caso é que todos os sistemas dos quais o serviço depende (banco de dados, servidores de arquivos, etc.) sempre devem estar operacionais e sempre devem estar aptos a processar requisições imediatamente. Se tais sistemas estiverem indisponíveis, seja por uma falha ou por uma parada programada para manutenção, então as requisições dos clientes poderão ser rejeitadas.

Problemas relacionados ao tempo de resposta do serviço podem ainda acontecer mesmo quando todos os recursos dos quais o serviço dependem estão disponíveis. Uma vez que este padrão requer que requisições sejam processadas assim que recebidas, um grande volume de requisições pode comprometer a capacidade do sistema. Ao adotar tal padrão é preciso compreender a carga típica que o serviço deterá ter e projetar a capacidade de servidores, bancos de dados, rede, etc. de forma a endereçar tais cargas. Uma arquitetura tal deve ser projetada para que seja possível escalar horizontal ou verticalmente tais recursos, uma vez que as demandas de requisição aumentem ao longo do tempo. A adoção dos padrões assíncronos Request/Acknowledge/Poll e Request/Acknowledge/Callback, que serão vistos no próximo post, ajuda a mitigar esta necessidade, uma vez que transfere do cliente do serviço para o provedor do serviço o controle das requisições que serão processadas em paralelo.

O acoplamento temporal também traz implicações relacionadas ao tempo em que o consumidor do serviço aguardará por uma resposta antes que um timeout seja lançado. Nestes casos, uma vez que o processamento já tenha sido iniciado pelo serviço, a resposta não seria recebida pelo cliente, implicando em perda de sincronismo ou inconsistência de dados. As razões para que um serviço demore mais para responder do que o tempo planejado são inúmeras. Atividades que requeiram maior I/O, altos níveis de trafego de rede são exemplos comuns. Neste ponto, mais uma vez os padrões de serviços assíncronos são mais vantajosos.

Client-side Blocking / Asynchronous Response Handler

Por padrão, clientes de serviços que implementam o padrão Request/Response aguardam pela resposta do serviço invocado sem realizar outras operações no meio tempo. Esta característica é conhecida como “Client-side Blocking”, uma vez que o cliente fica bloqueado até que uma resposta do serviço chamado seja retornada. Para casos em que se deseje aproveitar o tempo de espera de um serviço processando outras atividades, pode-se utilizar o padrão denominado “Asynchronous Response Handler” em conjunto com o padrão Request/Response, o qual permite que o cliente efetue requisições para um serviço Request/Response, delegando o recebimento da resposta para um thread apartada da thread principal, de forma que outras atividades sejam executadas na thread principal logo após a requisição do serviço. Veja no diagrama de sequencia mais abaixo a ilustração desta implementação.

É importante destacar que este padrão também não garante que respostas não sejam perdidas, como já descrito anteriormente.

Sync Services with Async Response Handler

Por todos os motivos apresentados, podemos concluir que o padrão Request/Response deve ser usado apenas quando for possível garantir que o tempo médio de resposta do serviço seja relativamente baixo, e que o cliente será projetado para tolerar perda de respostas. No próximo post veremos como os padrões assíncronos ajudam a mitigar os riscos relacionados ao acoplamento temporal, à perda de sincronismo e inconsistência de dados, além de permitir que o cliente não fique bloqueado enquanto aguarda o resultado do processamento.

Neste post ficamos por aqui. Até o próximo!