Padrão de agregação de gatewayGateway Aggregation pattern

Use um gateway para agregar várias solicitações individuais em uma única solicitação.Use a gateway to aggregate multiple individual requests into a single request. Esse padrão é útil quando um cliente deve fazer várias chamadas para diferentes sistemas de back-end ao executar uma operação.This pattern is useful when a client must make multiple calls to different backend systems to perform an operation.

Contexto e problemaContext and problem

Para executar uma única tarefa, um cliente talvez precise fazer várias chamadas a vários serviços de back-end.To perform a single task, a client may have to make multiple calls to various backend services. Um aplicativo que depende de muitos serviços para executar uma tarefa deve gastar recursos em cada solicitação.An application that relies on many services to perform a task must expend resources on each request. Quando qualquer novo serviço ou recurso é adicionado ao aplicativo, solicitações adicionais são necessárias, além de aumentar os requisitos de recursos e chamadas de rede.When any new feature or service is added to the application, additional requests are needed, further increasing resource requirements and network calls. Esse excesso de conversa entre um cliente e um back-end pode afetar negativamente o desempenho e a escala do aplicativo.This chattiness between a client and a backend can adversely impact the performance and scale of the application. Arquiteturas de microsserviço tornaram esse problema mais comum, uma vez que aplicativos baseados em torno de muitos serviços menores naturalmente têm uma quantidade maior de chamadas entre serviços.Microservice architectures have made this problem more common, as applications built around many smaller services naturally have a higher amount of cross-service calls.

No diagrama a seguir, o cliente envia solicitações a cada serviço (1,2,3).In the following diagram, the client sends requests to each service (1,2,3). Cada serviço processa a solicitação e envia a resposta de volta ao aplicativo (4,5,6).Each service processes the request and sends the response back to the application (4,5,6). Em uma rede celular com latência normalmente alta, usar solicitações individuais dessa maneira é ineficiente e pode resultar em interrupção da conectividade ou em solicitações incompletas.Over a cellular network with typically high latency, using individual requests in this manner is inefficient and could result in broken connectivity or incomplete requests. Embora cada solicitação possa ser executada em paralelo, o aplicativo deve enviar, aguardar e processar dados para cada solicitação, tudo em conexões separadas, aumentando a possibilidade de falha.While each request may be done in parallel, the application must send, wait, and process data for each request, all on separate connections, increasing the chance of failure.

Diagrama de problema para o padrão de agregação de Gateway

SoluçãoSolution

Use um gateway para reduzir a conversa entre o cliente e os serviços.Use a gateway to reduce chattiness between the client and the services. O gateway recebe solicitações de cliente, envia solicitações para os vários sistemas de back-end e, em seguida, agrega os resultados e envia-os de volta ao cliente solicitante.The gateway receives client requests, dispatches requests to the various backend systems, and then aggregates the results and sends them back to the requesting client.

Esse padrão pode reduzir o número de solicitações que o aplicativo faz a serviços back-end e melhorar o desempenho do aplicativo em redes de alta latência.This pattern can reduce the number of requests that the application makes to backend services, and improve application performance over high-latency networks.

No diagrama a seguir, o aplicativo envia uma solicitação para o gateway (1).In the following diagram, the application sends a request to the gateway (1). A solicitação contém um pacote de solicitações adicionais.The request contains a package of additional requests. O gateway as decompõe e processa cada solicitação enviando-a ao serviço em questão (2).The gateway decomposes these and processes each request by sending it to the relevant service (2). Cada serviço retorna uma resposta ao gateway (3).Each service returns a response to the gateway (3). O gateway combina as respostas de cada serviço e envia a resposta ao aplicativo (4).The gateway combines the responses from each service and sends the response to the application (4). O aplicativo faz uma única solicitação e recebe apenas uma única resposta do gateway.The application makes a single request and receives only a single response from the gateway.

Diagrama de solução para o padrão de agregação de Gateway

