Aracılığıyla paylaş


İlke parçaları için merkezi meta veri önbelleği

UYGULANANLAR: Tüm API Management katmanları

Birden çok ilke parçasının ortak yapılandırma verileri gibi paylaşılan meta verilere erişmesi gerektiğinde, performansı iyileştirmek için istekler arası önbelleğe alma yaklaşımını kullanın. Meta verileri her parçada tekrar tekrar ayrı ayrıştırmak yerine, her yerde önbelleğe alma yaklaşımı performansı önemli ölçüde artırır ve veri tutarlılığı sağlar. Bu yaklaşımla, önbellek boş olduğunda ilk istekte meta veriler ayrıştırılır , ardından önbellek süresi dolana veya önbellek sürümü değişene kadar sonraki tüm istekler için önbellekten alınır .

Bu yaklaşım iki parça gerektirir: biri paylaşılan meta verileri depolamak için, diğeri de meta verileri ayrıştırıp önbelleğe almak için.

1. Meta veri parçası

Meta veri parçası, işlem hattındaki diğer parçalar tarafından erişilen paylaşılan meta veriler için tek bir gerçek kaynağı olarak görev görür:

  • Merkezi JSON depolama: Tüm meta verileri JSON olarak depolar.
  • Önbellek ayarları: Sürüm oluşturma ve süre (Yaşam Süresi veya TTL) ile önbellek ayarlarını içerir.

2. Parça ayrıştırma ve önbelleğe alma

Ayrıştırma ve önbelleğe alma parçası aşağıdaki davranışları uygular:

  • Tek ayrıştırma işlemi: Önbellek boşsa her işlem hattı isteğinin başlangıcında meta veri parçasında depolanan JSON'ı ayrıştırmak için kullanılır JObject.Parse() .
  • İstekler arası önbelleğe alma: Birden çok istekte yerleşik JObject ve önbellek-arama-değeri ilkelerini kullanarak ayrıştırılmış meta veri bölümlerini depolar ve alır.
  • Önbellek öncelikli erişim: Sonraki istekler, tüm parçalara anında erişim sağlayarak, yeniden ayrıştırma işlemi gerektirmeden doğrudan önbellekten ayrıştırılmış bir JObject getirir.
  • Önbellek geçersizliği: Meta veri sürümü değiştiğinde veya önbellek süresi (TTL) sona erdiğinde önbellek yenilenir.

Uygulama ayrıntıları

Bu modeli uygulamak için, her iki parçayı da gelen istekler aşamasının başında bir ürün veya API ilkesinin tanımına ekleyin. Meta veri parçasının önce eklenmesi, ardından ayrıştırma ve önbelleğe alma parçasının eklenmesi gerekir. Örneğin:

<policies>
    <inbound>
        <base />
        <include-fragment fragment-id="metadata-fragment" />
        <include-fragment fragment-id="parse-cache-fragment" />
    </inbound>
</policies>

Meta veri parçası örneği

Bölüm, metadata-fragment.xml paylaşılan JSON meta verilerini bağlam değişkenleri adı içinde metadata-config depolar:

<!-- 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>

Parça ayrıştırma ve önbelleğe alma örneği

parse-cache-fragment.xml parçacığı, metadata-config bağlam değişkeninde depolanan JSON'u bir kez ayrıştırır ve elde edilen JObject öğesine erişim sağlar. metadata-config değişkeni metadata-fragment.xml tarafından zaten ayarlanmış olmalıdır.

<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>

Diğer parçalarda meta verileri kullanma

Diğer parçalar artık ayrıştırılmış meta veri bölümlerine doğrudan erişebilir. Örneğin:

<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>

Önbellek ayarları ve geçersizleştirme

parse-cache-fragment.xml parçası, önbelleğe alma davranışını ve geçersizleştirmeyi belirlemek için metadata-fragment.xml parçasında depolanan önbellek ayarlarını kullanır. Örneğin, ayarlar aşağıdaki gibi değiştirilebilir:

<!-- 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'
  }
}

Önbellek geçersizleştirme nasıl çalışır: Parça, parse-cache-fragment.xml değerini kullanarak config-version önbellek anahtarlarını oluşturur (örneğin, metadata-config-v1.0.1). Sürüm 1.0.2 olarak değiştirildiğinde, yeni bir önbellek anahtarı (metadata-config-v1.0.2) oluşturulur. Yeni anahtar için önbelleğe alınmış veri olmadığından, parça yeni meta veri JSON'unu ayrıştırır.

Önbellek yenilemesini zorlamak için:metadata-fragment.xml parçacığındaki config-version öğesini güncelleştirin. Önbellek ayarları, önbellek araması gerçekleşmeden önce her istekte ayrıştırıldığından, önbellek yapılandırmasındaki değişiklikler hemen geçerli olur.

Test etme ve hata ayıklama

Önbellek sonuçlarının takibi

Parça parse-cache-fragment.xml bir config-cache-result değişken ayarlar. Bu değişken, hata ayıklama amacıyla hem günlüğe kaydetmede hem de yanıt üst bilgileri içerisinde yararlıdır.

<!-- 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>

Önbellek atlama

Önbelleğe almayı devre dışı bırakmak için önbellek atlama üst bilgisini kullanın:

curl -H "X-Config-Cache-Bypass: true" https://your-gateway.com/api

Parça, parse-cache-fragment.xml önbellek ayarlarını ayrıştırdıktan sonra atlama üst bilgisini denetler:

<!-- 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";
}" />

Atlama denetimi daha sonra önbelleğe alma karar mantığında kullanılır:

<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>

En iyi yöntemler

Hata günlüğü ve varsayılanlarla JSON ayrıştırma hatalarını işleme

Parça hatalarını önlemek ve geri dönüş davranışı sağlamak için JSON ayrıştırma işlemleri için hata işlemeyi uygulayın. Try-catch bloklarındaki JObject.Parse() işlemlerini anlamlı varsayılan değerlerle sarmalayın.

<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>