REST sadece iyimser eşzamanlılık kontrolü ile mi sınırlı?


9

bağlam

REST mimari stilinin vatansızlığı nedeniyle, her bir talebin tamamen tek başına durması, sunucunun müşteri hakkında hiçbir zaman bilgi depolamamasına neden olur.

Bu nedenle, kötümser eşzamanlılık kontrolü uygun değildir, çünkü istemcinin bir kaynak üzerindeki kilidi alması gereken sunucu deposunu gerektirir. Daha sonra Etagbaşlık yardımıyla iyimser eşzamanlılık kontrolü kullanılır . (btw, orada sorduğum gibi /programming/30080634/concurrency-in-a-rest-api )

Sorun

İyimser bir eşzamanlılık kontrol mekanizmasıyla ilgili temel sorun, her zaman, tüm istemcilerin herhangi bir işlemi gerçekleştirmesine izin vermenizdir.

Ve bundan kaçınmak istiyorum REST vatansızlık ilkesini bozmadan. Yani tüm istemciler hiçbir zaman herhangi bir işlem yapamaz.

Soru

Zihnimde, yarı iyimser bir eşzamanlılık kontrol mekanizması ile bu mümkün olabilir:

  • Müşteriler bir jeton isteyebilir
  • Yalnızca bir jeton oluşturulabilir ve sınırlı bir geçerlilik süresi vardır
  • Kaynaklar ( POST veya PUT gibi) üzerinde işlem yapmak için , istemcinin bu belirteci isteğin gövdesinin (veya üstbilgisi?) Bir parçası olarak vermesi gerekir. Jetonu olmayan istemci bu işlemleri yapamaz.

İyimser eşzamanlılık kontrolüne çok benzer, tek fark sadece bir müşterinin bazı işlemleri yapabilmesi (jetonu alan) ... "tüm istemciler tüm işlemleri yapabilir" in tam tersidir.

Bu mekanizma bir REST mimari stiliyle uyumlu mu? Herhangi bir kısıtlamasını bozuyor mu? SO'ya sormayı düşünüyordum, ancak bu daha çok yazılım tasarımı ile ilgili üst düzey bir soru gibi görünüyor.


1
Aslında oldukça basit: TransactionAçıkça bir Kaynak olarak modellemelisiniz .
Jörg W Mittag

Ne değişiyor? Yorumunuzu anladığınızdan emin değilim. İşlem için eşzamanlılık kontrolü yapmıyorum, ancak müşteriye "şimdi ok, kesinlikle kimsenin kaynağı değiştirmeyeceğinden" eminiz (benzersiz bir jeton var gibi).
AilurusFulgens

1
Fark ne? Bir tarafta, "geçerli" sürümü kimin güncellemesine izin verildiğini kontrol etmek için Etag'i kullanırsınız; çakışırsa, sürümünüzü güncellemeniz ve daha sonra güncellemeyi yapmanız gerekir. Diğer tarafta, "kilitleme" mekanizmanız var: birine izin verilir, diğerleri beklemek zorundadır. Kulağa aynı geliyor. İkinci yaklaşımın dezavantajı: 2 istek - 1 kilit için ve 1 güncelleme için. En uygun durumda, Etag-yaklaşımıyla yalnızca bir güncellemeniz olur.
Thomas Junk

Genel olarak eşzamanlılık kontrolü hakkında konuşmak ... "yarışı kaybetti" ikincisi her zaman beklemek zorunda kalacak (sadece farklı nedenlerle, ben buna katılıyorum). İle fark Etag? İle Etagsize operasyonları sona ereceğini olmadığına emindir, size herhangi işlemleri gerçekleştirmek asla asla bir durum olabilir. Bir kilit ile en azından işleminizi yapacağınızdan emin olabilirsiniz. Yani basit bir kilide sahip olmak, "yüksek çatışmaların" ve "nadir çatışmaların" meydana gelebileceği bir ortam arasında sadece bir ortamdır.
Ocak

Yanıtlar:


3

Bir kullanıcı etkileşimini beklerken hiçbir zaman (daha önce hiç olmadığı gibi) herhangi bir kaynağı kilitlememelisiniz.

Bir noktada, bazı kullanıcılarınız uzun bir hafta sonu için bazı hayati kayıtları kilitli olarak çıkaracak.

Ah ama bunun olmasına izin vermeyeceksin çünkü zekice zaman aşımı / kilitlenme çözüm şemasına sahipsin; sonra bir noktada bu korkunç bir şekilde yanlış gidecek ve güzel bir "Widget sipariş edildi" mesajı var bir kullanıcı onun widget neden teslim olmadığını bilmek isteyen yardım masasında çığlık olacak.

Çoğu kişi "üzgünüm başka bir kullanıcı bu bölümü sipariş etti" mesajı ile başa çıkabilir.


