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.
Dikkatlice tasarlanmış bir RESTful web API'si, istemci uygulamaları tarafından erişilebilen kaynakları, ilişkileri ve gezinti düzenlerini tanımlar. Bir web API’sini uygulayıp dağıttığınızda, verilerin mantıksal yapısı yerine web API’sini barındıran ortamın fiziksel gereksinimlerini ve web API'sinin hangi şekilde oluşturulduğunu göz önünde bulundurmanız gerekir. Bu kılavuz, bir web API'sini uygulamaya ve istemci uygulamalarının kullanımına açmak için yayımlamaya yönelik en iyi yöntemlere odaklanır. Web API'si tasarımı hakkında ayrıntılı bilgi için bkz . Web API'si tasarımı.
İstekleri işleme
İstekleri işlemek üzere kod uygularken aşağıdaki noktaları göz önünde bulundurun.
GET, PUT, DELETE, HEAD ve PATCH eylemleri idempotent olmalıdır
Bu istekleri uygulayan kod herhangi yan etki oluşturmamalıdır. Aynı kaynak üzerinde yinelenen aynı istek, aynı durumla sonuçlanmalıdır. Örneğin, yanıt iletilerindeki HTTP durum kodu farklı olsa da, aynı URI'ye birden çok DELETE isteği göndermek aynı etkiye sahip olmalıdır. İlk DELETE isteği 204 (İçerik Yok) durum kodunu, sonraki bir DELETE isteği ise 404 (Bulunamadı) durum kodunu döndürebilir.
Not
Uygulama kılavuzu için bkz. Etkili ileti işleme. Uygulamada, ilk olarak bir işlemin doğal olarak idempotent olup olmadığını belirleyin ve değilse, işlenen ileti kimliklerini izleyerek ve yinelenenleri proaktif veya reaktif olarak ele alarak yapay idempotentlik uygulayın.
Yeni kaynaklar oluşturan POST eylemlerinin ilişkisiz yan etkileri olmamalıdır
POST isteğinin yeni bir kaynak oluşturması amaçlanıyorsa, isteğin etkileri yeni kaynakla (ve bir tür bağlantı söz konusuysa muhtemelen doğrudan ilgili tüm kaynaklarda) sınırlandırılmalıdır. Örneğin, bir e-ticaret sisteminde, müşteri için yeni bir sipariş oluşturan bir POST isteği de envanter düzeylerini değiştirebilir ve fatura bilgileri oluşturabilir, ancak siparişle doğrudan ilgili olmayan bilgileri değiştirmemeli veya sistemin genel durumu üzerinde başka bir yan etkisi olmamalıdır.
Sık iletişim kuran POST, PUT ve DELETE işlemlerini uygulamaktan kaçının
API'nizi fazla iletişimli işlemlere göre tasarlamaktan kaçının. Her istek protokol, ağ ve işlem yüküyle birlikte gelir. Örneğin, daha büyük bir toplu iş isteği yerine 100 daha küçük istek yürütmek, istemcide, ağda ve kaynak sunucusunda ek yüke neden olur. Mümkün olduğunda, yalnızca tek tek kaynaklar yerine kaynak koleksiyonları için HTTP fiili desteği sağlayın.
- Bir koleksiyona get isteği aynı anda birden çok kaynak alabilir.
- POST isteği birden çok yeni kaynağın ayrıntılarını içerebilir ve bunların tümünü aynı koleksiyona ekleyebilir.
- PUT isteği, bir koleksiyondaki tüm kaynak kümesinin yerini alabilir.
- DELETE isteği koleksiyonun tamamını kaldırabilir.
ASP.NET Web API 2'de bulunan Açık Veri Protokolü (OData) desteği, istekleri toplu olarak oluşturma olanağı sağlar. bir istemci uygulaması birkaç web API'si isteği paketleyebilir ve bunları tek bir HTTP isteğinde sunucuya gönderebilir ve her isteğin yanıtlarını içeren tek bir HTTP yanıtı alabilir. Daha fazla bilgi için bkz . Web API'sinde Batch'i Etkinleştirme OData Hizmeti.
Yanıt gönderirken HTTP belirtimini takip edin
Bir web API’si, istemcinin sonucu nasıl işleyeceğini belirlemesi için doğru HTTP durum kodunu, istemcinin sonucun niteliğini anlayabilmesi için uygun HTTP üst bilgilerini ve istemcinin sonucu ayrıştırması için uygun şekilde biçimlendirilmiş bir gövdeyi içeren iletiler döndürmelidir.
Örneğin, bir POST işlemi 201 (Oluşturuldu) durum kodunu döndürmeli ve yanıt iletisi, yanıt iletisinin Konum üst bilgisinde yeni oluşturulan kaynağa ait URI’yi içermelidir.
İçerik anlaşmasını destekler
Yanıt iletisinin gövdesi çeşitli biçimlerde veriler içerebilir. Örneğin, bir HTTP GET isteği JSON veya XML biçiminde veri döndürebilir. İstemci bir istek gönderdiğinde, hangi veri biçimlerini işleyebileceğini belirtir bir Accept başlığı içerebilir. Bu biçimler medya türleri olarak belirtilir. Örneğin, bir görüntüyü alan bir GET isteği veren bir istemci, istemcinin işleyebileceği medya türlerini listeleyen accept üst bilgisini (gibi) image/jpeg, image/gif, image/pngbelirtebilir. Web API'si sonucu döndürdüğünde bu medya türlerinden birini kullanarak verileri biçimlendirmeli ve biçimi yanıtın Content-Type üst bilgisinde belirtmelidir.
İstemci bir Accept üst bilgisi belirtmezse, yanıt gövdesi için mantıklı bir varsayılan biçim kullanın. Örneğin, ASP.NET Web API çerçevesi metin tabanlı veriler için varsayılan olarak JSON'dır.
HATEOAS stili gezintiyi ve kaynakların bulunmasını desteklemek için bağlantılar sağlar
HATEOAS yaklaşımı, istemcinin bir başlangıç noktasından itibaren gezinip kaynakları bulmasını sağlar. Bu işlem, URI'ler içeren bağlantılar kullanılarak yapılır; istemci bir kaynağı almak için HTTP GET isteği gönderdiğinde, yanıt bir istemci uygulamanın dolaylı olarak ilgili tüm kaynakları hızlıca bulmasını sağlayan URI’ler içermelidir. Örneğin, e-ticaret çözümünü destekleyen bir web API'sinde müşteri birçok sipariş verebilir. Bir istemci uygulama bir müşterinin ayrıntılarını aldığında yanıt, istemci uygulamanın bu siparişleri alabilmesi için HTTP GET istekleri göndermesini sağlayan bağlantılar içermelidir. Ayrıca HATEOAS stilindeki bağlantılar, her bağlı kaynağın her isteği gerçekleştirmek için ilgili URI ile birlikte desteklediği diğer işlemleri (POST, PUT ve DELETE gibi) açıklamalıdır. Bu yaklaşım API tasarımında daha ayrıntılı olarak açıklanmıştır.
Şu anda HATEOAS uygulamasını yöneten bir standart bulunmamasına karşın aşağıdaki örnekte olası bir yaklaşım gösterilmektedir. Bu örnekte, müşterinin ayrıntılarını bulan bir HTTP GET isteği, söz konusu müşterinin siparişlerine başvuran HATEOAS bağlantılarını içeren bir yanıt döndürür:
GET https://adventure-works.com/customers/2 HTTP/1.1
Accept: text/json
...
HTTP/1.1 200 OK
...
Content-Type: application/json; charset=utf-8
...
Content-Length: ...
{"CustomerID":2,"CustomerName":"Bert","Links":[
{"rel":"self",
"href":"https://adventure-works.com/customers/2",
"action":"GET",
"types":["text/xml","application/json"]},
{"rel":"self",
"href":"https://adventure-works.com/customers/2",
"action":"PUT",
"types":["application/x-www-form-urlencoded"]},
{"rel":"self",
"href":"https://adventure-works.com/customers/2",
"action":"DELETE",
"types":[]},
{"rel":"orders",
"href":"https://adventure-works.com/customers/2/orders",
"action":"GET",
"types":["text/xml","application/json"]},
{"rel":"orders",
"href":"https://adventure-works.com/customers/2/orders",
"action":"POST",
"types":["application/x-www-form-urlencoded"]}
]}
Bu örnekte müşteri verilerini, aşağıdaki kod parçacığında gösterilen Customer sınıfı temsil eder. HATEOAS bağlantıları Links koleksiyon özelliğinde tutulur:
public class Customer
{
public int CustomerID { get; set; }
public string CustomerName { get; set; }
public List<Link> Links { get; set; }
...
}
public class Link
{
public string Rel { get; set; }
public string Href { get; set; }
public string Action { get; set; }
public string [] Types { get; set; }
}
HTTP GET işlemi, depolama alanından müşteri verilerini alıp bir Customer nesnesi oluşturur ve sonra Links koleksiyonunu doldurur. Sonuç bir JSON yanıt iletisi olarak biçimlendirilir. Her bağlantı aşağıdaki alanları içerir:
- Döndürülen nesne ile bağlantı tarafından açıklanan nesne arasındaki ilişki (
Rel). Bu durumdaself, bağlantının nesnenin kendisine bir başvuru olduğunu (nesne odaklı birçok dildeki işaretçiyethisbenzer) veordersilgili sipariş bilgilerini içeren bir koleksiyonun adı olduğunu gösterir. - Açıklanan nesne için URI biçiminde verilen köprü bağlantısı (
Href). - Bu URI’ya gönderilebilen HTTP isteğinin türü (
Action). - İstek türüne bağlı olarak, HTTP isteğinde belirtilmesi gereken veya yanıtta döndürülebilecek her türlü verinin biçimi (
Types).
Örnek HTTP yanıtında gösterilen HATEOAS bağlantıları, bir istemci uygulamanın aşağıdaki işlemleri gerçekleştirebileceğini ifade eder:
- Müşterinin ayrıntılarını getirmek için (tekrar)
https://adventure-works.com/customers/2URI’ya gönderilen HTTP GET isteği. Veriler, XML veya JSON olarak döndürülebilir. - Müşterinin ayrıntılarını değiştirmek için
https://adventure-works.com/customers/2URI’ya gönderilen HTTP PUT isteği. Yeni veriler, yanıt iletisinde x-www-form-urlencoded biçiminde belirtilmelidir. - Müşteri silmek için
https://adventure-works.com/customers/2URI’ya gönderilen HTTP DELETE isteği. İstek, yanıt iletisi gövdesinde ek bilgi beklemez veya veri döndürmez. - Müşteriye ait tüm siparişleri bulmak için
https://adventure-works.com/customers/2/ordersURI’ya gönderilen HTTP GET isteği. Veriler, XML veya JSON olarak döndürülebilir. - Bu müşteri için yeni bir sipariş oluşturmak için URI'ye
https://adventure-works.com/customers/2/ordersbir HTTP POST isteği. Veriler, yanıt iletisinde x-www-form-urlencoded biçiminde belirtilmelidir.
Özel Durumların Yönetimi
Bir operasyon ele alınmayan bir istisna oluşturursa, aşağıdaki noktaları dikkate alın.
Özel durumları yakalama ve istemcilere anlamlı bir yanıt döndürme
Bir HTTP işlemi uygulayan kod, yakalanmayan özel durumların çerçeveye yayılmasına izin vermek yerine kapsamlı özel durum işleme sağlamalıdır. Bir özel durum nedeniyle işlemi tamamlamak mümkün değilse, özel durum yanıt iletisine geri gönderilebilir ancak özel durum nedeninin anlamlı bir açıklamasını içermelidir. Özel durum, her durum için 500 durum kodunu döndürmek yerine uygun HTTP durum kodunu da içermelidir. Örneğin, bir kullanıcı isteği sonucunda kısıtlamayı ihlal eden bir veritabanı güncelleştirmesi yapılırsa (bekleyen siparişleri olan bir müşteriyi silmeye çalışmak gibi), 409 (Çakışma) durum kodunu ve çakışma nedenini belirten bir ileti gövdesini döndürmeniz gerekir. Başka bir koşul isteği gerçekleştirilemez hale getirirse, 400 (Hatalı İstek) durum kodunu döndürebilirsiniz. HTTP durum kodlarının tam listesini W3C web sitesindeki Durum kodu tanımları sayfasında bulabilirsiniz.
Kod örneği farklı koşulları yakalar ve uygun bir yanıt döndürür.
[HttpDelete]
[Route("customers/{id:int}")]
public IHttpActionResult DeleteCustomer(int id)
{
try
{
// Find the customer to be deleted in the repository
var customerToDelete = repository.GetCustomer(id);
// If there is no such customer, return an error response
// with status code 404 (Not Found)
if (customerToDelete == null)
{
return NotFound();
}
// Remove the customer from the repository
// The DeleteCustomer method returns true if the customer
// was successfully deleted
if (repository.DeleteCustomer(id))
{
// Return a response message with status code 204 (No Content)
// To indicate that the operation was successful
return StatusCode(HttpStatusCode.NoContent);
}
else
{
// Otherwise return a 400 (Bad Request) error response
return BadRequest(Strings.CustomerNotDeleted);
}
}
catch
{
// If an uncaught exception occurs, return an error response
// with status code 500 (Internal Server Error)
return InternalServerError();
}
}
İpucu
API'nize sızmaya çalışan bir saldırgan için yararlı olabilecek bilgiler eklemeyin.
Birçok web sunucusu, web API’sine ulaşmadan önce hata koşullarını kendi başına yakalar. Örneğin, bir web sitesi için kimlik doğrulamasını yapılandırırsanız ve kullanıcı doğru kimlik doğrulama bilgilerini sağlayamazsa, web sunucusunun 401 (Yetkisiz) durum koduyla yanıt vermesi gerekir. Bir istemcinin kimliği doğrulandıktan sonra kodunuz, istemcinin istenen kaynağa erişebildiğini doğrulamak üzere kendi denetimlerini gerçekleştirebilir. Bu yetkilendirme başarısız olursa, 403 (Yasak) durum kodunu döndürmeniz gerekir.
Özel durumları tutarlı bir şekilde ele alın ve hata bilgilerini kaydedin.
Özel durumları tutarlı bir şekilde işlemek için web API'sinin tamamında genel bir hata işleme stratejisi uygulayın. Ayrıca her özel durumun tüm ayrıntılarını yakalayan hata günlüğünü de eklemelisiniz; Bu hata günlüğü, web üzerinden istemciler tarafından erişilebilir hale getirilmediği sürece ayrıntılı bilgiler içerebilir.
İstemci tarafı hataları ile sunucu tarafı hatalarını birbirinden ayırt etme
HTTP protokolü, istemci uygulamadan kaynaklanan hataları (HTTP 4xx durum kodları) sunucu üzerindeki bir sorundan kaynaklanan hatalardan (HTTP 5xx durum kodları) ayırt eder. Tüm hata yanıt iletilerinde bu kurala uyduğunuzdan emin olun.
İstemci tarafı veri erişimini en iyi duruma getirme
Web sunucusu ile istemci uygulamalar içerenler gibi dağıtılmış bir ortamda en önemli kaynaklardan birisi ağdır. Özellikle bir istemci uygulama sıklıkla istek gönderiyor veya veri alıyorsa bu durum önemli bir performans sorunu oluşturabilir. Bu nedenle, ağ üzerinden akan trafiği en aza indirmeyi amaçlamanız gerekir. Veri alıp sürdürmek üzere kod uygularken aşağıdaki noktaları göz önünde bulundurun:
İstemci tarafı önbelleğe alma desteği
HTTP 1.1 protokolü, istemcilerde ve Cache-Control üst bilgisi kullanılarak bir isteğin yönlendirildiği ara sunucularda önbelleğe almayı destekler. Bir istemci uygulama tarafından web API’sine HTTP GET isteği gönderildiğinde yanıt, yanıt gövdesindeki verilerin istemci tarafından veya isteğin yönlendirildiği bir ara sunucu tarafından güvenli bir şekilde önbelleğe alınıp alınamayacağını ve süresi dolmadan ve eski kabul edilmeden önce ne kadar süre kaldığını gösteren bir Cache-Control üst bilgisi içerebilir.
Aşağıdaki örnekte bir HTTP GET isteği ve Cache-Control üst bilgisi içeren ilgili yanıt gösterilmektedir:
GET https://adventure-works.com/orders/2 HTTP/1.1
HTTP/1.1 200 OK
...
Cache-Control: max-age=600, private
Content-Type: text/json; charset=utf-8
Content-Length: ...
{"orderID":2,"productID":4,"quantity":2,"orderValue":10.00}
Bu örnekte, Cache-Control üst bilgisi döndürülen verilerin süresinin 600 saniye sonra dolması gerektiğini belirtir ve yalnızca tek bir istemci için uygundur ve diğer istemciler tarafından kullanılan paylaşılan önbellekte depolanmamalıdır ( özeldir). Cache-Control üst bilgisinin private yerine public seçeneğini belirttiğinde veriler ortak bir önbellekte depolanabilir veya no-store seçeneğini belirttiğinde verilerin istemci tarafından önbelleğe alınmaması gerekir. Aşağıdaki kod örneğinde, bir yanıt iletisinde Cache-Control üst bilgisinin nasıl oluşturulacağı gösterilmektedir:
public class OrdersController : ApiController
{
...
[Route("api/orders/{id:int:min(0)}")]
[HttpGet]
public IHttpActionResult FindOrderByID(int id)
{
// Find the matching order
Order order = ...;
...
// Create a Cache-Control header for the response
var cacheControlHeader = new CacheControlHeaderValue();
cacheControlHeader.Private = true;
cacheControlHeader.MaxAge = new TimeSpan(0, 10, 0);
...
// Return a response message containing the order and the cache control header
OkResultWithCaching<Order> response = new OkResultWithCaching<Order>(order, this)
{
CacheControlHeader = cacheControlHeader
};
return response;
}
...
}
Bu kod, özel bir IHttpActionResult sınıfı olan OkResultWithCaching kullanır. Bu sınıf, denetleyicinin önbellek üst bilgisi içeriklerini ayarlamasını sağlar:
public class OkResultWithCaching<T> : OkNegotiatedContentResult<T>
{
public OkResultWithCaching(T content, ApiController controller)
: base(content, controller) { }
public OkResultWithCaching(T content, IContentNegotiator contentNegotiator, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters)
: base(content, contentNegotiator, request, formatters) { }
public CacheControlHeaderValue CacheControlHeader { get; set; }
public EntityTagHeaderValue ETag { get; set; }
public override async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response;
try
{
response = await base.ExecuteAsync(cancellationToken);
response.Headers.CacheControl = this.CacheControlHeader;
response.Headers.ETag = ETag;
}
catch (OperationCanceledException)
{
response = new HttpResponseMessage(HttpStatusCode.Conflict) {ReasonPhrase = "Operation was cancelled"};
}
return response;
}
}
Not
HTTP protokolü ayrıca Cache-Control üst bilgisi için no-cache yönergesini tanımlar. Oldukça kafa karıştırıcı bir şekilde, bu yönerge "önbelleğe alma" anlamına gelmez, "önbelleğe alınan bilgileri döndürmeden önce sunucuyla yeniden doğrulama" anlamına gelir; veriler önbelleğe alınmaya devam edebilir, ancak hala güncel olduğundan emin olmak için her kullanıldığında denetlenebilir.
Önbellek yönetimi, istemci uygulamasının veya ara sunucunun sorumluluğundadır; ancak doğru şekilde uygulanırsa, yakın zamanda zaten alınmış verileri getirme gereksinimini ortadan kaldırarak bant genişliği kazandırabilir ve performansı artırabilir.
Cache-Control üst bilgisindeki max-age değeri yalnızca kılavuz niteliğindedir ve belirtilen süre boyunca ilgili verilerin değişmeyeceğini garanti etmez. Web API’si, verilerin beklenen geçiciliğine bağlı olarak max-age parametresini uygun bir değere ayarlamalıdır. Bu süre sona erdiğinde istemci, nesneyi önbellekten atmalıdır.
Not
Birçok modern web tarayıcısı, isteklere uygun önbellek kontrolü üst bilgilerini ekleyerek ve sonuçların üst bilgilerini açıklandığı gibi inceleyerek istemci tarafındaki önbelleğe alma özelliğini destekler. Ancak bazı eski tarayıcılar, sorgu dizesi içeren bir URL'den döndürülen değerleri önbelleğe almaz. Bu genellikle burada açıklanan protokole göre kendi önbellek yönetimi stratejisini uygulayan özel istemci uygulamaları için bir sorun değildir.
Bazı eski proxy'ler aynı davranışı sergiler ve sorgu dizeleriyle URL’lere göre istekleri önbelleğe almayabilir. Bu sorun, bu tür bir proxy üzerinden bir web sunucusuna bağlanan özel istemci uygulamaları için geçerli olabilir.
Sorgu işlemeyi iyileştirmek için Etag'ler sağlama
İstemci uygulaması bir nesne aldığında, yanıt iletisi bir varlık etiketi (ETag) de içerebilir. ETag, kaynağın sürümünü gösteren opak bir dizedir; Bir kaynak her değiştiğinde ETag de değiştirilir. Bu ETag, istemci uygulama tarafından verilerin bir parçası olarak önbelleğe alınmalıdır. Aşağıdaki kod örneğinde bir HTTP GET isteğine yanıtın parçası olarak ETag ekleme işlemi gösterilmektedir. Bu kod, nesneyi tanımlayan sayısal bir değer oluşturmak için nesnesinin yöntemini kullanır GetHashCode (gerekirse bu yöntemi geçersiz kılabilir ve MD5 gibi bir algoritma kullanarak kendi karmanızı oluşturabilirsiniz):
public class OrdersController : ApiController
{
...
public IHttpActionResult FindOrderByID(int id)
{
// Find the matching order
Order order = ...;
...
var hashedOrder = order.GetHashCode();
string hashedOrderEtag = $"\"{hashedOrder}\"";
var eTag = new EntityTagHeaderValue(hashedOrderEtag);
// Return a response message containing the order and the cache control header
OkResultWithCaching<Order> response = new OkResultWithCaching<Order>(order, this)
{
...,
ETag = eTag
};
return response;
}
...
}
Web API’si tarafından gönderilen yanıt iletisi şuna benzer:
HTTP/1.1 200 OK
...
Cache-Control: max-age=600, private
Content-Type: text/json; charset=utf-8
ETag: "2147483648"
Content-Length: ...
{"orderID":2,"productID":4,"quantity":2,"orderValue":10.00}
İpucu
Güvenlik nedeniyle, kimliği doğrulanmış (HTTPS) bağlantı üzerinden döndürülen hassas verilerin veya verilerin önbelleğe alınmasına izin verme.
Bir istemci uygulama herhangi bir zamanda aynı kaynağı almak için sonraki bir GET isteği düzenleyebilir ve kaynak değiştiyse (farklı ETag’e sahipse), önbelleğe alınan sürüm atılmalı ve yeni sürüm önbelleğe eklenmelidir. Bir kaynak büyükse ve istemciye geri iletmek için önemli miktarda bant genişliği gerektiriyorsa, aynı verileri getirmek için tekrarlanan istekleri verimsiz olabilir. Bu sorunla başa çıkmak için HTTP protokolü bir web API’sinde desteklemeniz gereken GET isteklerini iyileştirmeye yönelik aşağıdaki işlemi tanımlar:
İstemci, bir If-None-Match HTTP üst bilgisinde başvurulan kaynağın o anda önbelleğe alınan sürümü için ETag içeren bir GET isteği oluşturur:
GET https://adventure-works.com/orders/2 HTTP/1.1 If-None-Match: "2147483648"Web API’sindeki GET işlemi, istenen veriler için geçerli ETag’i alır (yukarıdaki örnekte sipariş 2) ve If-None-Match üst bilgisindeki değerle karşılaştırır.
İstenen veriler için geçerli ETag, istek tarafından sağlanan ETag ile eşleşiyorsa kaynak değişmemiştir ve web API’si boş bir ileti ve 304 (Değiştirilmedi) durum kodu ile bir HTTP yanıtı döndürmelidir.
İstenen veriler için geçerli ETag, istek tarafından sağlanan ETag ile eşleşmiyorsa veriler değişmiştir ve web API'sinin ileti gövdesindeki yeni verilerle birlikte bir HTTP yanıtı ve 200 durum kodu (Tamam) döndürmesi gerekir.
İstenen veriler artık mevcut değilse web API'si, 404 (Bulunamadı) durum kodu ile bir HTTP yanıtı döndürmelidir.
İstemci, önbelleği korumak için durum kodunu kullanır. Veriler değişmemişse (304 durum kodu), nesne önbelleğe alınmış olarak kalır ve istemci uygulama nesnenin bu sürümünü kullanmaya devam etmelidir. Veriler değişmişse (200 durum kodu), önbelleğe alınmış nesne atılmalı ve yeni bir nesne eklenmelidir. Veriler artık mevcut değilse (404 durum kodu) nesne önbellekten kaldırılmalıdır.
Not
Yanıt üst bilgisi Cache-Control üst bilgisi no-store değerini içeriyorsa, HTTP durum koduna bakılmaksızın nesne her zaman önbellekten kaldırılmalıdır.
Aşağıdaki kod, FindOrderByID yönteminin If-None-Match üst bilgisini destekleyecek şekilde genişletilmiş halini gösterir. If-None-Match üst bilgisi çıkarıldığında, belirtilen sıranın her zaman alındığını fark edin.
public class OrdersController : ApiController
{
[Route("api/orders/{id:int:min(0)}")]
[HttpGet]
public IHttpActionResult FindOrderByID(int id)
{
try
{
// Find the matching order
Order order = ...;
// If there is no such order then return NotFound
if (order == null)
{
return NotFound();
}
// Generate the ETag for the order
var hashedOrder = order.GetHashCode();
string hashedOrderEtag = $"\"{hashedOrder}\"";
// Create the Cache-Control and ETag headers for the response
IHttpActionResult response;
var cacheControlHeader = new CacheControlHeaderValue();
cacheControlHeader.Public = true;
cacheControlHeader.MaxAge = new TimeSpan(0, 10, 0);
var eTag = new EntityTagHeaderValue(hashedOrderEtag);
// Retrieve the If-None-Match header from the request (if it exists)
var nonMatchEtags = Request.Headers.IfNoneMatch;
// If there is an ETag in the If-None-Match header and
// this ETag matches that of the order just retrieved,
// then create a Not Modified response message
if (nonMatchEtags.Count > 0 &&
String.CompareOrdinal(nonMatchEtags.First().Tag, hashedOrderEtag) == 0)
{
response = new EmptyResultWithCaching()
{
StatusCode = HttpStatusCode.NotModified,
CacheControlHeader = cacheControlHeader,
ETag = eTag
};
}
// Otherwise create a response message that contains the order details
else
{
response = new OkResultWithCaching<Order>(order, this)
{
CacheControlHeader = cacheControlHeader,
ETag = eTag
};
}
return response;
}
catch
{
return InternalServerError();
}
}
...
}
Bu örnek IHttpActionResult adlı ek bir özel EmptyResultWithCaching sınıfını içerir. Bu sınıf, yanıt gövdesi içermeyen bir HttpResponseMessage nesnenin çevresinde sarmalayıcı görevi görür:
public class EmptyResultWithCaching : IHttpActionResult
{
public CacheControlHeaderValue CacheControlHeader { get; set; }
public EntityTagHeaderValue ETag { get; set; }
public HttpStatusCode StatusCode { get; set; }
public Uri Location { get; set; }
public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response = new HttpResponseMessage(StatusCode);
response.Headers.CacheControl = this.CacheControlHeader;
response.Headers.ETag = this.ETag;
response.Headers.Location = this.Location;
return response;
}
}
İpucu
Bu örnekte veriler için ETag değeri, temel alınan veri kaynağından alınan verilerin karması oluşturularak üretilir. ETag başka bir şekilde hesaplanabiliyorsa, işlem daha fazla iyileştirilebilir ve verilerin yalnızca değişmişse veri kaynağından getirilmesi gerekir. Bu yaklaşım özellikle veriler büyükse veya veri kaynağına erişim önemli bir gecikme süresine neden oluyorsa (örneğin, veri kaynağı bir uzak veritabanı ise) yararlıdır.
İyimser Eşzamanlılığı Desteklemek için ETag’ler Kullanma
Önbelleğe alınmış veriler üzerindeki güncellemeleri mümkün kılmak için, HTTP protokolü iyimser bir eşzamanlılık stratejisini destekler. Bir kaynağı getirip önbelleğe aldıktan sonra istemci uygulaması kaynağı değiştirmek veya kaldırmak için bir PUT veya DELETE isteği gönderirse, ETag'e başvuran bir If-Match üst bilgisi içermelidir. Web API’si daha sonra bu bilgileri kullanarak kaynağın alındıktan sonra başka bir kullanıcı tarafından değiştirilip değiştirilmediğini belirleyebilir ve istemci uygulamaya aşağıdaki gibi uygun bir yanıt gönderebilir:
İstemci, bir If-Match HTTP üst bilgisinde başvurulan kaynağın o anda önbelleğe alınan sürümü için kaynağın yeni ayrıntılarını ve ETag içeren bir PUT isteği oluşturur. Aşağıdaki örnekte bir siparişi güncelleştiren PUT isteği gösterilmektedir:
PUT https://adventure-works.com/orders/1 HTTP/1.1 If-Match: "2282343857" Content-Type: application/x-www-form-urlencoded Content-Length: ... productID=3&quantity=5&orderValue=250Web API’sindeki PUT işlemi, istenen veriler için geçerli ETag’i alır (yukarıdaki örnekte sipariş 1) ve If-Match üst bilgisindeki değerle karşılaştırır.
İstenen verilerin geçerli ETag değeri istek tarafından sağlanan ETag ile eşleşiyorsa kaynak değişmemiştir ve başarılı olursa web API'sinin güncelleştirmeyi gerçekleştirmesi ve HTTP durum kodu 204 (İçerik Yok) olan bir ileti döndürmesi gerekir. Yanıt, kaynağın güncelleştirilmiş sürümü için Cache-Control ve ETag üst bilgilerini içerebilir. Yanıt her zaman yeni güncelleştirilmiş kaynağın URI'sine başvuran Location üst bilgisini içermelidir.
İstenen veriler için geçerli ETag, istek tarafından sağlanan ETag ile eşleşmiyorsa, veriler getirildikten sonra başka bir kullanıcı tarafından değiştirilmiştir ve web API'sinin boş ileti gövdesi ve durum kodu 412 (Önkoşul Başarısız) olan bir HTTP yanıtı döndürmesi gerekir.
Güncelleştirilecek kaynak artık mevcut değilse web API'si, 404 (Bulunamadı) durum kodu ile bir HTTP yanıtı döndürmelidir.
İstemci, önbelleği korumak için durum kodunu ve yanıt üst bilgilerini kullanır. Veriler güncelleştirildiyse (durum kodu 204) nesne önbelleğe alınmış olarak kalabilir (Cache-Control üst bilgisi depo belirtmediği sürece) ancak ETag güncelleştirilmelidir. Veriler başka bir kullanıcı tarafından değiştirildiyse (durum kodu 412) veya bulunamazsa (durum kodu 404) önbelleğe alınan nesne atılmalıdır.
Sonraki kod örneğinde Orders denetleyicisinin PUT işlemine ait uygulama gösterilmektedir:
public class OrdersController : ApiController
{
[HttpPut]
[Route("api/orders/{id:int}")]
public IHttpActionResult UpdateExistingOrder(int id, DTOOrder order)
{
try
{
var baseUri = Constants.GetUriFromConfig();
var orderToUpdate = this.ordersRepository.GetOrder(id);
if (orderToUpdate == null)
{
return NotFound();
}
var hashedOrder = orderToUpdate.GetHashCode();
string hashedOrderEtag = $"\"{hashedOrder}\"";
// Retrieve the If-Match header from the request (if it exists)
var matchEtags = Request.Headers.IfMatch;
// If there is an ETag in the If-Match header and
// this ETag matches that of the order just retrieved,
// or if there is no ETag, then update the Order
if (((matchEtags.Count > 0 &&
String.CompareOrdinal(matchEtags.First().Tag, hashedOrderEtag) == 0)) ||
matchEtags.Count == 0)
{
// Modify the order
orderToUpdate.OrderValue = order.OrderValue;
orderToUpdate.ProductID = order.ProductID;
orderToUpdate.Quantity = order.Quantity;
// Save the order back to the data store
// ...
// Create the No Content response with Cache-Control, ETag, and Location headers
var cacheControlHeader = new CacheControlHeaderValue();
cacheControlHeader.Private = true;
cacheControlHeader.MaxAge = new TimeSpan(0, 10, 0);
hashedOrder = order.GetHashCode();
hashedOrderEtag = $"\"{hashedOrder}\"";
var eTag = new EntityTagHeaderValue(hashedOrderEtag);
var location = new Uri($"{baseUri}/{Constants.ORDERS}/{id}");
var response = new EmptyResultWithCaching()
{
StatusCode = HttpStatusCode.NoContent,
CacheControlHeader = cacheControlHeader,
ETag = eTag,
Location = location
};
return response;
}
// Otherwise return a Precondition Failed response
return StatusCode(HttpStatusCode.PreconditionFailed);
}
catch
{
return InternalServerError();
}
}
...
}
İpucu
If-Match üst bilgisinin kullanımı tamamen isteğe bağlıdır ve atlanırsa web API'si her zaman belirtilen sırayı güncelleştirmeye çalışır ve büyük olasılıkla başka bir kullanıcı tarafından yapılan bir güncelleştirmenin üzerine körü körüne yazılır. Kayıp güncellemelerden kaynaklanabilecek sorunları önlemek için daima bir If-Match üst bilgisi sağlayın.
Büyük istekleri ve yanıtları işleme
Bazen bir istemci uygulamasının, boyutu birkaç megabayt (veya daha büyük) olabilen verileri gönderen veya alan istekler göndermesi gerekir. Bu miktarda verilerin aktarılmasını beklemek, istemci uygulamanın yanıt vermemesine neden olabilir. Büyük miktarda veriler içeren istekleri işlemeniz gerektiğinde aşağıdaki noktaları göz önünde bulundurun:
Büyük nesneler içeren istek ve yanıtları en iyi duruma getirme
Bazı kaynaklar büyük nesneler olabilir veya grafik görüntüleri veya diğer ikili veri türleri gibi büyük alanlar içerebilir. Bu kaynakların en iyi şekilde karşıya yüklenmesini ve indirilmesini sağlamak üzere web API’si akışı desteklemelidir.
HTTP protokolü, büyük veri nesnelerini istemciye akışla geri aktarmak için öbekli aktarım kodlama mekanizması sağlar. İstemci büyük bir nesne için bir HTTP GET isteği gönderdiğinde, web API’si yanıtı bir HTTP bağlantısı üzerinden öbek parçaları halinde geri gönderebilir. Yanıttaki verilerin uzunluğu başlangıçta bilinmiyor olabilir (oluşturulabilir), bu nedenle web API'sini barındıran sunucu, Content-Length üst bilgisinin yerine Transfer-Encoding: Chunked üst bilgisini belirten her öbekle bir yanıt iletisi göndermelidir. İstemci uygulama her bir öbeği sırasıyla alıp tam yanıtı oluşturabilir. Sunucu sıfır boyuta sahip bir son öbeği geri gönderdiğinde veri aktarımı tamamlanır.
Tek bir istek, önemli miktarda kaynak tüketen çok büyük bir nesne ile sonuçlanabilir. Akış işlemi sırasında web API'si bir istekteki veri miktarının kabul edilebilir bazı sınırları aştığını belirlerse, işlemi iptal edebilir ve durum kodu 413 (İstek Varlığı Çok Büyük) olan bir yanıt iletisi döndürebilir.
HTTP sıkıştırmasını kullanarak, ağ üzerinden aktarılan büyük nesnelerin boyutunu en aza indirebilirsiniz. Bu yaklaşım, ağ trafiği miktarını ve ilişkili ağ gecikmesini azaltmaya yardımcı olur ancak istemcide ve web API’sini barındıran sunucuda ek işleme gerektirir. Örneğin, sıkıştırılmış verileri almayı bekleyen bir istemci uygulaması bir Accept-Encoding: gzip istek üst bilgisi içerebilir (diğer veri sıkıştırma algoritmaları da belirtilebilir). Sunucu sıkıştırmayı destekliyorsa, ileti gövdesinde ve Content-Encoding: gzip yanıt üst bilgisinde gzip biçiminde tutulan içerikle yanıt vermelidir.
Kodlanmış sıkıştırmayı akışla birleştirebilirsiniz; verileri akışla aktarmadan önce sıkıştırabilir ve ileti üst bilgilerinde gzip içerik kodlaması ile öbekli aktarım kodlamasını belirtebilirsiniz. Internet Information Server gibi bazı web sunucuları, web API'sinin verileri sıkıştırıp sıkıştırmadığına bakılmaksızın HTTP yanıtlarını otomatik olarak sıkıştıracak şekilde yapılandırılabilir.
Zaman uyumsuz işlemleri desteklemeyen istemciler için kısmi yanıtlar sağlamak
Bir istemci uygulama, zaman uyumsuz akışa alternatif olarak büyük nesneler için öbekler halinde açıkça veri isteyebilir. Bu duruma kısmi yanıt adı verilir. İstemci uygulama, nesne hakkında bilgi almak için bir HTTP HEAD isteği gönderir. Web API'si kısmi yanıtları destekliyorsa HEAD isteğine üst bilgi ve nesnenin toplam boyutunu gösteren bir üst bilgi içeren bir Accept-RangesContent-Length yanıt iletisiyle yanıt vermelidir, ancak iletinin gövdesi boş olmalıdır. İstemci uygulama, alınacak bayt aralığını belirtmek üzere bir dizi GET isteği oluşturmak için bu bilgileri kullanabilir. Web API'sinin HTTP durumu 206 (Kısmi İçerik) olan bir yanıt iletisi, yanıt iletisinin gövdesinde yer alan gerçek veri miktarını belirten content-length üst bilgisi ve bu verilerin temsil ettiği nesnenin hangi bölümünü (bayt sayısı gibi 40008000) gösteren bir İçerik Aralığı üst bilgisi döndürmesi gerekir.
HTTP HEAD istekleri ve kısmi yanıtlar API tasarımında daha ayrıntılı olarak açıklanmıştır.
İstemci uygulamalarda gereksiz 100-Continue durum iletileri göndermekten kaçının
Bir sunucuya büyük miktarda veri göndermek üzere olan bir istemci uygulaması, önce sunucunun isteği kabul etmek isteyip istemediğini belirleyebilir. İstemci uygulaması verileri göndermeden önce, verilerin boyutunu gösteren bir Expect: 100-Continue üst bilgisi ve boş bir ileti gövdesi ile bir Content-Length üst bilgisi içeren bir HTTP isteği gönderebilir. Sunucu isteği işlemek için istekliyse, 100 (Devam) HTTP durumunu belirten bir ileti ile yanıt vermelidir. İstemci uygulaması daha sonra devam edebilir ve ileti gövdesindeki veriler de dahil olmak üzere isteğin tamamını gönderebilir.
bir hizmeti Internet Information Services (IIS) kullanarak barındırıyorsanız, HTTP.sys sürücüsü istekleri web uygulamanıza geçirmeden önce Expect: 100-Continue üst bilgilerini otomatik olarak algılar ve işler. Bu durum, bu üst bilgileri uygulama kodunuzda görme olasılığınızın düşük olduğu anlamına gelir ve IIS’nin uygunsuz ya da çok büyük olarak kabul ettiği tüm iletileri filtrelediğini varsayabilirsiniz.
.NET Framework kullanarak istemci uygulamaları oluşturursanız, tüm POST ve PUT iletileri ilk olarak Varsayılan olarak Expect: 100-Continue üst bilgilerine sahip iletiler gönderir. Sunucu tarafında olduğu gibi, işlem .NET Framework tarafından saydam bir şekilde işlenir. Ancak bu işlem, her POST ve PUT isteğinin küçük istekler için bile sunucuya iki gidiş dönüşe neden olmasına neden olur. Uygulamanız büyük miktarda veri içeren istekler göndermiyorsa, istemci uygulamasında nesne oluşturmak ServicePointManager için sınıfını ServicePoint kullanarak bu özelliği devre dışı bırakabilirsiniz. Bir ServicePoint nesnesi, istemcinin bir düzene göre sunucu ile kurduğu bağlantıları ve sunucu üzerindeki kaynakları tanımlayan URI’lerin konak parçalarını işler. Bundan sonra Expect100Continue nesnesinin ServicePoint özelliğini false olarak ayarlayabilirsiniz. İstemci tarafından nesnenin düzeni ve konak parçalarıyla ServicePoint eşleşen bir URI aracılığıyla yapılan sonraki tüm POST ve PUT istekleri Expect: 100-Continue üst bilgileri olmadan gönderilir. Aşağıdaki kod, bir ServicePoint düzeni ve bir http konağı ile URI’lere gönderilen tüm istekleri yapılandıran bir www.contoso.com nesnesini yapılandırma işlemini göstermektedir.
Uri uri = new Uri("https://www.contoso.com/");
ServicePoint sp = ServicePointManager.FindServicePoint(uri);
sp.Expect100Continue = false;
Sınıfın statik Expect100Continue özelliğini ServicePointManager , daha sonra oluşturulan tüm ServicePoint nesneleri için bu özelliğin varsayılan değerini belirtmek üzere de ayarlayabilirsiniz.
Çok sayıda nesne döndürebilecek istekler için sayfalandırma desteği
Bir koleksiyon çok sayıda kaynak içeriyorsa, karşılık gelen URI’ye bir GET isteğinin düzenlenmesi web API’sini barındıran sunucuda performansı etkileyerek önemli işlem yüküyle sonuçlanabilir ve gecikme süresini artıran önemli miktarda ağ trafiği oluşturabilir.
Web API'si, bu durumları ele almak için, istemci uygulamanın istekleri daha kolay yönetilebilir, özelleştirilebilir bloklar (veya sayfalar) halinde daraltmasını sağlayan sorgu dizelerini desteklemelidir. Aşağıdaki kod, denetleyicideki GetAllOrders yöntemini gösterirOrders. Bu yöntem, siparişlerin ayrıntılarını alır. Bu yöntem kısıtlanmamışsa büyük miktarda veri döndürebilir.
limit ve offset parametreleri, veri hacmini daha küçük bir alt kümeye indirgemeye (bu örnekte varsayılan olarak ilk 10 sipariş) yöneliktir:
public class OrdersController : ApiController
{
...
[Route("api/orders")]
[HttpGet]
public IEnumerable<Order> GetAllOrders(int limit=10, int offset=0)
{
// Find the number of orders specified by the limit parameter
// starting with the order specified by the offset parameter
var orders = ...
return orders;
}
...
}
Bir istemci uygulama, https://www.adventure-works.com/api/orders?limit=30&offset=50 URI’sini kullanarak 50. kayıttan başlayarak 30 siparişi almak için bir istek gönderebilir.
İpucu
İstemci uygulamaların 2000 karakterden uzun bir URI ile sonuçlanan sorgu dizeleri belirtmesini önleyin. Birçok web istemcisi ve sunucusu bu kadar uzun URI'leri işleyemez.
Yanıt hızı, ölçeklenebilirlik ve kullanılabilirliği sürdürme
Aynı web API'si dünyanın herhangi bir yerinde çalışan birçok istemci uygulaması tarafından kullanılabilir. Ağır bir yük altında yanıt hızını korumak, yüksek oranda değişen bir iş yükünü destekleyecek şekilde ölçeklenebilir olmak ve kritik iş işlemleri gerçekleştiren istemciler için kullanılabilirliği garanti etmek amacıyla web API’sinin uygulandığından emin olmak gerekir. Bu gereksinimlerin nasıl karşılanacağını belirlerken aşağıdaki noktaları göz önünde bulundurun:
Uzun süreli istekler için asenkron destek sağlama
İşlenmesi uzun sürebilecek bir istek, isteği gönderen istemciyi engellemeden gerçekleştirilmelidir. Web API’si isteği doğrulamak üzere bazı ilk denetimler gerçekleştirebilir, işi gerçekleştirmek üzere ayrı bir görev başlatabilir ve sonra 202 (Kabul Edildi) HTTP kodu ile bir yanıt iletisi döndürebilir. Görev, web API işlemenin bir parçası olarak eşzamanlı çalışabilir veya bir arka plan görevine aktarılabilir. Tam HTTP semantiği ve uygulama kılavuzu için bkz. Zaman Uyumsuz Request-Reply düzeni.
Web API’si ayrıca işleme sonuçlarını istemci uygulamaya döndüren bir mekanizma sağlamalıdır. İstemci uygulamaların işlemenin tamamlanıp tamamlanmadığını düzenli aralıklarla sorgulayıp sonucu almasına yönelik bir yoklama mekanizması sağlayarak ya da işlem tamamlandığında web API’sinin bir bildirim göndermesini sağlayarak bunu gerçekleştirebilirsiniz.
Aşağıdaki yaklaşımı kullanarak, sanal bir kaynak olarak hareket eden bir yoklama URI’si sağlama yoluyla basit bir yoklama mekanizması uygulayabilirsiniz:
- İstemci uygulama, ilk isteği web API’sine gönderir.
- Web API'si, istek hakkındaki bilgileri Azure Table Storage veya Azure Managed Redis içinde tutulan bir tabloda depolar ve bu giriş için büyük olasılıkla genel olarak benzersiz bir tanımlayıcı (GUID) biçiminde benzersiz bir anahtar oluşturur. Alternatif olarak, istek ve benzersiz anahtar hakkındaki bilgileri içeren bir ileti de Azure Service Bus aracılığıyla gönderilebilir.
- Web API'si işlemeyi ayrı bir görev olarak veya Hangfire gibi bir kitaplıkla başlatır. Web API'si, görevin durumunu tabloya Çalışıyor olarak kaydeder.
- Azure Service Bus kullanırsanız, ileti işleme api'den ayrı olarak yapılır ve büyük olasılıkla Azure Functions veya AKS kullanılır.
- Web API'si HTTP durum kodu 202 (Kabul Edildi) ve /polling/{guid} gibi oluşturulan benzersiz anahtarı içeren bir URI içeren bir yanıt iletisi döndürür.
- Görev tamamlandığında, web API'si sonuçları tabloda depolar ve görevin durumunu Tamamlandı olarak ayarlar. Görev başarısız olursa, web API'si hata hakkındaki bilgileri de depolayabilir ve durumu Başarısız olarak ayarlayabilir.
- Olası geçici hataları çözmek için yeniden deneme tekniklerini uygulamayı göz önünde bulundurun.
- Görev çalıştırılırken istemci kendi işlemini gerçekleştirmeye devam edebilir. Daha önce aldığı URI'ye düzenli aralıklarla istek gönderebilir.
- URI'deki web API'si, tablodaki karşılık gelen görevin durumunu sorgular ve bu durumu içeren HTTP durum kodu 200 (Tamam) içeren bir yanıt iletisi döndürür (Çalışıyor, Tamamlandı veya Başarısız). Görev tamamlandıysa veya başarısız olduysa, yanıt iletisi işlemin sonuçlarını veya hata nedeniyle ilgili mevcut tüm bilgileri de içerebilir.
- Uzun süre çalışan işlemin daha fazla ara durumu varsa, NServiceBus veya MassTransit gibi saga desenini destekleyen bir kitaplık kullanmak daha iyidir.
Bildirimleri uygulama seçenekleri şunlardır:
- İstemci uygulamalarına zaman uyumsuz yanıtlar göndermek için bildirim hub'ı kullanma. Daha fazla bilgi için bkz. Azure Notification Hubs kullanarak belirli kullanıcılara bildirim gönderme.
- İstemci ile web API’sini barındıran sunucu arasında kalıcı bir ağ bağlantısı sürdürmek üzere Comet modelini kullanma ve bu bağlantıyı kullanarak sunucudan istemciye iletileri geri gönderme. MSDN dergisi makalesi Microsoft .NET Framework'te Basit Comet Uygulaması Oluşturma örnek bir çözüm açıklamaktadır.
- Kalıcı bir ağ bağlantısı üzerinden verileri web sunucusundan istemciye gerçek zamanlı olarak göndermek için SignalR kullanma. SignalR, ASP.NET web uygulamalarında NuGet paketi olarak kullanılabilir. ASP.NET SignalR web sitesinde daha fazla bilgi bulabilirsiniz.
Her bir isteğin durum bilgisiz olduğundan emin olun
Her isteğin atomik olduğu kabul edilmelidir. Bir istemci uygulama tarafından yapılan istek ile aynı istemcinin gönderdiği sonraki istekler arasında bir bağımlılık olmamalıdır. Bu yaklaşım ölçeklenebilirliği destekler. Web hizmetinin örnekleri birden çok sunucuya dağıtılabilir. İstemci istekleri bu örneklerin herhangi birine yönlendirilebilir ve sonuçlar her zaman aynı olmalıdır. Ayrıca benzer bir nedenle kullanılabilirliği artırır; bir web sunucusu başarısız olursa, sunucu istemci uygulamaları üzerinde hiçbir kötü etki olmadan yeniden başlatılırken istekler başka bir örneğe yönlendirilebilir (Azure Traffic Manager kullanılarak).
DoS saldırılarının olasılığını azaltmak için istemcileri izleyin ve hız sınırlaması uygulayın.
Belirli bir istemci belirli bir süre içinde çok sayıda istekte bulunursa, hizmeti tekeline alabilir ve diğer istemcilerin performansını etkileyebilir. Bu sorunu gidermek için web API’si tüm gelen isteklerin IP adresini izleyerek veya kimliği doğrulanmış her erişimi günlüğe kaydederek istemci uygulamalardan gelen çağrıları izleyebilir. Bu bilgileri, kaynak erişimini sınırlamak için kullanabilirsiniz. Bir istemci tanımlı bir sınırı aşarsa, web API’si 503 (Hizmet Kullanılamıyor) durumu ile bir yanıt iletisi döndürebilir ve istemcinin reddedilmeden sonraki isteği ne zaman gönderebileceğini belirten bir Retry-After üst bilgisi ekleyebilir. Bu strateji, sistemi geciktiren bir istemci kümesinden Hizmet Reddi (DoS) saldırısı olasılığını azaltmaya yardımcı olabilir.
Kalıcı HTTP bağlantılarını dikkatli bir şekilde yönetme
HTTP protokolü, kullanılabilir olduğu durumlarda kalıcı HTTP bağlantılarını destekler. HTTP 1.0 belirtimi, istemci uygulamasının sunucuya yenilerini açmak yerine sonraki istekleri göndermek için aynı bağlantıyı kullanabileceğini belirtmesini sağlayan Connection:Keep-Alive üst bilgisini ekledi. İstemci, ana bilgisayar tarafından tanımlanan bir süre içinde bağlantıyı yeniden kullanmazsa bağlantı otomatik olarak kapanır. Bu davranış, Azure hizmetleri tarafından kullanılan HTTP 1.1'de varsayılandır, bu nedenle iletilere Keep-Alive üst bilgileri eklemeniz gerekmez.
Bağlantının açık tutulması, gecikme süresi ve ağ tıkanıklığını azaltarak yanıt süresini iyileştirmeye yardımcı olabilir, ancak gereksiz bağlantıları gerekenden daha uzun süre açık tutup diğer eşzamanlı istemcilerin bağlantı kurma becerisini sınırlayarak ölçeklenebilirliğe zarar verebilir. Ayrıca, istemci uygulama bir mobil cihazda çalışıyorsa pil ömrünü etkileyebilir; uygulama sunucuya yalnızca ara sıra istek gönderiyorsa, bağlantının açık tutulması pilin daha hızlı boşalmasına neden olabilir. HTTP 1.1 ile bağlantının kalıcı hale gelmesini önlemek için, istemci varsayılan davranışı geçersiz kılacak bir Connection: close başlık içerebilir. Benzer şekilde, bir sunucu çok sayıda istemciyi işlerse, bağlantıyı kapatmak ve sunucu kaynaklarını kaydetmek için yanıt iletilerine bir Connection: close üst bilgi ekleyebilir.
Not
Kalıcı HTTP bağlantıları, bir iletişim kanalının tekrar tekrar kurulmasını önleyerek ağ ek yükünü azaltmak için kullanabileceğiniz isteğe bağlı bir özelliktir. Ancak web API'sinin ve istemci uygulamasının kalıcı bir HTTP bağlantısının kullanılabilirliğine bağlı olmaması gerekir. Comet stili bildirim sistemlerini uygulamak için kalıcı HTTP bağlantıları kullanmayın. Bunun yerine yuvaları veya varsa WebSockets'i İletim Denetimi Protokolü katmanında kullanın. Keep-Alive üst bilgileri, istemci uygulaması bir sunucuyla ara sunucu üzerinden iletişim kurarken sınırlı yararlılığa sahiptir. Yalnızca istemci ile ara sunucu arasındaki bağlantı kalıcı kalır.
Web API’si yayımlama ve yönetme
Bir web API’sini istemci uygulamalar için kullanılabilir hale getirmek üzere web API’sinin bir ana bilgisayar ortamına dağıtılması gerekir. Bu ortam genellikle bir web sunucusudur, ancak başka bir konak süreç türü olabilir. Bir web API'sini yayımlarken aşağıdaki noktaları dikkate almanız gerekir:
- Tüm istekler kimlik doğrulamasından geçmiş ve yetkilendirilmiş olmalı ve uygun düzeyde erişim denetimi uygulanmalıdır.
- Ticari bir web API’si, yanıt süreleriyle ilgili çeşitli kalite garantilerine tabi olabilir. Yük zaman içinde önemli ölçüde farklılık gösterebiliyorsa konak ortamının ölçeklenebilir olduğundan emin olmak önemlidir.
- Para kazanma amacıyla isteklerin ölçülmesi gerekebilir.
- Web API'ye olan trafik akışının düzenlenmesi ve kotalarını tüketmiş belirli istemciler için trafiğin sınırlandırılması gerekebilir.
- Yasal düzenlemeler tüm istek ve yanıtların kaydedilmesini ve denetlenmesini zorunlu kılabilir.
- Kullanılabilirliği sağlamak için web API'sini barındıran sunucunun durumunu izlemek ve gerekirse yeniden başlatmak gerekebilir.
Bu sorunları web API'sinin uygulanmasıyla ilgili teknik sorunlardan ayrıştırabilmek yararlıdır. Bu nedenle, ayrı bir işlem olarak çalışan ve istekleri web API’sine yönlendiren bir façade oluşturmayı düşünün. Cephe, yönetim işlemlerini sağlayabilir ve doğrulanmış istekleri web API’sine iletebilir. Cephe kullanılması aşağıdaki gibi çok sayıda işlevsel avantaj da sağlayabilir:
- Birden çok web API'si için tümleştirme noktası olarak hareket etme.
- Çeşitli teknolojiler kullanılarak oluşturulan istemciler için iletileri dönüştürme ve iletişim protokollerini çevirme.
- Web API’sini barındıran sunucu üzerindeki yükü azaltmak üzere istekleri ve yanıtları önbelleğe alma.
Web API'sini test etme
Bir web API’si, yazılımın herhangi bir kısmı kadar ayrıntılı bir şekilde test edilmelidir. İşlevselliği doğrulamak için birim testleri oluşturmayı düşünmelisiniz.
Bir web API'sinin doğası, düzgün çalıştığını doğrulamak için kendi ek gereksinimlerini getirir. Aşağıdaki durumlara özellikle dikkat etmeniz gerekir:
Doğru işlemleri çağırdığını onaylamak üzere tüm yolları test edin. Bir yol ile bu yola gönderilebilen HTTP yöntemleri (GET, POST, PUT, DELETE) arasında bir uyumsuzluk olduğunu gösterebileceği için, beklenmedik şekilde döndürülen 405 (Yönteme İzin Verilmiyor) HTTP durum koduna özellikle dikkat edin.
Belirli bir kaynağa POST isteği gönderme gibi, bunları desteklemeyen yollara HTTP istekleri gönderin (POST istekleri yalnızca kaynak koleksiyonlarına gönderilmelidir). Bu durumlarda tek geçerli yanıt 405 (İzin Verilmiyor) durum kodu olmalıdır.
Tüm yolların uygun şekilde korunduğunu ve uygun kimlik doğrulama ile yetkilendirme denetimlerine tabi olduğunu doğrulayın.
Not
Kullanıcı kimlik doğrulaması gibi güvenliğin bazı yönleri büyük olasılıkla web API'sinin değil konak ortamının sorumluluğundadır, ancak yine de dağıtım işleminin bir parçası olarak güvenlik testlerini dahil etmek gerekir.
Her bir işlem tarafından gerçekleştirilen özel durum işlemeyi test edin ve istemci uygulamaya uygun ve anlamlı bir HTTP yanıtının geri gönderildiğini doğrulayın.
İstek ve yanıt iletilerinin doğru oluşturulduğunu onaylayın. Örneğin, bir HTTP POST isteği yeni bir kaynağın verilerini x-www-form-urlencoded biçiminde içeriyorsa, karşılık gelen işlemin verileri doğru şekilde ayıkladığını, kaynakları oluşturduğunu ve doğru Location üst bilgisi dahil olmak üzere yeni kaynağın ayrıntılarını içeren bir yanıt döndürdüğünü onaylayın.
Yanıt iletilerindeki tüm bağlantıları ve URI'leri doğrulayın. Örneğin, bir HTTP POST iletisi yeni oluşturulan kaynağın URI'sini döndürmelidir. Tüm HATEOAS bağlantıları geçerli olmalıdır.
Her işlemin farklı giriş birleşimleri için doğru durum kodlarını döndürdüğünden emin olun. Örneğin:
- Bir sorgu başarılı olursa, 200 (Tamam) durum kodunu döndürmelidir
- Kaynak bulunamazsa, işlem 404 (Bulunamadı) HTTP durum kodunu döndürmelidir.
- İstemci bir kaynağı başarıyla silen bir istek gönderirse durum kodu 204 (İçerik Yok) olmalıdır.
- İstemci yeni bir kaynak oluşturan bir istek gönderirse, durum kodu 201 (Oluşturuldu) olmalıdır.
5xx aralığında beklenmedik yanıt durum kodlarına dikkat edin. Bu iletiler genellikle geçerli bir isteği yerine getiremediğini belirtmek üzere ana bilgisayar sunucusu tarafından raporlanır.
Bir istemci uygulamanın belirtebildiği farklı istek üst bilgisi birleşimlerini test edin ve web API’sinin yanıt iletilerinde beklenen bilgileri döndürdüğünden emin olun.
Sorgu dizelerini test edin. Bir işlem isteğe bağlı parametreler (örneğin, sayfalandırma istekleri) alabiliyorsa, parametrelerin farklı birleşimlerini ve sırasını test edin.
Zaman uyumsuz işlemlerin başarıyla tamamlandığını doğrulayın. Web API'sinin büyük ikili nesneler (video veya ses gibi) döndüren istekler için akış desteği varsa, veriler akışı yapılırken istemci isteklerinin engellenmediğinden emin olun. Web API'si uzun süre çalışan veri değiştirme işlemleri için yoklama uygularsa, işlemlerin devam ederken durumlarını doğru bildirdiğini doğrulayın.
Ayrıca, web API’sinin zorlama altında tatmin edici bir şekilde çalışıp çalışmadığını denetlemek için performans testleri oluşturup çalıştırmanız gerekir. Visual Studio Ultimate kullanarak bir web performansı ve yük testi projesi oluşturabilirsiniz.
Azure API Management'i kullanma
Azure web API'sini yayımlamak ve yönetmek için Azure API Management kullanmayı göz önünde bulundurun. Bu özelliği kullanarak, bir veya daha fazla web API’si için cephe olarak davranan bir hizmet oluşturabilirsiniz. Hizmet, Azure portalını kullanarak oluşturabileceğiniz ve yapılandırabileceğiniz ölçeklenebilir bir web hizmetidir. Bu hizmeti kullanarak bir web API’sini aşağıdaki gibi yayımlayıp yönetebilirsiniz:
Web API'sini bir web sitesine, Azure bulut hizmetine veya Azure sanal makineye dağıtın.
API yönetim hizmetini web API'sine bağlayın. Yönetim API’sinin URL’sine gönderilen istekler, web API’sindeki URI’ler ile eşlenir. Aynı API yönetimi hizmeti, istekleri birden fazla web API’sine yönlendirebilir. Bunun yapılması, birden fazla web API’sini tek bir yönetim hizmetinde toplamanıza olanak tanır. Benzer şekilde, farklı uygulamaların kullanabileceği işlevleri kısıtlamanız veya bölmeniz gerekirse aynı web API’sine birden fazla API yönetim hizmetinden başvurulabilir.
Not
HTTP GET isteklerine yönelik yanıtın bir parçası olarak oluşturulan HATEOAS bağlantılarındaki URI'ler, web API'sini barındıran web sunucusuna değil API yönetim hizmetinin URL'sine başvurmalıdır.
Her bir web API’si için web API’sinin işleme giriş olarak eklenebilecek isteğe bağlı parametrelerle birlikte kullanıma sunduğu HTTP işlemlerini belirtin. API yönetim hizmetinin aynı verilere yönelik tekrarlayan istekleri en iyi duruma getirmek üzere web API’sinden alınan yanıtı önbelleğe alıp almayacağını da yapılandırabilirsiniz. Her bir işlemin oluşturabileceği HTTP yanıtlarının ayrıntılarını kaydedin. Bu bilgiler geliştiricilere yönelik belgeler oluşturmak için kullanılır, bu nedenle doğru ve eksiksiz olması önemlidir.
Azure portalı tarafından sağlanan sihirbazları kullanarak işlemleri el ile tanımlayabilir veya bunları WADL veya Swagger biçiminde tanımları içeren bir dosyadan içeri aktarabilirsiniz.
API yönetim hizmeti ile web API’sini barındıran web sunucusu arasındaki iletişime yönelik güvenlik ayarlarını yapılandırın. API management hizmeti şu anda sertifikaları kullanarak Temel kimlik doğrulamasını ve karşılıklı kimlik doğrulamasını ve Açık Yetkilendirme (OAuth) 2.0 kullanıcı yetkilendirmesini destekler.
Ürün oluşturma. Ürün, yayın birimidir; daha önce yönetim hizmetine bağladığınız web API’lerini ürüne eklersiniz. Ürün yayımlandığında web API’leri geliştiriciler için kullanılabilir hale gelir.
Not
Bir ürünü yayımlamadan önce, ürüne erişebilecek kullanıcı grupları tanımlayabilir ve bu gruplara kullanıcı ekleyebilirsiniz. Böylece, web API’sini kullanabilecek geliştiriciler ve uygulamalar üzerinde denetim elde edersiniz. Bir web API'sinin onaylanması gerekiyorsa, geliştiricilerin ürün yöneticisine erişebilmesi için önce bir istek göndermesi gerekir. Yönetici, geliştiriciye erişim verebilir veya erişimi engelleyebilir. Koşulların değişmesi halinde mevcut geliştiriciler de engellenebilir.
Her bir web API'sine yönelik ilkeleri yapılandırın. İlkeler, etki alanları arası çağrılara izin verilip verilmeyeceği, istemci kimliklerinin nasıl doğrulanacağı, XML ile JSON veri biçimleri arasında şeffaf dönüştürme yapılıp yapılmayacağı, belirli bir IP aralığından çağrıların kısıtlanıp kısıtlanmayacağı, kullanım kotaları ve çağrı hızının sınırlanıp sınırlanmayacağı gibi konuları yönetir. İlkeler ürünün tamamına genel olarak, bir üründeki tek bir web API’si için veya bir web API’sindeki tek işlemler için uygulanabilir.
Daha fazla bilgi için API Management belgelerine bakın.
İpucu
Azure, yük devretme ve yük dengeleme uygulamanıza ve farklı coğrafi konumlarda barındırılan bir web sitesinin birden çok örneğinde gecikme süresini azaltmanıza olanak tanıyan Azure Traffic Manager sağlar. Azure Traffic Manager API Management Hizmeti ile birlikte kullanabilirsiniz; API Management Hizmeti, istekleri Azure Traffic Manager aracılığıyla bir web sitesinin örneklerine yönlendirebilir. Daha fazla bilgi için bkz . Traffic Manager yönlendirme yöntemleri.
Bu yapıda, web siteleriniz için özel DNS adları kullanıyorsanız, her web sitesi için uygun CNAME kaydını Azure Traffic Manager web sitesinin DNS adına işaret eden şekilde yapılandırmanız gerekir.
İstemci tarafı geliştiricileri destekleme
İstemci uygulamalar oluşturan geliştiriciler genellikle web API’sine erişim ile ilgili bilgiler ve web hizmeti ile istemci uygulama arasındaki farklı istek ve yanıtları tanımlayan parametreler, veri türleri, dönüş türleri ve dönüş kodları ile ilgili belgeler gerektirir.
Bir web API’sinin REST işlemlerini belgeleme
Azure API Management Hizmeti, bir web API'sinin kullanıma sunduğu REST işlemlerini açıklayan bir geliştirici portalı içerir. Bir ürün yayımlandığında bu portalda görüntülenir. Geliştiriciler, erişime kaydolmak için bu portalı kullanabilir; daha sonra yönetici, isteği onaylayabilir veya reddedebilir. Geliştirici onaylanırsa, geliştirdikleri istemci uygulamalarından gelen çağrıların kimliğini doğrulamak için kullandıkları bir abonelik anahtarı atanır. Bu anahtar her web API çağrısıyla sağlanmalıdır.
Bu portal ayrıca şunları sağlar:
- Ürünün kullanıma sunduğu işlemleri, gerekli parametreleri ve döndürülebilecek farklı yanıtları listeleyen ürün belgeleri. Bu bilgiler, Microsoft Azure API Management Hizmeti kullanılarak web API'sini yayımlama bölümündeki 3. adımda sağlanan ayrıntılardan oluşturulur.
- JavaScript, C#, Java, Ruby, Python ve PHP gibi çeşitli dillerden işlemlerin nasıl çağrıldığını gösteren kod parçacıkları.
- Geliştiricinin üründeki her bir işlemi test etmek ve sonuçları görüntülemek üzere HTTP isteği göndermesini sağlayan geliştirici konsolu.
- Geliştiricinin bulunan her türlü sorunu bildirebileceği bir sayfa.
Azure portalı, kuruluşunuzun markasıyla eşleşecek şekilde stil ve düzeni değiştirmek için geliştirici portalını özelleştirmenizi sağlar.
İstemci SDK’sını uygulama
Bir web API’sine erişmek üzere REST istekleri çağıran bir istemci uygulamanın derlenmesi, her bir isteği oluşturmak için önemli miktarda kod yazıp uygun şekilde biçimlendirmeyi, isteği web hizmetini barındıran sunucuya göndermeyi ve isteğin başarılı olup olmadığını belirlemek ve döndürülen verileri ayıklamak üzere yanıtı ayrıştırmayı gerektirir. İstemci uygulamayı bu sorunlardan uzak tutmak için REST arabirimini sarmalayan ve bu düşük düzeyli ayrıntıları daha işlevsel bir yöntem kümesinde soyutlayan bir SDK sağlayabilirsiniz. İstemci uygulama, çağrıları saydam bir şekilde REST isteklerine dönüştüren ve sonra yanıtları yeniden yöntem dönüş değerlerine dönüştüren bu yöntemleri kullanır. Bu, Azure SDK dahil olmak üzere birçok hizmet tarafından uygulanan yaygın bir tekniktir.
İstemci tarafı SDK oluşturma işlemi tutarlı bir şekilde uygulanması ve dikkatlice test edilmesi gereken önemli bir iştir. Ancak, bu işlemin büyük bölümü mekanik hale getirilebilir ve birçok satıcı bu görevlerin birçoğunu otomatikleştirebilen araçlar sağlar.
Web API'sini izleme
Web API’nizi nasıl yayımlayıp dağıttığınıza bağlı olarak, web API’sini doğrudan izleyebilir veya API Management hizmetinden geçen trafiği analiz ederek kullanım ve sistem durumu bilgilerini toplayabilirsiniz.
Web API'sini doğrudan izleme
Web API'nizden kullanılabilirlik, performans ve kullanım verilerini toplamak ve Application Insights'a göndermek için Azure Monitor OpenTelemetry Distro kullanın. Distro, web API'si buluta dağıtıldığında istekler ve yanıtlar hakkındaki bilgileri izler ve kaydeder. Web API'sini bir Azure web sitesine dağıttığınızda tüm trafik incelenir ve aşağıdaki istatistikler toplanır:
- Sunucu yanıt süresi.
- Sunucu isteklerinin sayısı ve her isteğin ayrıntıları.
- Ortalama yanıt süresi bakımından en yavaş istekler.
- Başarısız olan isteklerin ayrıntıları.
- Farklı tarayıcılar ve kullanıcı aracıları tarafından başlatılan oturum sayısı.
- En sık görüntülenen sayfalar (web API’leri yerine öncelikle web uygulamaları için yararlıdır).
- Web API’sine erişen farklı kullanıcı rolleri.
Bu verileri Azure portalında gerçek zamanlı olarak görüntüleyebilirsiniz. Ayrıca, web API'sinin durumunu izleyen web testleri de oluşturabilirsiniz. Web testi, web API'sinde belirtilen URI'ye düzenli bir istek gönderir ve yanıtı yakalar. Başarılı bir yanıtın tanımını (HTTP durum kodu 200 gibi) belirtebilirsiniz ve istek bu yanıtı döndürmezse bir uyarının yöneticiye gönderilmesini ayarlayabilirsiniz. Gerekirse, yönetici başarısız olması durumunda web API’sini barındıran sunucuyu yeniden başlatabilir.
Daha fazla bilgi için bkz. .NET, Node.js, Python ve Java uygulamaları için
API Management Hizmeti aracılığıyla web API’si izleme
Web API'nizi API Management hizmetini kullanarak yayımladıysanız, Azure portalındaki API Management sayfasında hizmetin genel performansını görüntülemenizi sağlayan bir pano bulunur. Analiz sayfası, ürünün kullanımına ilişkin ayrıntılara inmenizi sağlar. Bu sayfa aşağıdaki sekmeleri içerir:
- Kullanım. Bu sekme, yapılan API çağrılarının sayısı ve zaman içinde bu çağrıları işlemek için kullanılan bant genişliği hakkında bilgi verir. Kullanım ayrıntılarını ürün, API ve işleme göre filtreleyebilirsiniz.
- Sağlık. Bu sekmeyi kullanarak API isteklerinin sonucunu (döndürülen HTTP durum kodları), önbelleğe alma ilkesinin etkinliğini, API yanıt süresini ve hizmet yanıt süresini görüntüleyebilirsiniz. Sistem durumu verilerini de ürün, API ve işleme göre filtreleyebilirsiniz.
- Etkinlik. Bu sekme başarılı çağrı, başarısız çağrı, engellenen çağrı, ortalama yanıt süresi ve her bir ürüne ait yanıt süresi, web API’si ve işlem sayısının metin özetini sağlar. Bu sayfa ayrıca her bir geliştirici tarafından yapılan çağrıların sayısını listeler.
- Bir bakışta. Bu sekme, çoğu API çağrısını yapmaktan sorumlu geliştiriciler dahil olmak üzere performans verilerinin, ürünlerin, web API’lerinin ve bu çağrıları alan işlemlerin bir özeti gösterir.
Belirli bir web API'si veya işlemin bir performans sorununa neden olup olmadığını belirlemek ve gerekirse ana bilgisayar ortamını ölçeklendirip daha fazla sunucu eklemek için bu bilgileri kullanabilirsiniz. Ayrıca bir veya daha fazla uygulamanın orantısız hacimlerde kaynak kullanıp kullanmadığını öğrenebilir ve kota ayarlamak ve çağrı oranlarını sınırlamak üzere uygun ilkeler uygulayabilirsiniz.
Not
Yayımlanmış bir ürünün ayrıntılarını değiştirdiğinizde değişiklikler hemen uygulanır. Örneğin, bir web API’sini içeren ürünü yeniden yayımlamanıza gerek kalmadan web API’sine işlem ekleyebilir ya da kaldırabilirsiniz.
Sonraki adımlar
- ASP.NET Web API OData ASP.NET kullanarak OData web API'si uygulamayla ilgili örnekler ve daha fazla bilgi içerir.
- Web API ve Web API OData'da toplu iş desteğine giriş, OData kullanarak bir web API'sinde toplu işlemlerin nasıl uygulanacağını açıklar.
- Idempotent mesaj işleme, işlenmiş mesaj kimliklerini izlemek ve tekrarlı teslimatı nasıl işleneceğine dair uygulama rehberi sunar.
- W3C web sitesindeki durum kodu tanımları , HTTP durum kodlarının ve açıklamalarının tam listesini içerir.
- WebJobs ile arka plan görevleri çalıştırma, arka plan işlemleri gerçekleştirmek için WebJobs kullanmaya ilişkin bilgi ve örnekler sağlar.
- Azure Notification Hubs kullanıcılara bildirme istemci uygulamalarına zaman uyumsuz yanıtlar göndermek için Azure Bildirim Hub'larının nasıl kullanılacağını gösterir.
- API Management, bir web API'sine denetimli ve güvenli erişim sağlayan bir ürünü yayımlama işlemini açıklar.
- Azure API Management REST API başvurusu özel yönetim uygulamaları oluşturmak için API Management REST API'sinin nasıl kullanılacağını açıklar.
- Traffic Manager yönlendirme yöntemleri web API'sini barındıran bir web sitesinin birden çok örneğinde isteklerin yükünü dengelemek için Azure Traffic Manager nasıl kullanılabileceğini özetler.
- Azure Monitor OpenTelemetry'yi etkinleştirin, Azure Monitor OpenTelemetry Distro'nun telemetriyi Application Insights'a gönderecek şekilde yapılandırılması hakkında ayrıntılı bilgi sağlar.