Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
APLICA-SE A: Todas as camadas de gerenciamento de API
Quando múltiplos fragmentos de política precisam de acesso a metadados partilhados, como dados de configuração comuns, utilize-se uma abordagem de cache cross-request para otimizar o desempenho. Em vez de analisar metadados repetidamente em cada fragmento, uma abordagem de análise uma vez e cache em todo o lado melhora drasticamente o desempenho, garantindo a consistência dos dados. Com esta abordagem, os metadados são analisados uma vez no primeiro pedido quando a cache está vazia, e depois recuperados da cache para todos os pedidos subsequentes até que a cache expire ou a versão da cache mude.
Abordagem recomendada
Esta abordagem requer dois fragmentos: um para armazenar metadados partilhados e outro para analisar e armazenar em cache os metadados.
1. Fragmento de metadados
O fragmento de metadados serve como a única fonte confiável para metadados partilhados que são acedidos por outros fragmentos no pipeline.
- Armazenamento JSON centralizado: Armazena todos os metadados como JSON.
- Definições de cache: Inclui definições de cache com versionamento e duração (Time to Live, ou TTL).
** 2. Análise e cache de fragmentos
O fragmento de análise e cache implementa os seguintes comportamentos:
-
Operação única de análise sintética: Utiliza
JObject.Parse()para analisar o JSON armazenado no fragmento de metadados uma vez no início de cada pedido de pipeline, caso a cache esteja vazia. -
Cache entre pedidos: Armazena e recupera secções de metadados analisadas sob a forma de
JObjectutilizando as políticas integradas cache-store-value e cache-lookup-value em vários pedidos. -
Acesso com prioridade para cache: Pedidos subsequentes recuperam um analisado
JObjectdiretamente do cache, proporcionando acesso imediato a todos os fragmentos sem necessidade de nova análise. - Invalidação da cache: A cache atualiza-se quando a versão dos metadados muda ou quando a duração da cache (TTL) expira.
Detalhes da implementação
Para implementar este padrão, insira ambos os fragmentos numa definição de política de produto ou API no início da fase de entrada. O fragmento de metadados deve ser inserido primeiro, seguido pelo fragmento de análise e cache. Por exemplo:
<policies>
<inbound>
<base />
<include-fragment fragment-id="metadata-fragment" />
<include-fragment fragment-id="parse-cache-fragment" />
</inbound>
</policies>
Exemplo de fragmento de metadados
O metadata-fragment.xml fragmento armazena metadados JSON partilhados numa variável de contexto chamada metadata-config:
<!-- Single source of truth for all shared metadata -->
<fragment fragment-id="metadata-fragment">
<set-variable name="metadata-config" value="@{return @"{
'cache-settings': {
'config-version': '1.0',
'ttl-seconds': 3600,
'feature-flags': {
'enable-cross-request-cache': true,
'cache-bypass-header': 'X-Config-Cache-Bypass'
}
},
'logging': {
'level': 'INFO',
'enabled': true
},
'rate-limits': {
'premium': { 'requests-per-minute': 1000 },
'standard': { 'requests-per-minute': 100 },
'basic': { 'requests-per-minute': 20 }
}
}";}" />
</fragment>
Exemplo de fragmento de análise sintática e cache
O parse-cache-fragment.xml fragmento analisa o JSON armazenado na metadata-config variável de contexto uma vez e fornece acesso ao resultado JObject. A metadata-config variável já deve estar definida por metadata-fragment.xml:
<fragment fragment-id="parse-cache-fragment">
<!-- Extract cache settings from metadata-config to determine cache version and TTL -->
<set-variable name="cache-config-temp" value="@{
try {
var configStr = context.Variables.GetValueOrDefault<string>("metadata-config", "{}");
if (string.IsNullOrEmpty(configStr) || configStr == "{}") {
return "{\"version\":\"1.0\",\"enabled\":true,\"ttl\":3600}";
}
var tempConfig = JObject.Parse(configStr);
var cacheSettings = tempConfig["cache-settings"] as JObject;
var result = new JObject();
result["version"] = cacheSettings?["config-version"]?.ToString() ?? "1.0";
result["enabled"] = cacheSettings?["feature-flags"]?["enable-cross-request-cache"]?.Value<bool>() ?? true;
result["ttl"] = cacheSettings?["ttl-seconds"]?.Value<int>() ?? 3600;
return result.ToString(Newtonsoft.Json.Formatting.None);
} catch {
return "{\"version\":\"1.0\",\"enabled\":true,\"ttl\":3600}";
}
}" />
<!-- Parse cache configuration -->
<set-variable name="cache-settings-parsed" value="@{
return JObject.Parse(context.Variables.GetValueOrDefault<string>("cache-config-temp", "{}"));
}" />
<!-- Build cache key with version from cache settings -->
<set-variable name="cache-key" value="@{
var settings = context.Variables.GetValueOrDefault<JObject>("cache-settings-parsed");
var version = settings?["version"]?.ToString() ?? "1.0";
return "metadata-config-parsed-v" + version;
}" />
<!-- Try to get from APIM cache -->
<cache-lookup-value key="@(context.Variables.GetValueOrDefault<string>("cache-key"))" variable-name="cached-config" />
<choose>
<when condition="@(context.Variables.ContainsKey("cached-config"))">
<!-- Cache found - Use cached configuration -->
<set-variable name="config-cache-result" value="@(true)" />
<!-- Restore cached config-parsed -->
<set-variable name="config-parsed" value="@(context.Variables.GetValueOrDefault<JObject>("cached-config"))" />
<!-- Extract sections from cached metadata JObject -->
<set-variable name="config-logging" value="@{
var config = context.Variables.GetValueOrDefault<JObject>("config-parsed");
return config["logging"] as JObject ?? new JObject();
}" />
<set-variable name="config-rate-limits" value="@{
var config = context.Variables.GetValueOrDefault<JObject>("config-parsed");
return config["rate-limits"] as JObject ?? new JObject();
}" />
</when>
<otherwise>
<!-- Cache miss - Parse and store in cache -->
<set-variable name="config-cache-result" value="@(false)" />
<!-- Parse metadata-config JSON -->
<set-variable name="config-parsed" value="@{
var configStr = context.Variables.GetValueOrDefault<string>("metadata-config", "{}");
return JObject.Parse(configStr);
}" />
<!-- Extract commonly used sections for direct access -->
<set-variable name="config-logging" value="@{
var config = context.Variables.GetValueOrDefault<JObject>("config-parsed");
return config["logging"] as JObject ?? new JObject();
}" />
<set-variable name="config-rate-limits" value="@{
var config = context.Variables.GetValueOrDefault<JObject>("config-parsed");
return config["rate-limits"] as JObject ?? new JObject();
}" />
<!-- Store parsed metadata JObject in cache -->
<cache-store-value key="@(context.Variables.GetValueOrDefault<string>("cache-key"))"
value="@(context.Variables.GetValueOrDefault<JObject>("config-parsed"))"
duration="@(context.Variables.GetValueOrDefault<JObject>("cache-settings-parsed")?["ttl"]?.Value<int>() ?? 3600)" />
</otherwise>
</choose>
</fragment>
Utilização de metadados noutros fragmentos
Outros fragmentos podem agora aceder diretamente a secções de metadados analisadas. Por exemplo:
<fragment fragment-id="request-logging-fragment">
<!-- Access logging metadata JObject without reparsing -->
<set-variable name="config-logging" value="@{
return context.Variables.GetValueOrDefault<JObject>("config-logging", new JObject());
}" />
</fragment>
Definições de cache e invalidação
O fragmento parse-cache-fragment.xml utiliza as definições de cache armazenadas no fragmento metadata-fragment.xml para determinar o comportamento de cache e a invalidade. Por exemplo, as definições podem ser alteradas da seguinte forma:
<!-- Example: Updated cache settings in the metadata fragment -->
'cache-settings': {
'config-version': '1.0.1', <!-- Change version to invalidate cache -->
'ttl-seconds': 7200, <!-- Increase TTL to 2 hours -->
'feature-flags': {
'enable-cross-request-cache': true,
'cache-bypass-header': 'X-Config-Cache-Bypass'
}
}
Como funciona a invalidação de cache: O parse-cache-fragment.xml fragmento constrói chaves de cache usando o config-version valor (por exemplo, metadata-config-v1.0.1). Quando a versão é alterada para 1.0.2, é criada uma nova chave de cache (metadata-config-v1.0.2). Como não existem dados em cache para a nova chave, o fragmento analisa novos metadados em JSON.
Para forçar a atualização da cache: Atualize o config-version no metadata-fragment.xml fragmento. Como as definições de cache são analisadas em cada pedido antes de ocorrer a consulta de cache, as alterações à configuração da cache entram em vigor imediatamente.
Teste e depuração
Rastreamento de resultados de cache
O parse-cache-fragment.xml fragmento define uma config-cache-result variável. Esta variável é útil para registos e cabeçalhos de resposta para depuração:
<!-- Add cache status to response headers for debugging -->
<set-header name="X-Config-Cache-Result" exists-action="override">
<value>@(context.Variables.GetValueOrDefault<bool>("config-cache-result", false).ToString())</value>
</set-header>
Ignorar cache
Para desativar a cache, use o cabeçalho para contornar a cache.
curl -H "X-Config-Cache-Bypass: true" https://your-gateway.com/api
O parse-cache-fragment.xml fragmento verifica o cabeçalho de bypass depois de analisar as definições da cache:
<!-- Check if cache bypass is requested -->
<set-variable name="cache-bypass-requested" value="@{
var settings = context.Variables.GetValueOrDefault<JObject>("cache-settings-parsed");
var bypassHeader = settings?["bypass-header"]?.ToString() ?? "X-Config-Cache-Bypass";
return context.Request.Headers.GetValueOrDefault(bypassHeader, "").ToLower() == "true";
}" />
A verificação de bypass é então usada na lógica de decisão de cache.
<when condition="@{
var settings = context.Variables.GetValueOrDefault<JObject>("cache-settings-parsed");
var enabled = settings?["enabled"]?.Value<bool>() ?? false;
var bypass = context.Variables.GetValueOrDefault<bool>("cache-bypass-requested", false);
return enabled && !bypass;
}">
<!-- Cross-request caching is enabled and not bypassed -->
</when>
Melhores práticas
Gerir falhas no processamento de JSON com registo de erros e valores predefinidos
Implementar o tratamento de erros para operações de análise JSON para evitar falhas de fragmentos e proporcionar comportamento de recuo. Envolver operações JObject.Parse() em blocos try-catch com valores padrão significativos:
<set-variable name="config-parsed" value="@{
try {
var configJson = context.Variables.GetValueOrDefault<string>("metadata-config", "{}");
return JObject.Parse(configJson);
} catch (Exception ex) {
// Return default configuration on parse failure
return JObject.Parse(@"{
'logging': { 'level': 'ERROR', 'enabled': false },
'rate-limits': { 'default': { 'requests-per-minute': 10 } }
}");
}
}" />
<!-- Log parse error using trace policy -->
<choose>
<when condition="@(context.Variables.ContainsKey("parse-error"))">
<trace source="config-parse" severity="error">
<message>@("JSON parse failed: " + context.Variables.GetValueOrDefault<string>("parse-error"))</message>
</trace>
</when>
</choose>
Conteúdo relacionado
- Arquitetura para construção de pipelines de execução avançada com fragmentos de políticas - Padrões fundamentais para desenhar arquiteturas modulares e escaláveis de fragmentos de políticas com clara separação de preocupações.
- Gestão de variáveis para fragmentos de políticas - Orientação abrangente sobre o tratamento de variáveis de contexto, padrões de acesso seguro e comunicação entre fragmentos.
- Injeção de políticas e coordenação com fragmentos - Padrões de injeção de fragmentos e coordenação entre políticas de produto e API.
- Cache personalizada no Azure API Management - Aprenda a armazenar itens em cache por chave e a modificar a chave usando cabeçalhos de pedido.