Práticas recomendadas para design e desenvolvimento de proxy de API com a Apigee

Esta página se aplica à Apigee e à Apigee híbrida.

Confira a documentação da Apigee Edge.

Neste documento, apresentamos um conjunto de práticas recomendadas para desenvolver proxies de API com a Apigee.

Os tópicos abordados aqui incluem design, codificação, uso de políticas, monitoramento e depuração. As informações foram coletadas pela experiência dos desenvolvedores que trabalham com a Apigee para implementar programas de API bem-sucedidos. Este é um documento dinâmico e será atualizado periodicamente.

Além das diretrizes aqui, você também pode achar útil a Introdução a antipadrões.

Padrões de desenvolvimento

Comentários e documentação

  • Forneça comentários in-line nas configurações ProxyEndpoint e TargetEndpoint. Os comentários aumentam a legibilidade de um fluxo, especialmente quando os nomes de arquivo da política não são descritivos o suficiente para expressar a funcionalidade subjacente.
  • Faça comentários úteis. Evite comentários óbvios.
  • Use recuo consistente, espaçamento, alinhamento vertical e assim por diante.

Codificação em estilo de framework

A codificação no estilo de framework envolve o armazenamento de recursos de proxy de API em seu próprio sistema de controle de versões para reutilização em ambientes de desenvolvimento locais. Por exemplo, para reutilizar uma política, armazene-a no controle de origem para que os desenvolvedores possam sincronizá-la e usá-la nos próprios ambientes de desenvolvimento de proxy.

  • Para ativar DRY (não se repetir), quando possível, as configurações de política e scripts devem implementar funções especializadas e reutilizáveis. Por exemplo, uma política dedicada para extrair parâmetros de consulta de mensagens de solicitação pode ser chamada de ExtractVariables.ExtractRequestParameters.
  • Limpe políticas e recursos não utilizados (JavaScript, Java, XSLT.) de proxies de API, especialmente recursos grandes que podem atrasar a importação e a implantação de procedimentos.

Convenções de nomenclatura

  • O atributo name da política e o nome do arquivo de política XML precisam ser idênticos.
  • O Script e a política ServiceCallout, do atributo name e o nome do arquivo de recurso precisam ser idênticos.
  • DisplayName precisa descrever com precisão a função da política para alguém que nunca tenha trabalhado com esse proxy de API.
  • Nomear políticas de acordo com a função. A Apigee recomenda que você estabeleça uma convenção de nomenclatura consistente para suas políticas. Por exemplo, use prefixos curtos seguidos por uma sequência de palavras descritivas separadas por traços. Por exemplo, AM-xxx para a política AssignMessage. Veja também a ferramenta apigeelint (em inglês).
  • Use extensões adequadas para arquivos de recursos, .js para JavaScript, .py para Python e .jar para arquivos Java JAR.
  • Os nomes das variáveis precisam ser consistentes. Se você escolher um estilo, como camelCase ou under_score, use-o em todo o proxy da API.
  • Use prefixos de variáveis, quando possível, para organizar variáveis com base na finalidade delas. Por exemplo, Consumer.username e Consumer.password.

Desenvolvimento de proxy de API

Considerações iniciais sobre design

  • Para ver orientações sobre o design da API RESTful, faça o download do e-book Design da API da Web: o link ausente.
  • Aproveite as políticas e funcionalidades da Apigee sempre que possível para criar proxies de API. Evite codificar toda a lógica de proxy nos recursos JavaScript, Java ou Python.
  • Crie fluxos de maneira organizada. Vários fluxos, cada um com uma única condição, são preferidos para vários anexos condicionais no mesmo Preflow e no Postflow.
  • Como "failsafe", crie um proxy de API padrão com um ProxyEndpoint BasePath de /. Ele pode ser usado para redirecionar solicitações básicas da API para um site de desenvolvedor, para retornar uma resposta personalizada ou executar outra ação mais útil do que retornar o messaging.adaptors.http.flow.ApplicationNotFound padrão.
  • Use os recursos do TargetServer para desacoplar as configurações de TargetEndpoint dos URLs concretos, oferecendo suporte à promoção em vários ambientes.
    Consulte Balanceamento de carga entre servidores de back-end.
  • Se você tiver várias RouteRules, crie uma como "padrão", ou seja, como uma RouteRule sem condição. Certifique-se de que a RouteRule padrão esteja definida por último na lista de rotas condicionais. As RouteRules são avaliadas de cima para baixo no ProxyEndpoint. Consulte Referência de configuração do proxy da API.
  • Tamanho do pacote do proxy de API: os pacotes de proxy de API não podem ser maiores que 15 MB.
  • Controle de versão da API: para ver as ideias e recomendações da Apigee sobre o controle de versão da API, consulte Controle de versões no e-book Design da API da Web: o link ausente.

