Serviços de fluxo de trabalho

Fluxos de trabalho escalonáveis e de execução longa com o Windows Server AppFabric

Rafael Godinho

Baixar o código de exemplo

Os processos empresariais podem abranger uma grande variedade de cenários de aplicativo. Podem incluir fluxos de trabalho humanos, lógica de negócios expostas por meio de serviços, coordenação de camadas de apresentação e até mesmo integração de aplicativos.

Embora esses cenários sejam diferentes, processos empresariais bem-sucedidos têm algumas coisas em comum. Eles precisam ser simples de criar, usar e modificar. Precisam ser escalonáveis para atender às necessidades em constante alteração dos negócios. E, com frequência, precisam de alguma forma de log para status, conformidade e depuração.

Os fluxos de trabalho são um bom exemplo de processos empresariais que foram codificados em aplicativos. Eles incorporam todos os elementos que mencionei: necessidades de negócios, lógica de negócios, coordenação entre pessoas e aplicativos e capacidade de inserir dados e recuperar status facilmente. Isso é muita coisa para um aplicativo fazer e, também, muito código.

Felizmente, o Microsoft .NET Framework e o Windows Server AppFabric fornecem as ferramentas que você precisa para criar, implantar e configurar serviços de fluxos de trabalho controláveis e de longa execução. Provavelmente, você já está familiarizado com o .NET Framework. O Windows Server AppFabric é um conjunto de extensões do Windows Server que inclui serviços de cache e de host para serviços baseados no WCF (Windows Communication Foundation) e no WF (Windows Workflow Foundation).

Neste artigo, darei instruções sobre o processo de criação de um simples fluxo de trabalho escalonável com o uso do WCF, do WF e do Windows Server AppFabric.

Criando um serviço de fluxo de trabalho

Para criar um serviço de fluxo de trabalho, você precisa combinar duas tecnologias: WCF e WF. Essa integração é transparente para o desenvolvedor e é feita com o uso de atividades específicas do sistema de mensagens para receber mensagens do WCF no fluxo de trabalho. O fluxo de trabalho é hospedado em um ServiceHost do WCF específico ao fluxo de trabalho (o WorkflowServiceHost), que expõe os pontos de extremidade do WCF para essas mensagens. Do grupo de atividades do sistema de mensagens, duas podem ser usadas para receber informações, permitindo que o fluxo de trabalho aceite mensagens de clientes externos como chamadas de serviço Web: a atividade Receive e o modelo ReceiveAndSendReply.

A atividade Receive é usada para receber informações a serem processadas pelo fluxo de trabalho. Ela pode receber quase qualquer tipo de dados, como tipos de dados internos, classes definidas pelo aplicativo ou até mesmo tipos serializáveis por XML. A Figura 1 mostra um exemplo de uma atividade Receive no designer de fluxo de trabalho.

image: A Receive Activity on the Workflow Designer

Figura Uma atividade Receive no designer de fluxo de trabalho

Esse tipo de atividade tem muitas propriedades, mas quatro delas são extremamente importantes e devem ser lembradas:

  • CanCreateInstance é usada para determinar se o tempo de execução do fluxo de trabalho deve criar uma nova instância de fluxo de trabalho para processar a mensagem recebida ou se deve reutilizar uma instância existente por meio de técnicas de correlação. Abordarei a correlação em mais detalhes posteriormente. Você provavelmente irá defini-la como true na primeira atividade Receive do fluxo de trabalho.
  • OperationName especifica o nome da operação do serviço implementado por essa atividade Receive.
  • Content indica os dados a serem recebidos pelo serviço. Essa propriedade é muito parecida com os parâmetros de contract da operação do serviço do WCF.
  • ServiceContractName é usada para criar contratos de serviço com o agrupamento de operações de serviço dentro da linguagem WSDL gerada.

Quando usada sozinha, a atividade Receive implementa um padrão de troca de mensagens unidirecional, que é usado para receber informações de clientes, sem enviar uma resposta. Esse tipo de atividade também pode ser usado para implementar um padrão de solicitação-resposta por meio de associação a uma atividade SendReply.

Para ajudar a implementar o padrão solicitação-resposta, o WF adiciona uma opção à caixa de ferramentas do Visual Studio chamada ReceiveAndSendReply. Quando é solta no designer de fluxo de trabalho, ela cria automaticamente um par de atividades Receive e SendReplyToReceive pré-configuradas dentro de uma atividade Sequence (consulte a Figura 2).

