Padrão de Pipes e FiltrosPipes and Filters pattern

Decomponha uma tarefa que realiza processamento complexo numa série de elementos separados que podem ser reutilizados.Decompose a task that performs complex processing into a series of separate elements that can be reused. Este procedimento pode melhorar o desempenho, a escalabilidade e a reutilização ao permitir que os elementos de tarefas que realizam o processamento sejam implementados e dimensionados de forma independente.This can improve performance, scalability, and reusability by allowing task elements that perform the processing to be deployed and scaled independently.

Contexto e problemaContext and problem

É preciso uma aplicação para realizar uma série de tarefas de complexidade variada nas informações que vai processar.An application is required to perform a variety of tasks of varying complexity on the information that it processes. Uma abordagem simples, mas inflexível, para implementar uma aplicação consiste em realizar este processamento como um módulo monolítico.A straightforward but inflexible approach to implementing an application is to perform this processing as a monolithic module. No entanto, é provável que esta abordagem reduza as oportunidades para refatorizar o código, ao otimizá-lo ou reutilizá-lo se forem precisas partes do mesmo processamento noutro local na aplicação.However, this approach is likely to reduce the opportunities for refactoring the code, optimizing it, or reusing it if parts of the same processing are required elsewhere within the application.

A figura mostra os problemas de processamento de dados com uma abordagem monolítica.The figure illustrates the issues with processing data using the monolithic approach. Uma aplicação recebe e processa dados de duas origens.An application receives and processes data from two sources. Os dados de cada origem são processados por um módulo separado que realiza uma série de tarefas para transformar estes dados, antes de transmitir o resultado para a lógica de negócio da aplicação.The data from each source is processed by a separate module that performs a series of tasks to transform this data, before passing the result to the business logic of the application.

Figura 1 – Solução implementada com módulos monolíticos

Algumas das tarefas realizadas pelos módulos monolíticos são funcionalmente muito semelhantes, mas os módulos foram concebidos separadamente.Some of the tasks that the monolithic modules perform are functionally very similar, but the modules have been designed separately. O código que implementa as tarefas está estreitamente integrado num módulo e foi desenvolvido com pouca ou nenhuma atenção dada à reutilização ou escalabilidade.The code that implements the tasks is closely coupled in a module, and has been developed with little or no thought given to reuse or scalability.

No entanto, as tarefas de processamento realizadas por cada módulo ou os requisitos de implementação de cada tarefa podem alterar à medida que os requisitos comerciais são atualizados.However, the processing tasks performed by each module, or the deployment requirements for each task, could change as business requirements are updated. Algumas tarefas podem ser intensivas em termos de computação e podem beneficiar da execução em hardware potente, enquanto outros utilizadores podem não precisar desses recursos dispendiosos.Some tasks might be compute intensive and could benefit from running on powerful hardware, while others might not require such expensive resources. Além disso, o processamento adicional pode ser preciso no futuro. Caso contrário, a ordem pela qual as tarefas são realizadas pelo processamento pode ser alterada.Also, additional processing might be required in the future, or the order in which the tasks performed by the processing could change. É preciso uma solução que aborde estes problemas e aumente as possibilidades de reutilização do código.A solution is required that addresses these issues, and increases the possibilities for code reuse.

SoluçãoSolution

Divida o processamento necessário para cada fluxo para um conjunto de componentes (ou filtros) separados, cada um a executar uma única tarefa.Break down the processing required for each stream into a set of separate components (or filters), each performing a single task. Ao uniformizar o formato dos dados que cada componente recebe e envia, estes filtros podem ser combinados num pipeline.By standardizing the format of the data that each component receives and sends, these filters can be combined together into a pipeline. Tal ajudará a evitar a duplicação de código e facilitará a remoção, a substituição ou a integração de componentes adicionais se os requisitos de processamento forem alterados.This helps to avoid duplicating code, and makes it easy to remove, replace, or integrate additional components if the processing requirements change. A figura seguinte mostra uma solução implementada com pipes e filtros.The next figure shows a solution implemented using pipes and filters.

Figura 2 – Solução implementada com pipes e filtros

O tempo que demora a processar um único pedido depende da velocidade do filtro mais lento no pipeline.The time it takes to process a single request depends on the speed of the slowest filter in the pipeline. Um ou mais filtros podem causar estrangulamento, especialmente se aparecer um grande número de pedidos numa transmissão em fluxo a partir de uma determinada origem de dados.One or more filters could be a bottleneck, especially if a large number of requests appear in a stream from a particular data source. Uma das principais vantagens da estrutura de pipeline consiste na possibilidade de execução de instâncias em paralelo dos filtros lentos, o que permite que o sistema propague a carga e melhore o débito.A key advantage of the pipeline structure is that it provides opportunities for running parallel instances of slow filters, enabling the system to spread the load and improve throughput.