Como ativar o CORS

Antes de publicar as APIs, será necessário adicionar a política de CORS ao PreFlow de solicitação do ProxyEndpoint para oferecer suporte às solicitações de origem cruzada do cliente.

O compartilhamento de recursos entre origens (CORS, na sigla em inglês) é um mecanismo padrão que permite que chamadas JavaScript XMLHttpRequest (XHR) executadas em uma página da Web interajam com recursos de domínios que não são de origem. O CORS é uma solução comumente implementada na política de mesma origem que é aplicada por todos os navegadores. Por exemplo, se você fizer uma chamada XHR para a API Twitter a partir do código JavaScript em execução no seu navegador, a chamada falhará. Isso ocorre porque o domínio que veicula a página para o navegador não é o mesmo que usa a API Twitter. O CORS oferece uma solução para esse problema permitindo que os servidores optem por permitir o compartilhamento de recursos entre origens.

Para informações sobre como ativar o CORS nos proxies da API antes de publicar as APIs, consulte Como adicionar suporte ao CORS a um proxy de API.

Tamanho do payload da mensagem

Para evitar problemas de memória na Apigee, o tamanho do payload da mensagem é restrito a 10 MB. Exceder esses tamanhos resulta em um erro protocol.http.TooBigBody.

Esse problema também é discutido em Erro ao solicitar/retornar um payload grande com o proxy da Apigee.

Veja a seguir as estratégias recomendadas para lidar com mensagens grandes na Apigee:

Gerenciamento de falhas

  • Aproveite as FaultRules para processar todo o tratamento de falhas. As políticas RaiseFault são usadas para interromper o fluxo de mensagens e enviar o processamento para o Fluxo FaultRules.
  • Dentro do fluxo FaultRules, use uma política AssignMessage para criar a resposta de falha, e não uma política RaiseFault. Execute de modo condicional as políticas AssignMessage com base no tipo de falha que ocorre.
  • Sempre inclui um gerenciador de falhas padrão "pega-tudo" para que as falhas geradas pelo sistema sejam mapeadas para formatos de resposta a falhas definidos pelo cliente.
  • Se possível, sempre faça com que as respostas de falha correspondam a todos os formatos padrão disponíveis na sua empresa ou projeto.
  • Use mensagens de erro significativas e legíveis que sugiram uma solução para a condição do erro.

Consulte Como lidar com falhas.

Persistência

Mapas de chave-valor

  • Use mapas de chave-valor apenas para conjuntos de dados limitados. Eles não são projetados para ser um armazenamento de dados de longo prazo.
  • Pense no desempenho ao usar mapas de chave-valor, já que essas informações são armazenadas no banco de dados do Cassandra.

Consulte a política KeyValueMapOperations.