image: ReceiveAndSendReply on the Workflow Designer

Figura 2 ReceiveAndSendReply no designer de fluxo de trabalho

A ideia por trás do modelo ReceiveAndSendReply é executar algum processamento entre as ações Receive e SendReplyToReceive. No entanto, é importante observar que a persistência não é permitida entre o par Receive e SendReplyToReceive. Uma zona sem persistência é criada e dura até que as duas atividades tenham sido concluídas, o que significa que se a instância do fluxo de trabalho se tornar ociosa, ela não persistirá mesmo que o host esteja configurado para persistir fluxos de trabalho quando se tornam ociosos. Se uma atividade tentar persistir explicitamente a instância do fluxo de trabalho na zona sem persistência, será gerada uma exceção fatal, o fluxo de trabalho será anulado e uma exceção será retornada ao chamador.

Correlacionando chamadas

Algumas vezes um processo empresarial pode receber mais de uma chamada externa. Quando isso ocorre, uma nova instância do fluxo de trabalho é criada na primeira chamada, suas atividades são executadas e o fluxo de trabalho permanece ocioso, esperando por chamadas subsequentes. Quando uma chamada posterior é feita, a instância do fluxo de trabalho deixa o estado ocioso e continua a ser executada.

Dessa maneira, o tempo de execução do fluxo de trabalho tem uma forma de usar as informações recebidas em chamadas posteriores e de distinguir entre as instâncias de fluxo de trabalho criadas anteriormente para continuar o processamento. Caso contrário, ele poderia chamar qualquer instância, o que colocaria toda a consistência do processo em risco. Isso é chamado de correlação. Você correlaciona chamadas subsequentes ao fluxo de trabalho pendente com o qual a chamada está associada.

Uma correlação é representada como uma consulta de XPath para identificar dados específicos em uma mensagem específica. Ela pode ser inicializada com o uso de uma atividade InitializeCorrelation ou com a adição de um valor a CorrelationInitializers, uma propriedade de algumas atividades como, por exemplo: Receive, SendReply, Send e ReceiveReply.

Esse processo de inicialização pode ser feito em código ou por meio do designer de fluxo de trabalho no Visual Studio 2010. Como o Visual Studio tem um assistente para ajudar a criar a consulta de XPath, ele é a maneira mais fácil e, provavelmente, a preferida da maioria dos desenvolvedores.

Um possível cenário para uso de correlação é um fluxo de trabalho de relatório de despesas. Primeiramente, um funcionário envia os dados do relatório de despesas. Posteriormente, seu gerente pode rever o relatório e aprovar ou negar as despesas (consulte a Figura 3).

image: Expense Report Sample Scenario

Figura 3 Cenário de exemplo de relatório de despesas

Neste cenário, a correlação é criada quando o fluxo de trabalho retorna a resposta ao aplicativo cliente do funcionário. Para criar uma correlação, você precisa de algumas informações de identificação do contexto, como a ID do relatório de despesas (que provavelmente já é uma ID exclusiva). Em seguida, a instância do fluxo de trabalho se torna ociosa, esperando que o gerente aprove ou negue o relatório de despesas. Quando a chamada de aprovação é feita pelo aplicativo cliente do gerente, o tempo de execução do fluxo de trabalho correlaciona a ID do relatório de despesas recebido com a instância do fluxo de trabalho criada anteriormente para continuar o processo.

Para criar uma correlação no Visual Studio 2010, primeiro selecione, no fluxo de trabalho, a atividade onde a correlação será inicializada. Em meu exemplo, essa é a atividade que retorna a ID do relatório de despesas ao cliente. Na atividade SendReply, defino a propriedade CorrelationInitializers na janela Propriedades com um clique no botão de reticências. Isso exibe a caixa de diálogo Adicionar Inicializadores de Correlação (consulte a Figura 4) onde você pode configurar a correlação.

image: Setting the XPath Query Correlation

Figura 4 Definindo a correlação da consulta de XPath

É necessário definir três itens: o identificador da correlação, o tipo da correlação e as Consultas de XPath. O identificador da correlação é uma variável usada pelo tempo de execução do fluxo de trabalho para armazenar os dados da correlação e é criada automaticamente pelo Visual Studio.