Os filtros que compõem um pipeline podem ser executados em computadores diferentes, o que permite que sejam dimensionados de forma independente e tirem partido da elasticidade que muitos ambientes na cloud fornecem.The filters that make up a pipeline can run on different machines, enabling them to be scaled independently and take advantage of the elasticity that many cloud environments provide. Um filtro intensivo em termos computacionais pode ser executado em hardware de elevado desempenho, enquanto outros filtros menos exigentes podem ser alojados em hardware base menos dispendioso.A filter that is computationally intensive can run on high performance hardware, while other less demanding filters can be hosted on less expensive commodity hardware. Os filtros não têm de estar no mesmo datacenter ou na mesma localização geográfica, o que permite que cada elemento num pipeline seja executado num ambiente próximo dos recursos que precisa.The filters don't even have to be in the same data center or geographical location, which allows each element in a pipeline to run in an environment that is close to the resources it requires. A figura seguinte mostra um exemplo aplicado ao pipeline dos dados da Origem 1.The next figure shows an example applied to the pipeline for the data from Source 1.

A figura 3 mostra um exemplo aplicado ao pipeline dos dados da Origem 1

Se a entrada e a saída de um filtro estiverem estruturadas como uma transmissão, será possível realizar o processamento de cada filtro em paralelo.If the input and output of a filter are structured as a stream, it's possible to perform the processing for each filter in parallel. O primeiro filtro no pipeline pode iniciar o seu trabalho e enviar os resultados, os quais são transmitidos diretamente para o filtro seguinte na sequência antes de o primeiro filtro ter concluído o trabalho.The first filter in the pipeline can start its work and output its results, which are passed directly on to the next filter in the sequence before the first filter has completed its work.

Outro benefício é a resiliência fornecida por este modelo.Another benefit is the resiliency that this model can provide. Se um filtro falhar ou o computador no qual está em execução já não estiver disponível, o pipeline poderá reagendar o trabalho que o filtro estava a realizar e direcioná-lo para outra instância do componente.If a filter fails or the machine it's running on is no longer available, the pipeline can reschedule the work that the filter was performing and direct this work to another instance of the component. A falha de um único filtro não resulta necessariamente na falha de todo o pipeline.Failure of a single filter doesn't necessarily result in failure of the entire pipeline.

A utilização do padrão de Pipes e Filtros, em conjunto com o padrão Transação de Compensação, é uma abordagem alternativa à implementação de transações distribuídas.Using the Pipes and Filters pattern in conjunction with the Compensating Transaction pattern is an alternative approach to implementing distributed transactions. Uma transação distribuída pode ser dividida em tarefas compensáveis separadas, cada uma das quais pode ser implementada com um filtro que também implementa o padrão Transação de Compensação.A distributed transaction can be broken down into separate, compensable tasks, each of which can be implemented by using a filter that also implements the Compensating Transaction pattern. Os filtros num pipeline podem ser implementados como tarefas separadas alojadas em execução próximas dos dados que estão a manter.The filters in a pipeline can be implemented as separate hosted tasks running close to the data that they maintain.

Problemas e consideraçõesIssues and considerations

Deve considerar os seguintes pontos ao decidir como implementar este padrão:You should consider the following points when deciding how to implement this pattern:

  • Complexidade.Complexity. O aumento da flexibilidade que este padrão fornece também pode fornecer complexidade, especialmente se os filtros num pipeline forem distribuídos por servidores diferentes.The increased flexibility that this pattern provides can also introduce complexity, especially if the filters in a pipeline are distributed across different servers.

  • Fiabilidade.Reliability. Utilize uma infraestrutura que garanta que os dados transmitidos entre os filtros num pipeline não serão perdidos.Use an infrastructure that ensures that data flowing between filters in a pipeline won't be lost.

  • Idempotência.Idempotency. Se um filtro num pipeline falhar depois de receber uma mensagem e o trabalho for reagendado para outra instância do filtro, parte do trabalho poderá já ter sido concluído.If a filter in a pipeline fails after receiving a message and the work is rescheduled to another instance of the filter, part of the work might have already been completed. Se este trabalho atualizar algum aspeto do estado global (por exemplo, as informações armazenadas numa base de dados), a mesma atualização poderá ser repetida.If this work updates some aspect of the global state (such as information stored in a database), the same update could be repeated. Um problema semelhante poderá ocorrer se um filtro falhar depois da publicação dos seus resultados para o filtro seguinte no pipeline, mas antes de indicar que concluiu o trabalho com sucesso.A similar issue might occur if a filter fails after posting its results to the next filter in the pipeline, but before indicating that it's completed its work successfully. Nestes casos, o mesmo trabalho pode ser repetido por outra instância do filtro, o que levará a que os mesmos resultados sejam publicado duas vezes.In these cases, the same work could be repeated by another instance of the filter, causing the same results to be posted twice. Tal pode resultar em filtros subsequentes no pipeline a processar os mesmos dados duas vezes.This could result in subsequent filters in the pipeline processing the same data twice. Por conseguinte, os filtros num pipeline devem ser concebidos para serem idempotentes.Therefore filters in a pipeline should be designed to be idempotent. Para obter mais informações, veja Idempotency Patterns (Padrões de Idempotência) no blogue de Jonathan Oliver.For more information see Idempotency Patterns on Jonathan Oliver’s blog.

  • Mensagens repetidas.Repeated messages. Se um filtro num pipeline falhar depois de publicar uma mensagem na fase seguinte do pipeline, outra instância do filtro poderá ser executada, publicando uma cópia da mesma mensagem no pipeline.If a filter in a pipeline fails after posting a message to the next stage of the pipeline, another instance of the filter might be run, and it'll post a copy of the same message to the pipeline. Tal pode levar à transmissão de duas instâncias da mesma mensagem para o filtro seguinte.This could cause two instances of the same message to be passed to the next filter. Para evitar esta situação, o pipeline deve detetar e eliminar as mensagens duplicadas.To avoid this, the pipeline should detect and eliminate duplicate messages.

    Se estiver a implementar o pipeline com filas de mensagens (por exemplo, as filas do Microsoft Azure Service Bus), a infraestrutura de colocação em fila das mensagens poderá fornecer a deteção e remoção automática de mensagens duplicadas.If you're implementing the pipeline by using message queues (such as Microsoft Azure Service Bus queues), the message queuing infrastructure might provide automatic duplicate message detection and removal.

  • Contexto e estado.Context and state. Num pipeline, cada filtro é executado essencialmente em isolamento e não deve criar qualquer pressuposto sobre a forma como foi invocado,In a pipeline, each filter essentially runs in isolation and shouldn't make any assumptions about how it was invoked. o que significa que cada filtro deve ser fornecido com contexto suficiente para realizar o trabalho.This means that each filter should be provided with sufficient context to perform its work. Este contexto pode incluir uma grande quantidade de informações de estado.This context could include a large amount of state information.

Quando utilizar este padrãoWhen to use this pattern

Utilize este padrão quando:Use this pattern when:

  • O processamento exigido a uma aplicação puder ser facilmente dividido num conjunto de passos independentes.The processing required by an application can easily be broken down into a set of independent steps.

  • Os passos do processamento realizados por uma aplicação tiverem requisitos de escalabilidade diferentes.The processing steps performed by an application have different scalability requirements.

    Pode agrupar filtros que devem ser dimensionados em conjunto no mesmo processo.It's possible to group filters that should scale together in the same process. Para obter mais informações, veja o Padrão de Consolidação de Recursos de Computação.For more information, see the Compute Resource Consolidation pattern.

  • A flexibilidade é exigida para permitir a reordenação dos passos de processamento realizados por uma aplicação ou a capacidade de adicionar e remover passos.Flexibility is required to allow reordering of the processing steps performed by an application, or the capability to add and remove steps.

  • O sistema puder beneficiar da distribuição dos passos de processamento por servidores diferentes.The system can benefit from distributing the processing for steps across different servers.

  • É exigida uma solução fiável que minimize os efeitos da falha num passo enquanto os dados estão a ser processados.A reliable solution is required that minimizes the effects of failure in a step while data is being processed.

Este padrão poderá não ser prático quando:This pattern might not be useful when:

  • Os passos do processamento realizados por uma aplicação não são independentes ou têm de ser realizados em conjunto como parte da mesma transação.The processing steps performed by an application aren't independent, or they have to be performed together as part of the same transaction.

  • A quantidade de contexto ou informações de estado precisas para um passo tornam esta abordagem ineficaz.The amount of context or state information required by a step makes this approach inefficient. Em vez disso, pode ser possível manter as informações de estado numa base de dados, mas não utilize esta estratégia se a carga adicional na base de dados provocar uma contenção excessiva.It might be possible to persist state information to a database instead, but don't use this strategy if the additional load on the database causes excessive contention.