Armazenamento de respostas em cache

  • Não preencha o cache de resposta se a resposta não tiver êxito ou se a solicitação não for GET. Criações, atualizações e exclusões não devem ser armazenadas em cache. <SkipCachePopulation>response.status.code != 200 or request.verb != "GET"</SkipCachePopulation>
  • Preencha o cache com um único tipo de conteúdo consistente (por exemplo, XML ou JSON). Depois de recuperar uma entrada de responseCache, converta para o tipo de conteúdo necessário com JSONtoXML ou XMLToJSON. Isso impedirá o armazenamento duplo, triplo ou mais dados.
  • Verifique se a chave de cache é suficiente para o requisito de armazenamento em cache. Em muitos casos, o request.querystring pode ser usado como o identificador exclusivo.
  • Não inclua a chave de API (client_id) na chave de cache, a menos que seja explicitamente necessário. Na maioria das vezes, as APIs protegidas apenas por uma chave retornam os mesmos dados para todos os clientes de uma determinada solicitação. Não é eficiente armazenar o mesmo valor para várias entradas com base na chave de API.
  • Defina intervalos de expiração de cache apropriados para evitar leituras sujas.
  • Sempre que possível, tente fazer com que a política de cache de resposta que preencha o cache seja executada no PostFlow da resposta do ProxyEndpoint o mais tarde possível. Em outras palavras, faça-o depois das etapas de tradução e mediação, incluindo mediação baseada em JavaScript e conversão entre JSON e XML. Ao armazenar dados de mediação em cache, você evita o custo de desempenho da execução da etapa de mediação toda vez que recupera dados em cache.

    Em vez disso, convém armazenar os dados não mediados em cache se a mediação resultar em uma resposta diferente da solicitação para a solicitação.

  • A política de cache de resposta para pesquisar a entrada do cache precisa ocorrer no PreFlow da solicitação ProxyEndpoint. Evite implementar uma lógica muito diferente, além da geração de chaves de cache, antes de retornar uma entrada de cache. Caso contrário, os benefícios do armazenamento em cache são minimizados.
  • Em geral, você precisa sempre manter a pesquisa em cache da resposta o mais próxima possível da solicitação do cliente. Por outro lado, mantenha o preenchimento de cache de resposta o mais próximo possível da resposta do cliente.
  • Ao usar várias políticas de cache de resposta diferentes em um proxy, siga estas diretrizes para garantir um comportamento distinto para cada:
    • Execute cada política com base em condições mutuamente exclusivas. Isso ajudará a garantir que apenas uma das várias políticas de cache de resposta seja executada.
    • Defina recursos de cache diferentes para cada política de cache de resposta. Você especifica o recurso de cache no elemento <CacheResource> da política.

Consulte a Política de ResponseCache.

Política e código personalizado

Política ou código personalizado?

  • Use políticas incorporadas em primeiro lugar (quando possível). As políticas da Apigee são reforçadas, otimizadas e compatíveis. Por exemplo, use as políticas padrão AssignMessage e ExtractVariables em vez de JavaScript (quando possível) para criar payloads, extraia informações de payloads (XPath, JSONPath) e assim por diante.
  • O JavaScript tem preferência sobre Python e Java. No entanto, se o desempenho for o principal requisito, o Java deverá ser usado em JavaScript.

JavaScript

  • Use JavaScript se for mais intuitivo do que políticas da Apigee (por exemplo, ao definir target.url para muitas combinações de URI diferentes).
  • Análise de payload complexa, como iteração por meio de um objeto JSON e codificação/decodificação Base64.
  • A política JavaScript tem um limite de tempo, portanto, loops infinitos são bloqueados.
  • Sempre use as etapas de JavaScript e coloque os arquivos na pasta de recursos jsc. O tipo de política JavaScript pré-compila o código no momento da implantação.

Java

  • Use Java se o desempenho for a prioridade mais alta ou se a lógica não puder ser implementada em JavaScript.
  • Inclua arquivos de origem Java no rastreamento do código-fonte.

Consulte a política JavaCallout para informações sobre como usar o Java em proxies de API.

Python

  • Não use Python, a menos que seja absolutamente necessário. Scripts Python podem introduzir gargalos de desempenho para execuções simples, tendo em vista que são interpretados no ambiente de execução.

Frases de destaque de script (Java, JavaScript, Python)

  • Use um try/catch global ou equivalente.
  • Crie exceções significativas e capture-as adequadamente para uso em respostas de falha.
  • Acione e capture exceções antecipadamente. Não use o try/catch global para processar todas as exceções.
  • Execute verificações nulas e indefinidas, quando necessário. Um exemplo de quando fazer isso é ao recuperar variáveis de fluxo opcionais.
  • Evite fazer solicitações HTTP/S dentro de uma chamada de script. Em vez disso, use a política ServiceCallout tendo em vista que a política processa conexões normalmente.