A próxima etapa é definir o tipo de correlação. O .NET Framework tem alguns tipos de correlação, mas como preciso consultar parte das informações trocadas com o cliente, em outras palavras, uma correlação baseada em conteúdo, minha melhor opção é usar o Inicializador de correlação de consultas. Depois de fazer isso, as consultas de XPath podem ser definidas para a ID do relatório de despesas. Quando clico na seta, o Visual Studio verifica o conteúdo da mensagem e mostra uma lista para eu selecionar as informações adequadas.

Para continuar o fluxo de trabalho depois da aprovação das despesas, a correlação deve ser usada pela atividade Receive correspondente. Isso é feito por meio da definição da propriedade CorrelatesOn. Basta clicar no botão de reticências perto da propriedade na janela Propriedades para abrir a caixa de diálogo Definição de CorrelatesOn (consulte a Figura 5). Nessa caixa de diálogo, a propriedade CorrelatesWith precisa ser definida com o mesmo identificador usado para inicializar a correlação da atividade SendReplyToReceive, e a propriedade de Consultas de XPath deve ser definida com a mesma chave e ID do relatório de despesas recebido na mensagem de aprovação do relatório de despesas.

image: CorrelatesOn Definition

Figura 5 Definição de CorrelatesOn

O WF é fornecido com um conjunto de atividades para fins gerais chamado BAL (Base Activity Library), algumas das quais usei para enviar e receber informações aqui. Embora elas sejam úteis, algumas vezes atividades mais relacionadas às regras de negócio são necessárias. Com base no cenário que abordei até agora, há três atividades necessárias para o envio e a aprovação de relatórios de despesas: Criar, Aprovar e Negar relatório de despesas. Como todas essas atividades são muito semelhantes, vou mostrar apenas o código de CreateExpenseReportActivity:

public sealed class CreateExpenseReportActivity 
  : CodeActivity<int> {
  public InArgument<decimal> Amount { get; set; }
  public InArgument<string> Description { get; set; }
  protected override int Execute(CodeActivityContext context) {
    Data.ExpenseReportManager expenseReportManager = 
      new Data.ExpenseReportManager();
    return expenseReportManager.CreateExpenseReport(
      Amount.Get(context), Description.Get(context));
  }
}

A atividade recebe a quantidade e a descrição das despesas, declaradas como InArgument. A maior parte do levantamento pesado é feita pelo método Execute. Ele acessa uma classe que usa o Entity Framework para tratar o acesso ao banco de dados e para salvar as informações do relatório de despesas e, na outra extremidade, o Entity Framework retorna a ID do relatório de despesas. Como preciso apenas executar o código CLR e não preciso interagir com o tempo de execução do WF, a opção mais fácil para criar uma atividade é herdar de CodeActivity. O fluxo de trabalho completo pode ser visto na Figura 6.

image: Complete Expense Report Workflow

Figura 6 Fluxo de trabalho completo do relatório de despesas

Hospedando o serviço de fluxo de trabalho

Depois que o serviço de fluxo de trabalho é criado, é necessário decidir onde ele será executado. A opção tradicional é executá-lo em seu próprio ambiente de host, no IIS ou no WAS (Windows Process Activation Services). Porém, outra opção é tirar proveito do Windows Server AppFabric, um aprimoramento da função Servidor de Aplicativos do Windows Server 2008 R2 para hospedar, gerenciar, proteger e dimensionar serviços criados com o WCF ou o WF. Também é possível implantar o Windows Server AppFabric em PCs que executam o Windows Vista ou o Windows 7 para desenvolvimento e teste.

Apesar do IIS e do WAS já darem suporte à hospedagem de serviços, o Windows Server AppFabric oferece um ambiente mais útil e gerenciável que integra os recursos do WCF e do WF, como persistência e acompanhamento, com o Gerenciador do IIS.

Persistência do fluxo de trabalho simplificada

Os computadores terão um conjunto limitado de recursos para processar todos os seus processos empresariais, e não há nenhum motivo para desperdiçar recursos de computação em fluxos de trabalho ociosos. Para processos de longa execução, talvez você não tenha nenhum controle sobre o período total de tempo do início ao fim do processo. Os processos podem demorar minutos, horas, dias ou mais tempo e, se dependerem de entidades externas, como outros sistemas ou usuários finais, eles podem ficar ociosos durante a maior parte do tempo simplesmente esperando uma resposta.