ExemploExample

Pode utilizar uma sequência de filas de mensagens para fornecer a infraestrutura necessária para implementar um pipeline.You can use a sequence of message queues to provide the infrastructure required to implement a pipeline. Uma fila de mensagens inicial recebe mensagens não processadas.An initial message queue receives unprocessed messages. Um componente implementado como uma tarefa de filtro fica à escuta de uma mensagem nesta fila, realiza o trabalho e, em seguida, publica a mensagem transformada na fila seguinte na sequência.A component implemented as a filter task listens for a message on this queue, performs its work, and then posts the transformed message to the next queue in the sequence. Outra tarefa do filtro pode ficar à escuta de mensagens nesta fila, processá-las e publicar os resultados noutra fila, e assim sucessivamente, até que os dados totalmente transformados apareçam na mensagem final na fila.Another filter task can listen for messages on this queue, process them, post the results to another queue, and so on until the fully transformed data appears in the final message in the queue. A figura seguinte ilustra a implementação de um pipeline com filas de mensagens.The next figure illustrates implementing a pipeline using message queues.

Figura 4 – Implementação de um pipeline com filas de mensagens

Se estiver a criar uma solução no Azure, poderá utilizar filas do Service Bus para fornecer um mecanismo de colocação em fila fiável e escalável.If you're building a solution on Azure you can use Service Bus queues to provide a reliable and scalable queuing mechanism. A classe ServiceBusPipeFilter, ilustrada abaixo, em C# demonstra como pode implementar um filtro que recebe mensagens de entrada de uma fila, processa-as e publica os resultados noutra fila.The ServiceBusPipeFilter class shown below in C# demonstrates how you can implement a filter that receives input messages from a queue, processes these messages, and posts the results to another queue.

A classe ServiceBusPipeFilter está definida no projeto PipesAndFilters.Shared, disponível no GitHub.The ServiceBusPipeFilter class is defined in the PipesAndFilters.Shared project available from GitHub.

public class ServiceBusPipeFilter
{
  ...
  private readonly string inQueuePath;
  private readonly string outQueuePath;
  ...
  private QueueClient inQueue;
  private QueueClient outQueue;
  ...

  public ServiceBusPipeFilter(..., string inQueuePath, string outQueuePath = null)
  {
     ...
     this.inQueuePath = inQueuePath;
     this.outQueuePath = outQueuePath;
  }

  public void Start()
  {
    ...
    // Create the outbound filter queue if it doesn't exist.
    ...
    this.outQueue = QueueClient.CreateFromConnectionString(...);

    ...
    // Create the inbound and outbound queue clients.
    this.inQueue = QueueClient.CreateFromConnectionString(...);
  }

  public void OnPipeFilterMessageAsync(
    Func<BrokeredMessage, Task<BrokeredMessage>> asyncFilterTask, ...)
  {
    ...

    this.inQueue.OnMessageAsync(
      async (msg) =>
    {
      ...
      // Process the filter and send the output to the
      // next queue in the pipeline.
      var outMessage = await asyncFilterTask(msg);

      // Send the message from the filter processor
      // to the next queue in the pipeline.
      if (outQueue != null)
      {
        await outQueue.SendAsync(outMessage);
      }

      // Note: There's a chance that the same message could be sent twice
      // or that a message gets processed by an upstream or downstream
      // filter at the same time.
      // This would happen in a situation where processing of a message was
      // completed, it was sent to the next pipe/queue, and then failed
      // to complete when using the PeekLock method.
      // Idempotent message processing and concurrency should be considered
      // in a real-world implementation.
    },
    options);
  }

  public async Task Close(TimeSpan timespan)
  {
    // Pause the processing threads.
    this.pauseProcessingEvent.Reset();

    // There's no clean approach for waiting for the threads to complete
    // the processing. This example simply stops any new processing, waits
    // for the existing thread to complete, then closes the message pump
    // and finally returns.
    Thread.Sleep(timespan);

    this.inQueue.Close();
    ...
  }

  ...
}