Güzelce açıkladın. İlk cümlenizden tamamen ikna olmama rağmen: bir noktada sizden başka kimsenin sipariş veremeyeceğini garanti edersiniz. Ancak, son cümleniz iyi bir özettir, durumun% 99'unda.
AilurusFulgens

1
Belirli bir kullanıcı için bir kaydı kilitlemeniz gerekiyorsa, bunu uygulama düzeyinde yapın. Ya basit bir "LockedBy" özniteliği ya da daha karmaşık bir sürüm ve iş akışı mekanizması ile.
James Anderson

"Uygulama düzeyinde" ile ne demek istiyorsun? Kaynağınıza "LockedBy" özniteliği eklerseniz, istemciyle ilgili bilgileri sunucunuzda depolarsınız. Ya da belki yorumunu anlamadım. Bazı detaylar sağlayabilirseniz harika olurdu!
AilurusFulgens

1
@AilurusFulgens - Veritabanınıza bir LockedBy özniteliği (ve muhtemelen bir LockedOn zaman damgası) eklersiniz. Uygulama kodunuzda, istemci bir güncelleme etkileşimi başlattığında kullanıcı adını ve saatini ayarlarsınız. İstemci bittiğinde ayarlamayı kaldırırsınız - ardından çatışmaları ve zaman aşımlarını vb. Çözmek için bazı iş kuralları üzerinde çalışmanız gerekir
James Anderson

2

Jeton kullanımı API'larda çok yaygındır, bu jetonlar genellikle başlık olarak gönderilir ve net bir yaşam döngüsüne sahiptir. Mesela OAuth'u düşünün.

Programlama dilinizden veya çerçevenizden bağımsız olarak, REST API'leri benzerdir.

Eşzamanlılığı sınırlamak istediğiniz birkaç senaryo düşünebilirim, bunlardan ikisi:

  1. Bir veritabanı satırı gibi aynı kaynakları güncelleyen birden fazla istemci. Örneğin: iki eşzamanlı istek, biri kaydı siler ve diğeri aynı kaydı güncellemeye çalışır. Veritabanınıza ve nasıl ayarladığınıza bağlı olarak, veriler farklı olacağı veya mevcut olmayacağı için kayıtlar veya geçersiz işlem için bir kilit alabilirsiniz.

  2. API ile özel eylemler gerçekleştiren bir süper kullanıcı veya yönetici.


Bu durumlarda ne yapmalı?

  1. Kaynaklara erişimi senkronize etmek için veritabanındaki işlemleri, tek tonları, kilitleri ve benzer mekanizmaları kullanın.

  2. Jeton işe yarayabilir, müşteri hakkında bilgi vermezseniz, jetonun kendisi hakkında daha iyi olacağını düşünüyorum. Bir adımda kullanıcıyı doğrulayabilir ve jetonu atayabilirsiniz. Ardından, jetonun canlı ve geçerli olduğunu doğrulayın. Ek bilgi almak için şifresi çözülebilecek bir jeton kullanın. Bu özel bir jetonsa saklayabilir ve yalnızca bir kerede izin verebilirsiniz. Bu şekilde jetonu doğrularsınız, kullanıcıyı değil.

Umarım bu yardımcı olur.


Evet, bir simgenin ve OAuth mekanizmasının benzerliği hakkında bir cevap bekliyordum. Sonuncusu kimlik doğrulamasına adanmış olsa da. Senaryo 1'in noktasını anlamadım. Bir REST API'de eşzamanlılıkla başa çıkmanın zor kısmı vatansızlık kısıtlamasını korumaktır ... yani sunucu istemci hakkında bilgi depolamaz. Senaryo 2 tam olarak şu anda yaptığım şey! :)
AilurusFulgens

Sorunuzu cevapladım mı?
Pablo Granados

Üzgünüm. Cevabınızı onayladım, çünkü sorunun iyi bir genel görünümünü veriyor, ancak ne yazık ki, imo, gerçekten mücadele etmiyor.
AilurusFulgens

0

REST tek başına çok ilkel. REST ile çalışmaya başlayabilirsiniz, ancak sonunda zengin uygulamanızın birleştirmelerle ilgili sorgulara ve işlemlerle ilgili güncellemelere ihtiyacı olacaktır. Bunları kendi başlarına eklemeye çalışan her geliştirici hataya yatkın ve tutarsız olacaktır. Neyse ki, OData adı verilen ve bunu yapan yeni bir standart var. REST'in üzerine katmanlar ve (1) gezinme özelliklerini (yabancı anahtarları açığa vurmadan) kullanarak basit birleşimlere izin veren sorgu dili ve (2) atomik değişiklik kümeleri içeren toplu işlem sağlar.

(1) https://stackoverflow.com/a/3921423/471129 için buraya bakın ve

Buraya ve (2) için https://stackoverflow.com/a/21939972/471129

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.