JavaScript

  • O JavaScript na plataforma de API é compatível com XML via E4X.

Consulte Modelo de objeto JavaScript.

Java

  • Ao acessar os payloads das mensagens, tente usar context.getMessage() vs. context.getResponseMessage ou context.getRequestMessage. Isso garante que o código possa recuperar o payload em fluxos de solicitação e resposta.
  • Importe bibliotecas para a organização ou o ambiente da Apigee e não as inclua no arquivo JAR. Isso reduz o tamanho do pacote e permite que outros arquivos JAR acessem o mesmo repositório da biblioteca.
  • Importe arquivos JAR usando a API de recursos da Apigee em vez de incluí-los na pasta de recursos de proxy da API. Isso reduzirá os tempos de implantação e permitirá que os mesmos arquivos JAR sejam referenciados por vários proxies de API. Outro benefício é o isolamento do carregador de classes.
  • Não use Java para processamento de recursos (por exemplo, criar e gerenciar pools de linhas de execução).

Python

  • Crie exceções significativas e capture-as adequadamente para uso em respostas de falha da Apigee.

Veja a política do PythonScript.

ServiceCallouts

  • Há muitos casos de uso válidos para o uso do encadeamento de proxies, em que você usa uma chamada de serviço em um proxy de API para chamar outro proxy de API. Se você usar o encadeamento de proxy, evite as frases de destaque recursivas de loop infinito no mesmo proxy de API.

    Se você estiver se conectando entre proxies que estão na mesma organização e ambiente, verifique se há Encadeamento de proxies de API juntos para saber mais sobre como implementar uma conexão local que evita sobrecarga desnecessária de rede.

  • Crie uma mensagem de solicitação ServiceCallout usando a política AssignMessage e preencha o objeto de solicitação em uma variável de mensagem. Isso inclui definir o payload da solicitação, o caminho e o método.
  • O URL configurado na política requer a especificação do protocolo, ou seja, a parte do protocolo do URL, https://, por exemplo, não pode ser especificada por uma variável. Além disso, use variáveis separadas para a parte do domínio do URL e para o restante do URL. Por exemplo, https://example.com.
  • Armazene o objeto de resposta para um ServiceCallout em uma variável de mensagem separada. Em seguida, é possível analisar a variável da mensagem e manter o payload da mensagem original intacto para uso por outras políticas.

Consulte Política ServiceCallout.

Como acessar entidades

Política AccessEntity

  • Para melhorar o desempenho, procure aplicativos por uuid em vez do nome do aplicativo.

Consulte a Política AccessEntity.

Logging

  • Use uma política syslog comum em todos os pacotes e dentro do mesmo pacote. Isso manterá um formato de geração de registros consistente.

Consulte a política MessageLogging.

Monitoring

Os clientes do Cloud não precisam verificar componentes individuais da Apigee (Roteadores, processadores de mensagem, e assim por diante.). A equipe de operações globais da Apigee está monitorando de forma completa todos os componentes com verificações de integridade da API, de acordo com as solicitações de verificação de integridade do cliente.

Análise da Apigee

As análises podem fornecer monitoramento não crítico da API à medida que as porcentagens de erro são medidas.

Consulte os painéis do Google Analytics.

Debug

A ferramenta Trace na IU da Apigee é útil para depurar problemas da API de ambiente de execução durante a operação de desenvolvimento ou produção de uma API.

Consulte Como usar a ferramenta de depuração.

Segurança

Lógica personalizada em proxies de API

Um requisito comum ao criar proxies de API é incluir alguma lógica para processar solicitações e/ou respostas. Embora muitos requisitos possam ser atendidos a partir de um conjunto predefinido de etapas/ações/políticas, como verificar um token ou aplicar uma cota ou responder com um objeto armazenado em cache, muitas vezes pode ser necessário acesso à programação. Por exemplo, pesquisar um local (endpoint) de uma tabela de roteamento com base em uma chave encontrada em uma solicitação e aplicar dinamicamente um endpoint de destino ou um método de autenticação personalizado/proprietário etc.