O método Start na classe ServiceBusPipeFilter liga-se a um par de filas de entrada e saída e o método Close desliga-se da fila de entrada.The Start method in the ServiceBusPipeFilter class connects to a pair of input and output queues, and the Close method disconnects from the input queue. O método OnPipeFilterMessageAsync realiza o processamento real de mensagens, o parâmetro asyncFilterTask para este método especifica o processamento a ser executado.The OnPipeFilterMessageAsync method performs the actual processing of messages, the asyncFilterTask parameter to this method specifies the processing to be performed. O método OnPipeFilterMessageAsync aguarda pelas mensagens recebidas na fila de entrada, executa o código especificado pelo parâmetro asyncFilterTask em cada mensagem à medida que chegam e publica os resultados na fila de saída.The OnPipeFilterMessageAsync method waits for incoming messages on the input queue, runs the code specified by the asyncFilterTask parameter over each message as it arrives, and posts the results to the output queue. As próprias filas são especificadas pelo construtor.The queues themselves are specified by the constructor.

A solução de exemplo implementa filtros num conjunto de funções de trabalho.The sample solution implements filters in a set of worker roles. Cada função de trabalho pode ser dimensionada de forma independente, dependendo da complexidade do processamento do negócio que executa ou dos recursos necessários para processamento.Each worker role can be scaled independently, depending on the complexity of the business processing that it performs or the resources required for processing. Além disso, várias instâncias de cada função de trabalho podem ser executadas em paralelo para melhorar o débito.Additionally, multiple instances of each worker role can be run in parallel to improve throughput.

O código seguinte mostra uma função de trabalho do Azure designada PipeFilterARoleEntry, definida no projeto PipeFilterA na solução de exemplo.The following code shows an Azure worker role named PipeFilterARoleEntry, defined in the PipeFilterA project in the sample solution.

public class PipeFilterARoleEntry : RoleEntryPoint
{
  ...
  private ServiceBusPipeFilter pipeFilterA;

  public override bool OnStart()
  {
    ...
    this.pipeFilterA = new ServiceBusPipeFilter(
      ...,
      Constants.QueueAPath,
      Constants.QueueBPath);

    this.pipeFilterA.Start();
    ...
  }

  public override void Run()
  {
    this.pipeFilterA.OnPipeFilterMessageAsync(async (msg) =>
    {
      // Clone the message and update it.
      // Properties set by the broker (Deliver count, enqueue time, ...)
      // aren't cloned and must be copied over if required.
      var newMsg = msg.Clone();

      await Task.Delay(500); // DOING WORK

      Trace.TraceInformation("Filter A processed message:{0} at {1}",
        msg.MessageId, DateTime.UtcNow);

      newMsg.Properties.Add(Constants.FilterAMessageKey, "Complete");

      return newMsg;
    });

    ...
  }

  ...
}

Esta função contém um objeto ServiceBusPipeFilter.This role contains a ServiceBusPipeFilter object. O método OnStart na função liga-se às filas para receber mensagens de entrada e publicar mensagens de saída (os nomes das filas estão definidos na classe Constants).The OnStart method in the role connects to the queues for receiving input messages and posting output messages (the names of the queues are defined in the Constants class). O método Run invoca o método OnPipeFilterMessagesAsync para realizar algum processamento em cada mensagem recebida (neste exemplo, o processamento é simulado através de uma curta espera).The Run method invokes the OnPipeFilterMessagesAsync method to perform some processing on each message that's received (in this example, the processing is simulated by waiting for a short period of time). Quando o processamento estiver concluído, é criada uma nova mensagem que contém os resultados (neste caso, a mensagem de entrada recebe uma propriedade personalizada) e esta mensagem é publicada na fila de saída.When processing is complete, a new message is constructed containing the results (in this case, the input message has a custom property added), and this message is posted to the output queue.

O código de exemplo contém outra função de trabalho designada PipeFilterBRoleEntry no projeto PipeFilterB.The sample code contains another worker role named PipeFilterBRoleEntry in the PipeFilterB project. Esta função é semelhante a PipeFilterARoleEntry, mas esta realiza um processamento diferente no método Run.This role is similar to PipeFilterARoleEntry except that it performs different processing in the Run method. Na solução de exemplo, estas duas funções são combinadas para construir um pipeline, a fila de saída da função PipeFilterARoleEntry é a fila de entrada da função PipeFilterBRoleEntry.In the example solution, these two roles are combined to construct a pipeline, the output queue for the PipeFilterARoleEntry role is the input queue for the PipeFilterBRoleEntry role.