O WF fornece uma estrutura de persistência capaz de armazenar uma captura durável do estado da instância de um fluxo de trabalho, independente das informações do processo ou do computador, em repositórios de instâncias. O WF 4 já tem um repositório de instâncias do SQL Server pronto para uso. No entanto, como o WF é muito extensível, eu posso criar meu próprio repositório de instâncias para persistir o estado de instâncias de fluxos de trabalho, se desejar. Quando a instância do fluxo de trabalho se tornar ociosa e tiver sido persistida, ela pode ser descarregada para preservar memória e recursos da CPU ou, eventualmente, pode ser movida de um nó para outro em um farm de servidores.

O Windows Server AppFabric tem uma maneira fácil de configurar e manter a integração com os recursos de persistência do WF. O processo inteiro é transparente para o tempo de execução do fluxo de trabalho, que delega as tarefas de persistência para o AppFabric, estendendo a estrutura padrão da persistência do WF.

A primeira etapa da configuração da persistência é configurar o banco de dados do SQL Server com o uso do Assistente de Configuração do Windows Server AppFabric ou com cmdlets do Windows PowerShell. Se o banco de dados não existir, o assistente poderá criá-lo ou criar apenas o esquema do AppFabric. Com o banco de dados já criado, todas as outras etapas são realizadas com o Gerenciador do IIS.

No Gerenciador do IIS, clique com o botão direito do mouse no nó que você deseja configurar (servidor, site ou aplicativo) e escolha Gerenciar os Serviços WCF e WF | Configurar para abrir a caixa de diálogo Configurar WCF e WF do Aplicativo e, em seguida, clique em Persistência de Fluxo de Trabalho (consulte a Figura 7). Você pode ver que tem a opção de habilitar ou desabilitar a persistência do fluxo de trabalho.

image: Configuring Workflow Persistence

Figura 7 Configuração da persistência do fluxo de trabalho

Você também tem a opção de definir quanto tempo será necessário para que o tempo de execução do fluxo de trabalho descarregue a instância do fluxo de trabalho da memória e persista-a no banco de dados quando o fluxo de trabalho se tornar ocioso. O valor padrão é 60 segundos. Se você definir o valor como zero, ela será persistida imediatamente. Isso é importante, principalmente para dimensionar por meio de um balanceador de carga.

Acompanhamento do fluxo de trabalho

Algumas vezes, algo pode não funcionar com processos que interagem com usuários e aplicativos externos. Devido à natureza desanexada de processos de longa execução, isso pode ser ainda pior nesses cenários. Quando um problema ocorre, como um desenvolvedor, você normalmente precisa analisar vários logs para descobrir o que aconteceu, como reproduzi-lo e, mais importante, como corrigi-lo e manter o sistema ativo. Se você usar o WF, você já terá esse tipo de log dentro da estrutura.

Da mesma maneira como o WF tem uma estrutura extensível para persistir instâncias ociosas, ele também tem uma estrutura extensível para fornecer visibilidade da execução do fluxo de trabalho. Essa estrutura é chamada de acompanhamento, o que instrumenta transparentemente um fluxo de trabalho, registrando eventos importantes durante sua execução. O Windows Server AppFabric usa essa extensibilidade para aprimorar a funcionalidade interna de acompanhamento do WF, registrando eventos de execução em um banco de dados do SQL Server.

A configuração do acompanhamento do Windows Server AppFabric é semelhante à usada para persistência e pode ser acessada por meio do Assistente de Configuração do Windows Server AppFabric ou dos cmdlets do Windows PowerShell. Na caixa de diálogo Configurar WCF e WF do Aplicativo discutida anteriormente, clique em Monitoramento. Agora você pode escolher habilitar ou desabilitar o acompanhamento e também o nível do acompanhamento, conforme mostrado na Figura 8.

image: Enabling Tracking on Windows Server AppFabric

Figura 8 Habilitando o acompanhamento no Windows Server AppFabric