A Apigee oferece ao desenvolvedor várias opções para lidar com essa lógica personalizada. Este documento explorará essas opções e quando usar quais:

Política Casos de uso da política
JavaScript e PythonScript

Quando usar:

  • As políticas JavaScript e PythonScript são equivalentes em termos de capacidade. A familiaridade de um desenvolvedor em uma linguagem normalmente é o motivo de escolher uma em vez da outra.
  • As políticas JavaScript e PythonScript são mais adequadas para processar a lógica in-line que não é excessivamente complexa e não requer o uso de bibliotecas de terceiros.
  • Essas políticas não têm um desempenho tão bom quanto a política JavaCallout.

Quando o uso não é recomendado:

  • O gateway da API da Apigee não é um servidor de aplicativos (nem fornece o ambiente de execução JavaScript completo, como node.js). Se a chamada sempre demorar mais de um segundo para ser processada, é provável que a lógica não pertença ao gateway e faça parte do serviço subjacente.

Prática recomendada: a Apigee recomenda o JavaScript no Python, já que ele oferece o melhor desempenho.

JavaCallout

Quando usar:

  • O desempenho do processamento da lógica in-line é fundamental.
  • As bibliotecas Java existentes fornecem grande parte da lógica.

Quando o uso não é recomendado:

  • O gateway da API da Apigee não é um servidor de aplicativos e não se destina a carregar frameworks como Spring, JEE etc. Se a chamada normalmente leva mais de um segundo para ser processada, a lógica pode ser considerada como funcional (lógica de negócios). Considere a externalização como um serviço.
  • Para proteger o gateway da API Apigee contra abuso, existem restrições aplicadas ao tipo de código que pode ser executado. Por exemplo, o código Java que tenta acessar determinadas bibliotecas criptográficas ou acessar o sistema de arquivos é bloqueado para execução.
  • Aplicativos Java, especialmente aqueles que dependem de bibliotecas de terceiros, podem trazer muitos arquivos JAR grandes. Isso pode atrasar o tempo de inicialização dos gateways.
ExternalCallout

Quando usar:

  • Ideal para externalizar a lógica personalizada e permitir que a lógica personalizada acesse (e, se necessário, modifique) o contexto da mensagem.
  • As chamadas externas implementam o gRPC e podem ter um desempenho melhor do que uma ServiceCallout.
  • Ao usar a Apigee ou a Apigee híbrida no Google Cloud, considere usar o Cloud Functions ou o Cloud Run para hospedar essa lógica.
  • Como uma substituição eficaz do recurso "Destinos hospedados" no Apigee Edge.

Quando não usar:

  • Para uma lógica leve que pode ser executada rapidamente e in-line.
ServiceCallout

Quando usar:

  • A lógica complexa é melhor implementada fora do gateway. Essa lógica pode ter o próprio ciclo de vida (lançamentos e controle de versões) e não afeta o funcionamento do gateway.
  • Quando o endpoint REST/SOAP/GraphQL já existe ou pode ser implementado facilmente
  • Ao usar a Apigee ou a Apigee híbrida no Google Cloud, considere usar o Cloud Functions ou o Cloud Run para hospedar essa lógica.
  • Como uma substituição eficaz do recurso "Destinos hospedados" no Apigee Edge.

Quando não usar:

  • Para uma lógica leve que pode ser executada rapidamente e in-line.
  • O proxy da API precisa transferir o contexto (como variáveis) ou receber contexto da implementação externa

Para resumir:

  1. Se a lógica for simples ou trivial, use JavaScript (de preferencialmente) ou PythonScript.
  2. Se a lógica in-line exigir um desempenho melhor do que o JavaScript ou o PythonScript, use o JavaCallout.
  3. Se a lógica precisar ser externalizada, use ExternalCallout.
  4. Se você já tiver implementações externas e/ou os desenvolvedores estiverem familiarizados com a REST, use ServiceCallout.

A figura a seguir ilustra esse processo: