Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Not
Azure Yapay Zeka Arama Azure portalı, REST API'leri ve Azure SDK’ları aracılığıyla kullanılabilir. Ayrıca kuruluş içeriğini Microsoft Foundry portalındaki aracılar için yeniden kullanılabilir, izin kullanan bilgi bankalarına dönüştüren yönetilen bilgi katmanı Foundry IQ'yu temel alır.
Dizinler ve veri kaynakları gibi Azure Yapay Zeka Arama kaynakları yönetirken, özellikle de uygulamanızın farklı bileşenleri tarafından kaynaklara eşzamanlı olarak erişiliyorsa kaynakları güvenli bir şekilde güncelleştirmek önemlidir.
- Kaynak güncelleştirme işlemleri hemen tamamlanmayabilir. Örneğin, bir dizini veya dizin oluşturucu güncelleştirme işleminin tamamlanması birkaç saniye sürebilir. Kaynak güncelleştirmeleri seri hale getirilir, bu da aynı kaynakta birden çok güncelleştirme işleminin aynı anda çalışmayabileceği anlamına gelir.
- İki istemci eş zamanlı olarak koordinasyon olmadan bir kaynağı güncelleştirdiğinde, bir yarış durumu mümkündür. Bir istemci bir güncelleştirme işlemi başlatabilirken diğer istemci bir çakışma hatası alır. Bunu önlemek için Azure Yapay Zeka Arama optimistic eşzamanlılık modelini destekler. Kaynakta kilit yok. Bunun yerine, her kaynak için kaynak sürümünü tanımlayan bir ETag vardır, böylece yanlışlıkla üzerine yazmayı önleyen istekleri formüle edebilirsiniz.
Nasıl çalışır?
İyimser eşzamanlılık, dizinlere, dizin oluşturuculara, veri kaynaklarına, beceri kümelerine, bilgi bankalarına ve synonymMap kaynaklarına yazılan API çağrılarında access koşul denetimleri aracılığıyla uygulanır.
Tüm kaynakların nesne sürümü bilgilerini sağlayan bir varlık etiketi (ETag) vardır. İlk olarak ETag'i denetleyerek, kaynağın ETag'inin yerel kopyanızla eşleştiğinden emin olarak tipik bir iş akışında eşzamanlı güncelleştirmelerden (yerel olarak alma, değiştirme, güncelleştirme) kaçınabilirsiniz.
REST API, istek üst bilgisinde ETag kullanır.
.NET için Azure SDK'sı, accessCondition sınıfı aracılığıyla ETag'i ayarlayarak kaynak üzerine If-Match | If-Match-None üst bilgileri ekler. SynonymMap.ETag ve SearchIndex.ETag gibi ETag kullanan nesnelerin accessCondition sınıfı vardır.
Bir kaynağı her güncelleştirdiğinizde ETag'i otomatik olarak değişir. Eşzamanlılık yönetimi uyguladığınızda, tek yaptığınız güncelleştirme isteğine uzak kaynağın istemcide değiştirdiğiniz kaynağın kopyasıyla aynı ETag'e sahip olmasını gerektiren bir önkoşul koymaktır. Başka bir işlem uzak kaynağı değiştirirse, ETag önkoşulla eşleşmez ve istek HTTP 412 veya 409 ile başarısız olur. .NET SDK'sını kullanıyorsanız, bu hata, IsAccessConditionFailed() uzantısı yönteminin true döndürdüğü bir özel durum olarak ortaya çıkar.
Not
Eşzamanlılık için tek bir mekanizma vardır. Kaynak güncelleştirmeleri için hangi API veya SDK kullanıldığından bağımsız olarak her zaman kullanılır. 18 Temmuz 2025'te Azure Yapay Zeka Arama tutarlılık ve güvenilirlik sağlamak amacıyla dizin oluşturma ve güncelleştirme işlemleri için serileştirmeyi zorunlu kılmaya başladı.
Örnek
Aşağıdaki kod, güncelleştirme işlemi için iyimser eşzamanlılığı gösterir. Nesnenin ETag'i önceki bir güncelleştirmeyle değiştirildiğinden ikinci güncelleştirme başarısız olur. Daha açık belirtmek gerekirse, istek üst bilgisindeki ETag artık nesnenin ETag değeriyle eşleşmediğinde, search service 400 (hatalı istek) durum kodu döndürür ve güncelleştirme başarısız olur.
using Azure;
using Azure.Search.Documents;
using Azure.Search.Documents.Indexes;
using Azure.Search.Documents.Indexes.Models;
using System;
using System.Net;
using System.Threading.Tasks;
namespace AzureSearch.SDKHowTo
{
class Program
{
// This sample shows how ETags work by performing conditional updates and deletes
// on an Azure Search index.
static void Main(string[] args)
{
string serviceName = "PLACEHOLDER FOR YOUR SEARCH SERVICE NAME";
string apiKey = "PLACEHOLDER FOR YOUR SEARCH SERVICE ADMIN API KEY";
// Create a SearchIndexClient to send create/delete index commands
Uri serviceEndpoint = new Uri($"https://{serviceName}.search.windows.net/");
AzureKeyCredential credential = new AzureKeyCredential(apiKey);
SearchIndexClient adminClient = new SearchIndexClient(serviceEndpoint, credential);
// Delete index if it exists
Console.WriteLine("Check for index and delete if it already exists...\n");
DeleteTestIndexIfExists(adminClient);
// Every top-level resource in Azure Search has an associated ETag that keeps track of which version
// of the resource you're working on. When you first create a resource such as an index, its ETag is
// empty.
SearchIndex index = DefineTestIndex();
Console.WriteLine(
$"Test searchIndex hasn't been created yet, so its ETag should be blank. ETag: '{index.ETag}'");
// Once the resource exists in Azure Search, its ETag is populated. Make sure to use the object
// returned by the SearchIndexClient. Otherwise, you will still have the old object with the
// blank ETag.
Console.WriteLine("Creating index...\n");
index = adminClient.CreateIndex(index);
Console.WriteLine($"Test index created; Its ETag should be populated. ETag: '{index.ETag}'");
// ETags prevent concurrent updates to the same resource. If another
// client tries to update the resource, it will fail as long as all clients are using the right
// access conditions.
SearchIndex indexForClientA = index;
SearchIndex indexForClientB = adminClient.GetIndex("test-idx");
Console.WriteLine("Simulating concurrent update. To start, clients A and B see the same ETag.");
Console.WriteLine($"ClientA ETag: '{indexForClientA.ETag}' ClientB ETag: '{indexForClientB.ETag}'");
// indexForClientA successfully updates the index.
indexForClientA.Fields.Add(new SearchField("a", SearchFieldDataType.Int32));
indexForClientA = adminClient.CreateOrUpdateIndex(indexForClientA);
Console.WriteLine($"Client A updates test-idx by adding a new field. The new ETag for test-idx is: '{indexForClientA.ETag}'");
// indexForClientB tries to update the index, but fails due to the ETag check.
try
{
indexForClientB.Fields.Add(new SearchField("b", SearchFieldDataType.Boolean));
adminClient.CreateOrUpdateIndex(indexForClientB);
Console.WriteLine("Whoops; This shouldn't happen");
Environment.Exit(1);
}
catch (RequestFailedException e) when (e.Status == 400)
{
Console.WriteLine("Client B failed to update the index, as expected.");
}
// Uncomment the next line to remove test-idx
//adminClient.DeleteIndex("test-idx");
Console.WriteLine("Complete. Press any key to end application...\n");
Console.ReadKey();
}
private static void DeleteTestIndexIfExists(SearchIndexClient adminClient)
{
try
{
if (adminClient.GetIndex("test-idx") != null)
{
adminClient.DeleteIndex("test-idx");
}
}
catch (RequestFailedException e) when (e.Status == 404)
{
//if an exception occurred and status is "Not Found", this is working as expected
Console.WriteLine("Failed to find index and this is because it's not there.");
}
}
private static SearchIndex DefineTestIndex() =>
new SearchIndex("test-idx", new[] { new SearchField("id", SearchFieldDataType.String) { IsKey = true } });
}
}
Tasarım deseni
İyimser eşzamanlılığı uygulamak için bir tasarım deseni, erişim şartı denetimini yeniden deneyen bir döngü, erişim şartı için bir test içermeli ve isteğe bağlı olarak değişiklikleri yeniden uygulamayı denemeden önce güncellenmiş bir kaynağı almalıdır.
Bu kod parçacığı, zaten var olan bir dizine synonymMap eklenmesini gösterir.
Kod parçacığı hotels-sample dizinini alır, bir güncelleştirme işleminde nesne sürümünü denetler, koşul başarısız olursa bir özel durum oluşturur ve ardından en son sürümü almak için sunucudan dizin alma işleminden başlayarak işlemi (en fazla üç kez) yeniden dener.
private static void EnableSynonymsInHotelsIndexSafely(SearchIndexClient indexClient)
{
int MaxNumTries = 3;
for (int i = 0; i < MaxNumTries; ++i)
{
try
{
SearchIndex index = indexClient.GetIndex("hotels-sample");
index = AddSynonymMapsToFields(index);
// The onlyIfUnchangedcondition ensures that the index is updated only if the ETags match.
indexClient.CreateOrUpdateIndex(index, onlyIfUnchanged: true);
Console.WriteLine("Updated the index successfully.\n");
break;
}
catch (RequestFailedException e) when (e.Status == 412)
{
Console.WriteLine($"Index update failed : {e.Message}. Attempt({i}/{MaxNumTries}).\n");
}
}
}
private static SearchIndex AddSynonymMapsToFields(SearchIndex index)
{
index.Fields.First(f => f.Name == "category").SynonymMapNames.Add("desc-synonymmap");
index.Fields.First(f => f.Name == "tags").SynonymMapNames.Add("desc-synonymmap");
return index;
}