A solução de exemplo também fornece duas funções adicionais designadas InitialSenderRoleEntry (no projeto InitialSender) e FinalReceiverRoleEntry (no projeto FinalReceiver).The sample solution also provides two additional roles named InitialSenderRoleEntry (in the InitialSender project) and FinalReceiverRoleEntry (in the FinalReceiver project). A função InitialSenderRoleEntry fornece a mensagem inicial no pipeline.The InitialSenderRoleEntry role provides the initial message in the pipeline. O método OnStart liga-se a uma fila única e o método Run publica um método nesta fila.The OnStart method connects to a single queue and the Run method posts a method to this queue. Esta é a fila de entrada utilizada pela função PipeFilterARoleEntry. Assim, a publicação de uma mensagem faz com que a mensagem seja recebida e processada pela função PipeFilterARoleEntry.This queue is the input queue used by the PipeFilterARoleEntry role, so posting a message to it causes the message to be received and processed by the PipeFilterARoleEntry role. Em seguida, a mensagem processada é transferida através da função PipeFilterBRoleEntry.The processed message then passes through the PipeFilterBRoleEntry role.

A fila de entrada da função FinalReceiveRoleEntry é a fila de saída da função PipeFilterBRoleEntry.The input queue for the FinalReceiveRoleEntry role is the output queue for the PipeFilterBRoleEntry role. O método Run na função FinalReceiveRoleEntry, ilustrada abaixo, recebe a mensagem e realiza parte do processamento final.The Run method in the FinalReceiveRoleEntry role, shown below, receives the message and performs some final processing. Em seguida, escreve os valores das propriedades personalizadas adicionados pelos filtros no pipeline ao resultado de rastreio.Then it writes the values of the custom properties added by the filters in the pipeline to the trace output.

public class FinalReceiverRoleEntry : RoleEntryPoint
{
  ...
  // Final queue/pipe in the pipeline to process data from.
  private ServiceBusPipeFilter queueFinal;

  public override bool OnStart()
  {
    ...
    // Set up the queue.
    this.queueFinal = new ServiceBusPipeFilter(...,Constants.QueueFinalPath);
    this.queueFinal.Start();
    ...
  }

  public override void Run()
  {
    this.queueFinal.OnPipeFilterMessageAsync(
      async (msg) =>
      {
        await Task.Delay(500); // DOING WORK

        // The pipeline message was received.
        Trace.TraceInformation(
          "Pipeline Message Complete - FilterA:{0} FilterB:{1}",
          msg.Properties[Constants.FilterAMessageKey],
          msg.Properties[Constants.FilterBMessageKey]);

        return null;
      });
    ...
  }

  ...
}

Os padrões e orientações que se seguem também podem ser relevantes ao implementar este padrão:The following patterns and guidance might also be relevant when implementing this pattern:

  • Um exemplo que demonstra este padrão está disponível no GitHub.A sample that demonstrates this pattern is available on GitHub.
  • Padrão de Consumidores Concorrentes.Competing Consumers pattern. Um pipeline pode conter várias instâncias de um ou mais filtros.A pipeline can contain multiple instances of one or more filters. Esta abordagem é útil para executar instâncias em paralelo de filtros lentos, o que permite ao sistema propagar a carga e melhorar o débito.This approach is useful for running parallel instances of slow filters, enabling the system to spread the load and improve throughput. Cada instância de um filtro vai competir por entradas com as outras instâncias, duas instâncias de um filtro não devem poder processar os mesmos dados.Each instance of a filter will compete for input with the other instances, two instances of a filter shouldn't be able to process the same data. Fornece uma explicação desta abordagem.Provides an explanation of this approach.
  • Padrão de Consolidação de Recursos de Computação.Compute Resource Consolidation pattern. Pode ser possível agrupar filtros que devem ser dimensionados em conjunto para o mesmo processo.It might be possible to group filters that should scale together into the same process. Fornece mais informações sobre os benefícios e compromissos desta estratégia.Provides more information about the benefits and tradeoffs of this strategy.
  • Padrão Transação de Compensação.Compensating Transaction pattern. Um filtro pode ser implementado como uma operação que pode ser revertida ou que tem uma operação de compensação que restaura o estado para uma versão anterior em caso de falha.A filter can be implemented as an operation that can be reversed, or that has a compensating operation that restores the state to a previous version in the event of a failure. Explica como pode ser implementada para manter ou alcançar a consistência eventual.Explains how this can be implemented to maintain or achieve eventual consistency.
  • Padrões de Idempotência no blogue de Jonathan Oliver.Idempotency Patterns on Jonathan Oliver’s blog.