Problemas e consideraçõesIssues and considerations

  • O gateway não deve introduzir acoplamento de serviço entre os serviços de back-end.The gateway should not introduce service coupling across the backend services.
  • O gateway deve estar localizado próximo aos serviços de back-end para reduzir a latência tanto quanto possível.The gateway should be located near the backend services to reduce latency as much as possible.
  • O serviço de gateway pode introduzir um ponto único de falha.The gateway service may introduce a single point of failure. Verifique se o gateway está corretamente projetado para atender aos requisitos de disponibilidade do aplicativo.Ensure the gateway is properly designed to meet your application's availability requirements.
  • O gateway pode introduzir um gargalo.The gateway may introduce a bottleneck. O gateway deve ter um desempenho adequado para lidar com a carga e pode ser dimensionado para atender o seu crescimento previsto.Ensure the gateway has adequate performance to handle load and can be scaled to meet your anticipated growth.
  • Execute testes de carga no gateway para garantir que você não introduza falhas em cascata para serviços.Perform load testing against the gateway to ensure you don't introduce cascading failures for services.
  • Implemente um design resiliente usando técnicas como bulkheads, interrupção de circuito, nova tentativa e tempos limite.Implement a resilient design, using techniques such as bulkheads, circuit breaking, retry, and timeouts.
  • Se uma ou mais chamadas de serviço levarem tempo demais, pode ser aceitável atingir o tempo limite e retornar um conjunto parcial de dados.If one or more service calls takes too long, it may be acceptable to timeout and return a partial set of data. Considere como o aplicativo tratará esse cenário.Consider how your application will handle this scenario.
  • Use E/S assíncrona para garantir que um atraso no back-end não cause problemas de desempenho no aplicativo.Use asynchronous I/O to ensure that a delay at the backend doesn't cause performance issues in the application.
  • Implemente rastreamento distribuído usando IDs de correlação para rastrear cada chamada individual.Implement distributed tracing using correlation IDs to track each individual call.
  • Monitore métricas de solicitação e tamanhos de resposta.Monitor request metrics and response sizes.
  • Considere retornar dados em cache como uma estratégia de failover para lidar com falhas.Consider returning cached data as a failover strategy to handle failures.
  • Em vez de criar a agregação para o gateway, considere colocar um serviço de agregação atrás do gateway.Instead of building aggregation into the gateway, consider placing an aggregation service behind the gateway. Agregação de solicitação provavelmente terá requisitos de recursos diferentes de outros serviços no gateway e poderá afetar a funcionalidade de roteamento e descarregamento do gateway.Request aggregation will likely have different resource requirements than other services in the gateway and may impact the gateway's routing and offloading functionality.

Quando usar esse padrãoWhen to use this pattern

Use esse padrão quando:Use this pattern when:

  • Um cliente precisa se comunicar com vários serviços de back-end para executar uma operação.A client needs to communicate with multiple backend services to perform an operation.
  • O cliente puder usar redes com latência significativa, como redes de celulares.The client may use networks with significant latency, such as cellular networks.

Esse padrão pode não ser adequado quando:This pattern may not be suitable when:

  • Você quiser reduzir o número de chamadas entre um cliente e um único serviço entre várias operações.You want to reduce the number of calls between a client and a single service across multiple operations. Nesse cenário, talvez seja melhor adicionar uma operação em lote ao serviço.In that scenario, it may be better to add a batch operation to the service.
  • O cliente ou aplicativo está localizado próximo dos serviços de back-end e a latência não é um fator significativo.The client or application is located near the backend services and latency is not a significant factor.

ExemploExample

O exemplo a seguir ilustra como criar um serviço NGINX de agregação do gateway simples usando Lua.The following example illustrates how to create a simple a gateway aggregation NGINX service using Lua.

worker_processes  4;

events {
  worker_connections 1024;
}

http {
  server {
    listen 80;

    location = /batch {
      content_by_lua '
        ngx.req.read_body()

        -- read json body content
        local cjson = require "cjson"
        local batch = cjson.decode(ngx.req.get_body_data())["batch"]

        -- create capture_multi table
        local requests = {}
        for i, item in ipairs(batch) do
          table.insert(requests, {item.relative_url, { method = ngx.HTTP_GET}})
        end

        -- execute batch requests in parallel
        local results = {}
        local resps = { ngx.location.capture_multi(requests) }
        for i, res in ipairs(resps) do
          table.insert(results, {status = res.status, body = cjson.decode(res.body), header = res.header})
        end

        ngx.say(cjson.encode({results = results}))
      ';
    }

    location = /service1 {
      default_type application/json;
      echo '{"attr1":"val1"}';
    }

    location = /service2 {
      default_type application/json;
      echo '{"attr2":"val2"}';
    }
  }
}