Ao configurar o acompanhamento no Windows Server AppFabric, você pode escolher cinco níveis de monitoramento:

  • Desativar tem o mesmo efeito que desabilitar o monitoramento e é melhor quando usado em cenários que precisam de acompanhamento mínimo de sobrecarga.
  • Apenas Erro fornece visibilidade somente a eventos críticos, como erros e avisos. Esse modo é melhor para cenários de alto desempenho que precisam apenas de log mínimo de erros.
  • Monitoramento de Integridade é o nível de monitoramento padrão e contém todos os dados capturados no nível Apenas Erros, além de alguns dados adicionais de processamento.
  • Monitoramento Fim a Fim contém todos os dados do nível Monitoramento de Integridade além de informações adicionais para reconstruir todo o fluxo de mensagens. Esse nível é usado em cenários onde um serviço chama outro serviço.
  • Solução de Problemas, como o nome sugere, é o nível mais detalhado e é útil em cenários onde um aplicativo está em um estado não íntegro e precisa ser corrigido.

Dimensionando o serviço de fluxo de trabalho

Como o Windows Server AppFabric estende a função Servidor de Aplicativos do Windows Server, ele herda a infraestrutura altamente escalonável de seu predecessor e pode ser executado em um farm de servidores por trás de um NLB (balanceador de carga de rede). Você também já notou que ele tem a capacidade de persistir e acompanhar instâncias de fluxo de trabalho quando necessário. Como resultado, o Windows Server AppFabric é uma excelente opção para hospedar processos de fluxo de trabalho de longa execução e dá suporte a um grande número de solicitações de clientes.

Um exemplo de um ambiente escalonável de serviço de fluxo de trabalho pode ser visto na Figura 9. Ele tem duas instâncias do Windows Server AppFabric, com as duas executando cópias da mesma definição de fluxo de trabalho. O NLB roteia solicitações para a instância do AppFabric disponível.

image: Workflows in a Scalable Environment

Figura 9 Fluxos de trabalho em um ambiente escalonável

No cenário do relatório de despesas, quando um cliente acessa o serviço pela primeira vez para criar um relatório de despesas, o balanceador redireciona as solicitações para uma instância do Windows Server AppFabric disponível, que salva os dados de despesas no banco de dados, retorna a ID gerada ao cliente e, como o fluxo de trabalho se torna ocioso esperando pela aprovação do tempo de execução do fluxo de trabalho, persiste a instância em execução no banco de dados.

Mais tarde, quando o aplicativo cliente acessar o serviço para aprovar ou negar o relatório de despesas, o NLB redireciona a solicitação para uma instância do Windows Server AppFabric disponível (pode ser um servidor diferente da primeira chamada do serviço), e o servidor correlaciona a solicitação e restaura a instância do fluxo de trabalho do banco de dados de persistências. Agora, a instância na memória continua o processamento, salva a aprovação no banco de dados e retorna para o cliente quando tiver concluído.

Observações finais

Como você viu, o uso de serviços de fluxo de trabalho com correlação, persistência e acompanhamento em um ambiente de balanceamento de carga é uma técnica avançada para executar esses serviços de uma maneira escalonável. A combinação desses recursos pode aumentar a produtividade das operações, permitindo ações proativas em serviços em execução e espalhando fluxos de trabalho entre threads, processos e até mesmo computadores. Isso permite que os desenvolvedores criem uma solução escalonável pronta para execução em um único computador, ou mesmo em grandes farms de servidores, sem se preocupar com a complexidade da infraestrutura.

Para obter informações adicionais sobre como criar fluxos de trabalho com o WCF e o WF, leia o artigo de Leon Welicki, “Design visual de fluxos de trabalho com o WCF e o WF 4”, da edição de maio de 2010 da MSDN Magazine (msdn.microsoft.com/magazine/ff646977). E para acessar uma discussão mais profunda sobre processos de longa execução e persistência de fluxos de trabalho, consulte o artigo de Michael Kennedy, “Aplicativos Web que dão suporte a operações de longa execução”, na edição de janeiro de 2009 (msdn.microsoft.com/magazine/dd296718).

Para obter detalhes sobre o Windows Server AppFabric, consulte o Windows Server Developer Center em msdn.microsoft.com/windowsserver/ee695849.

Rafael Godinho é um desenvolvedor e divulgador ISV da Microsoft Brasil que ajuda parceiros locais a adotar a tecnologia da Microsoft. Entre em contato com Godinho em seu blog em blogs.msdn.com/rafaelgodinho.

Agradecemos aos seguintes especialistas técnicos pela revisão deste artigo: Dave Cliffe, Ron Jacobs e Leon Welicki